开发者学堂课程【线上问题排查利器 Alibaba Arthas(上):JYM 相关命令之:sysenv、vmoption、getstatic、ognl】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/746/detail/13193
JYM 相关命令之:sysenv、vmoption、getstatic、ognl
内容介绍:
一、sysenv
二、vmoption
三、getstatic
四、ognl
五、小结
在这一组准备介绍四个命令,第一个叫 sysenv,第二个叫 vmoption,第三个叫 getstatic,第四个叫 ognl。那么现在分别来介绍每一个命令。
一、sysenv
1.作用:查看当前 JVM 的环境属性
第一个 sysenv,实际上是( System Environment Variables),System 是系统的意思,environment 是环境,various 是变量。顾名思义,其作用是用来查看当前 Java 虚拟机的环境属性。
2.举例
(1)查看所有环境变量: sysenv
(2)查看单个环境变量:sysenv USER
其用法也十分简单,主要是查看,这里进行实际操作。
输入 sysenv(可以按 tab 键进行补全),点击回车,这时可以看到Java 系统的环境变量,在这里,左边一列是键,右边一列是值。整个环境变量,例如路径(PATH)、JAVA_HOME,语言(LANG)以及编码,甚至还有邮箱(mail),以及 SHELL,用户的名字(USER),类所在的路径(CLASSPATH),甚至还有颜色的设置(LS_COLORS),以及主机的名字(HOSTNAME),还有连接的 IP 地址和端口号(SSH_CONNECTION)都会进行显示,包括当前用户的主目录(HOME),所以这是显示所有系统环境的变量。但如果只需要查看其中的一个,就只输入其中的一个的值。例如输入 USER,点击回车,这时就只显示其中的一个环境变量的值,这样看起来也比较简洁。这就是第一条命令。而且其主要功能就是查看,不能够像刚刚提到的 sysprop 命令还有修改功能。这就是第一个命令 system enviroment。
3.效果
[arthas@3174]$ sysenv USER
USER=root
二、vmoption
1.作用:查看,更新 VM 诊断相关的参数
接下来再看第二个命令,第二个命令叫作 vmoption,其中VM意思是虚拟机,Option是选项,顾名思义其含义为虚拟机的选项,主要也是用来查看 Java 虚拟机当中一些相关的参数。
2.举例
(1)查看所有的选项:vmoption
(2)查看制定的选项:Vmoption PrintGCDetails
(3)更新指定的选项:Vmoption PrintGCDetails true
[arthas@3174]$ vmoption PrintGCDetails true
Successfully updated the vm option.
PrintGCDetails=true
跟刚使用 sysenv 类似,如果单独输入 vmoption,那么它显示的是所有虚拟机里面的选项,一列显示键(key),一列显示值(value),一列显示原始的值(origin),最后一列是显示属性是否可以被修改(writeable),这里显示的键,举个例子,在最左边的一列,比如需要打印 Java 的垃圾回收器(printGC),第二列是否(false),说明 printGC 的值为否(false),也可以对其进行修改。上面是其对账的一些信息。
如果想查看其中的一个选项的具体细节,例如想查看 printGC 的细节,输入 printGC Details 并点击回车,这时只输入了其中一个键,就输出键以及它的值。其也是可以修改的,在后面直接输入要修改的值就可以完成修改。例如想把 printGC Details 的值 false 修改成 ture,那直接在后面添加 ture 即可以完成。如实操所示,刚刚值为 false,现在添加 ture 点击回车,然后成功更新虚拟机的选项,并且将其设置为 ture。修改过后再查看的情况下,可以发现如果不带任何参数再来查看,刚刚修改的是这一项值原来是 false,这个时候值已经修改为 ture,这就是第二条命令。
三、getstatic
1.作用:通过 getstatic 命令可以方便的查看类的静态属性
前二条命令都比较简单,没有特别难的地方。接下来再介绍第三条命令 getstatic,翻译成中文是获取静态的东西,在 Java 编程里有一些静态类以及静态方法。通过 getstate ,可以很方便的查看类的一些静态属性,这是在程序的执行过程中实时的获取它的静态属性。
2.语法
它的语法也比较简单,getstatic+类名+属性名。
3.举例
(1)显示 demo.MathGame 类中静态属性 random
(2)getstatic demo.MathGame random
举例,实际上是数学游戏的例子,数学游戏一直运行过程中,运行过程一直在打印,打印其分解质因数,而且现在也在颠覆在加法进程上。这里来查看源码,数学游戏的源码,这里面有一个静态的成员变量(random),这是一个获得随机数的类,这里把它设置成静态的成员。
public class MathGame {
private static Random random=newRandom();
//用于统计生成的不合法变量的个数
public int illegalArgumentCount=0;
Public static void main(String[]args)throws InterruptedException{
MathGame game=new MathGame();
//死循环,每过1秒调用1次下面的方法(不是开启一个线程) while(true){
game.run();
TimeUnit.SECONDS.sleep(timeout:1);
如果想知道 random 在运行过程中每次的值是多少,可以使用 getstatic。实际操作输入 getstatic,第一个参数是类名(demo.Mathgame) ,第二个参数是属性名(random),最后点击回车,可以获取在点击回车瞬间的值,每次执行,其获得的值是会变化的。这时可以看到,上面第一次中其属性名叫 random,下面是它里面 random 类当中的值,因为是用来随机生成一个数,所以这里有一些它的属性,例如下一个 gauss 的值(nextgaussian),以及它种子的偏移量(seedoffset),Double的值(double_unit)等等,这些都属于 random 里面的属性,这里其实不需要深入的了解。只要知道可以通过 random 来获取,比如包括随机种子数(seed)等都可以,而且可以看出来这是一个原子类,不会出现线程安全的问题。可以观察到,实际上随机种子数在每次运行时都是不一样的,这也说明了其可以实时的获取当时 random的值。所以 getstatic 命令,就是获取类的静态属性,但是目前有更好的替代品,也是接下来马上要讲的命令,叫作 ognl。
四、ognl
1.作用:执行 ognl 表达式
Ognl 这条命令是从3.0.5版本后才新增的命令。
2.语法
它其实完全可以代替上面的 getstatic 命令,但是,有一个前提,就是一定需要知道 ognl 的语法规则。这个内容,不是现在课程所探讨的范围,如果有兴趣,可以自行了解,在官网查看(官网地址:
http://commons.apache.org./proper/commons-ognl/language-guide.html),由于网站内容是纯英文内容,英语基础好的可以直接登录官网查看,英语基础不好的,在资料里也提供了一些中文的教程。如果学过 STRUTS2 或者是 SPRAD,就可以知道有很多的地方或者框架都支持 ognl 的语法,要掌握 ognl 的语法才能够使用这条命令,不然就无法使用。
3.参数说明
参数名称 |
参数说明 |
express |
执行的表达式 |
[c:] |
执行表达式的 ClassLoader 的 hashcode,默认值是 SystemClassLoader |
[x] |
结果对象的展开层次,默认值1 |
这里举几个例子,ognl 这个命令有三个参数。第一个参数是 express,也就是在 ognl 后面直接输入表达式,使用单引号引起来,因为往往添加字符串的时候使用双引号,所以这里一般使用单引号。第二个参数是[c:],这个参数,是用来指定类加载器的 hashcode。也就是选择需要使用哪个作为它的类加载器,默认的情况下是使用system classloader 系统的类加载器,还有很多第三方的类加载器,比如 mainland,它本身的框架,工具在启动的时候,本身自带了第三方的类加载器,所以有可能类加载器并不是 Java 的类加载器,所以可以通过[c:]的参数来指定其类加载器是哪一个。第三个参数是[x],这个参数是指执行结果的对象展开的层次,默认值是1,这里不建议展开的层次太深,否则当扩展的很深时,也会影响性能,所以默认值是1。
4.举例
这里举几个例子,通过例子来观察其执行结果。例如刚刚提到显示静态的属性,那该如何调用静态方法?当需要调用静态方法时,可以按照这样的步骤进行。
(1)调用静态函数。ognl '@java.lang.Systemout.printIn("hello")’
第一步先输入 java.lang.system,这个使用频率非常的高,system 是类名,out.println 是方法名,因为此方法是静态方法,所以在前面添加@,相当于直接调用 system.out.println,也就是相当于执行一条 java 程序,或者说执行一条 Java 命令。此时再回到 Linux 当中,在 arthas 中直接输入这条命令,点击回车。当然现在其在执行时,返回的结果的是空,其运行结果实际上就是空。空其实不是指其运行结果,是指其返回值,因为本身 out.println 就没有返回任何东西,所以其返回的是 long,输出的其实也是它的返回值,并不是其执行的结果。执行的结果在这里并不能看到。
(2)获取静态类的静态字段。ogn1'@demo.MathGame@random’
第二步,需要获得静态类的静态字段,getstatic 完全可以用,@符号是表示静态的属性,那么需要获取静态属性,就可以通过这条命令,点击回车。这个效果跟刚刚使用 getstatic 的效果是一样,这段就是其运行结果。
(3)执行多行表达式,赋值给临时变量,返回一个 List。ogn1'#value1=@System@getProperty("java.home),#value2=@System@getProperty("java.runtime.name"),{#value1, #value2}'
第三步,这步稍微复杂一点,这个步骤的代码是:
ognl‘#value1=@system@getproperty(“java.home”),#value2=@system@getproperty(“java.runtime.name”)。下面解释一下,这是调用 system 里面的getproperty,system.get property 也是静态方法。其作用就是用来获取 Java 当中的系统属性,或者 Java.home,并且返回一个值,这里使用临时变量将其保存下来,这是调用的第一条。调用第二条获取 java.runtime.name,也将其作为一个临时的变量保存下来,这两个临时变量保存了以后,再将这两个临时变量放到一个集合(ArrayList)里,所以最终会看到 ArrayList 的运行结果,点击回车,就可以看到 ArrayList 的结果出来。第一个值是字符串,其内容为[/usr/local/jdk1.8.0_221/jre],是 Java home 的值。第二个是 Java runtime 的名字,这样就可以将其做为 list 保存下来。这就是 ognl 命令的作用,该命令非常强大,只要 ognl 语法比较熟悉,那么就可以写出很多复杂的东西,对于诊断程序是非常有用的。
5.效果
五、小结
Jvm相关命令 |
说明 |
sysenv |
查看系统的环境变量,即 JYM 虚拟机系统环境变量的值 |
vmoption |
查看 JYM 虚拟机中的选项和配置,可以修改 |
getstatic |
获取静态的成员变量 |
ognl |
执行 ognl 表达式来实现更复杂的功能 |