使用jvisualvm来远程观察Java程序

jopen 10年前

原文链接:http://blog.iamzsx.me/show.html?id=394002

有时候,我们可能需要远程查看某台机器上的Java程序的运行情况,例如,可能出现了内存泄露,但是只能在某个特定的环境中出现。这时候我们就需要远程观察Java程序的一些执行情况。jvisualvm提供了很方便的界面来帮助我们监控Java程序。
 
这里要介绍的第一种方式是,使用JMX来进行监控。
这种方式要求我们在启动Java程序的时候手动开启jmx remote功能。开启的方式是使用下面的命令行参数启动Java程序:
 
-Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
 
这里<port>是jxm remote使用的端口。大家可以随意改成自己想要的端口。
 
假设我们要在10.2.3.4这台机器上启动一个Java程序foo.jar。那么我们可以使用下面的方式来启动程序。
java -Dcom.sun.management.jmxremote.port=40124 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar foo.jar
 
在这里我们把端口设置成了40124。
 
接下来我们打开jvisualvm,然后在Remote上点击右键,填上我们要监控的服务器host: 10.2.3.4,点击OK。
d1.png
 
接下来,我们在10.2.3.4上面右键选择Add JMX Connection,把Connection信息填成10.2.3.4:40124。这里端口号就是我们之前启动foo.jar时设置的端口号。
 
d2.png
 
接下来,我们就可以查看这个Java程序的信息,并且可以执行诸如Thread Dump或者Heap Dump的操作。
 
d3.png
 
d4.png
 
有一点缺陷是,目前的jvisualvm无法直接把远程的Java程序的heap dump到本地的机器上。当我们点击jvisualvm的heap dump时,只能把heap dump到远程机器上的某台目录,然后还需要我们自己去把heap dump文件拷贝到本地,再用jvisualvm打开来分析。
 
当然有时候,我们在启动程序时,没有开发jmx remote功能,那么这是不是就无法监控了呢?No。Java本身提供了jstat工具来帮助用户查某个Java程序的执行信息。同时,Java还提供了jstatd,来让用户可以远程访问jstat产生的信息。
 
要使用jstatd的时候我们需要先建一个文件jstatd.all.policy,内容如下:
grant codebase "file:${java.home}/../lib/tools.jar" {
   permission java.security.AllPermission;
};
 
接下里我们使用下面的命令来启动jstatd(注意,启动jstatd的用户要求跟启动Java程序的用户一致,不然jstatd就没有权限访问程序的信息了):
 
jstatd -p 40123 -J -Djava.security.policy=jstatd.all.policy
 
这里的40123是jstatd监听的端口,也就是我们要连接时使用的端口,jstatd.all.policy就是我们刚才创建的文件所在的路径。
 
启动之后,我们在10.2.3.4上右键,选择Add jstatd Connection,填上端口号40123,然后点击OK。
d5.png
接下来我们就可以看到这台机器上所有的Java程序了(仅限启动jstatd的用户有权限查看的程序)。
 
当然jstatd有一定的局限性,它只能查看信息,不能执行诸如Thread Dump和Heap Dump等操作。但是jstatd对于我们分析Java内存的状态一般来说是足够了。
 
如果可以的话,最好同时开启JMX和jstatd。这样可以看到更丰富的信息。比如,只有JMX是看不到Main Class和Arguments等信息的。
 
jvisualvm还有很多的功能,善用工具可以让我们事半功倍。