jvisualVm是jdk自帶的可視化監控工具,功能很強大,可安裝各種擴展插件。本篇不打算講解如果使用詳細的功能,只講在windows環境怎麼監控本地和遠端(一般是無界面的linux系統)的java進程。
首先安裝jdk,打開的{JAVA_HOME}/bin目錄,找到jvisualvm.exe程序,雙擊打開,如圖:
如上圖,左邊是本地和遠程的java進程,右邊是該工具的使用指南。
本地的java進程直接顯示在工具裏,如圖筆者本地有兩個java進程,雙擊進入即可。
一般情況下,我們通常是要監控遠程主機的java進程,已排查線上問題,那這時候就要用到遠程監控功能了。這裏主要介紹通過jstatd工具開啓遠程主機訪問接口。
1、在遠程機器上添加權限策略文件
在服務器{JAVA_HOME}/bin目錄建立文件:jstatd.all.policy(名字隨便,符合*.policy即可),
文件內容爲:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
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方式連接遠程主機了
(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監控時遇到的,希望能能幫助到大家!!