jvisualVm是jdk自带的可视化监控工具,功能很强大,可安装各种扩展插件。本篇不打算讲解如果使用详细的功能,只讲在windows环境怎么监控本地和远端(一般是无界面的linux系统)的java进程。



jvisualvm.exe程序,双击打开,如图:




jvisualvm 连接远程Java java visualvm远程监控_监控工具




如上图,左边是本地和远程的java进程,右边是该工具的使用指南。


本地的java进程直接显示在工具里,如图笔者本地有两个java进程,双击进入即可。


一般情况下,我们通常是要监控远程主机的java进程,已排查线上问题,那这时候就要用到远程监控功能了。这里主要介绍通过jstatd工具开启远程主机访问接口。


1、在远程机器上添加权限策略文件


{JAVA_HOME}/bin目录建立文件:jstatd.all.policy(名字随便,符合* .policy即可), 文件内容为:


"file:${java.home}/../lib/tools.jar"     {     
   
         permission java.security.AllPermission;        
     };


2、开启远程访问功能


    执行命令:

jstatd -J-Djava.security.policy=jstatd.all.policy(后台执行:nohup jstatd -J-Djava.security.policy=jstatd.all.policy &)

    我擦,报错了·····


Could not bind /JStatRemoteHost to RMI Registry
   

        java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:  
  
   

            java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:  
  
   

            java.lang.ClassNotFoundException: sun.jvmstat.monitor.remote.RemoteHost (no security manager: RMI class loader disabled) 
  
   

            at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:419) 
  
   

            at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267) 
  
   

            at sun.rmi.transport.Transport$1.run(Transport.java:177) 
  
   

            at sun.rmi.transport.Transport$1.run(Transport.java:174) 
  
   

            at java.security.AccessController.doPrivileged(Native Method) 
  
   

            at sun.rmi.transport.Transport.serviceCall(Transport.java:173) 
  
   

            at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553) 
  
   

            at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808) 
  
   

            at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667) 
  
   

            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
  
   

            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
  
   

            at java.lang.Thread.run(Thread.java:722) 
  
   

            at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273) 
  
   

            at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251) 
  
   

            at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:377) 
  
   

            at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) 
  
   

            at java.rmi.Naming.rebind(Naming.java:177) 
  
   

            at sun.tools.jstatd.Jstatd.bind(Jstatd.java:57) 
  
   

            at sun.tools.jstatd.Jstatd.main(Jstatd.java:143) 
  
   
jstatd默认启动1099端口,使用netstat -anp | grep 1099 看看端口是不是被占用了!
   

         [ 
    root@VM_200_30 bin]# netstat -anp | grep 1099    
    

         tcp        0      0 :::1099                     :::*                        LISTEN      12674/java  
   
   
2099)   
   
jstatd -J-Djava.security.policy=jstatd.all.policy -p 2099


3、使用本地jvisualVm连接远程主机


进过1、2步骤,最后我们使用window本地的jvisualVm连接配置好的远程主机,这个很简单,不介绍。


但是问题来了,第3部的时候连接配置却怎么也没有看到远程机器的java进程,排查这个问题,请确定你的一下步骤是否成功


(1)服务端机器jstatd服务是否开启:使用jps查看是否有jstatd进程。


(2)确定本地机器是否连接上远程服务器,使用netstat -anp | grep jstatd进程ID查看网络连接,是否有你本地机器IP


(3)jvisualVm远程连接IP和端口是否填写正确


经过以上步骤如果你确定没有问题,那么很可能是是的服务端hosts配置不对,解决办法:


(1)用hostname -i 命令查看返回的IP地址是不是127.0.0.1,如果不是的话则说明是其它原因造成,无需再往下看了,否则进行入第2步。
(2)打开/etc下的hosts文件,将其中的“127.0.0.1   机器名”改成"你机器的IP  机器名"。或者添加一个也可以
           例如:将127.0.0.1  ubuntuServer,改成192.168.1.99  ubuntuServer
(3)重新启动jstatd进程。 如果在本地用jps 192.168.1.99可以看到远程java进程则说明成功了,此时你应该可以在VisualVM中通过jstatd方式连接远程主机了 


好了,以上问题都在我使用jvisualVm监控时遇到的,希望能能帮助到大家!!