1. 程式人生 > >Java性能監控工具:VisualVM

Java性能監控工具:VisualVM

nbsp object 服務器端 stat 生成 pretty authent 重新啟動 args

VisualVM是一款免費的,集成了多個 JDK 命令行工具的可視化工具,它能為您提供強大的分析能力,對 Java 應用程序做性能分析和調優。這些功能包括生成和分析海量數據、跟蹤內存泄漏、監控垃圾回收器、執行內存和 CPU 分析,同時它還支持在 MBeans 上進行瀏覽和操作。本文主要介紹如何使用 VisualVM (JVM 監控)進行性能分析及調優。

自從 JDK 6 Update 7 以後已經作為 Oracle JDK 的一部分,位於 JDK 根目錄的 bin 文件夾下,無需安裝,直接運行即可。

雙擊啟動 Java VisualVM 後可以看到窗口左側 “應用程序 ”欄中有“ 本地 ”、“遠程 ” 、“快照 ”三個項目。

技術分享

“本地 ”下顯示的是在 localhost 運行的 Java 程序的資源占用情況,如果本地有 Java 程序在運行的話啟動 Java VisualVM 即可看到相應的程序名,點擊程序名打開相應的資源監控菜單,以圖形的形式列出程序所占用的 CPU 、 Heap 、 PermGen 、類、線程的 統計信息。

“遠程” 項下列出的遠程主機上的 Java 程序的資源占用情況,但需要在遠程主機上運行 jstatd 守護程序

VisualVM分為 3 類, 本地 它會自動偵測到,並顯示出來.

現在啟動IDEA.

技術分享

雙擊Local 下的任一節點,看到右邊的變化 ,你可以監控 CPU ,內存,類,線程等運行狀況,實時監控服務器性能。

技術分享

右鍵 VisualVM我們可以看到 Thread Dump, Heap Dump

做 Thread Dump 很快,馬上就可以看到結果

技術分享

技術分享

Heap Dump要稍花費一些時間(可以看到當前 heap 裏對象的數量及占用的比例,做 OOM 很好用)

技術分享

二.使用visualvm 遠程監控 JVM

1. 在服務器上安裝 jstatd 組件

jstatd工具是一個RMI服務器應用程序,主要用於監控HotSpot Java 虛擬機的創建與終止,並提供一個接口以允許遠程監控工具附加到本地主機上運行的JVM上。

使用apt-get 命令安裝 openjdk 即可 :

sudo apt-get
install openjdk-6-jdk

2.在服務器上配置 jstatd 的 security policy 文件

jstatd是一個監控 JVM 從創建到銷毀過程中資源占用情況並提供遠程監控接口的 RMI ( Remote Method Invocation ,遠程方法調用)服務器程序,它是一個 Daemon 程序,要保證遠程監控軟件連接到本地的話需要 jstatd 始終保持運行。

jstatd運行需要通過 -J-Djava.security.policy=*** 指定安全策略,因此我們需要在服務器上建立一個指定安全策略的文件jstatd.all.policy ,文件內容如下:

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

3. 修改服務器 hosts 文件中的 IP 地址

要使Java VisualVM 成功連接到遠程服務器上,服務器端應該在 /etc/hosts 文件中把本機地址設為本機的 IP 地址。使用 hostname -i 命令查看,如果顯示的是 127.0.0.1 或者與本機實際 IP 不一致的話,需要把 /etc/hosts 文件中相應的地址改為本機實際 IP 。

4.運行 jstatd 守護程序

jstatd 需要保持一直運行,執行 jstatd 程序,命令如下:

jstatd -J-Djava.security.policy=jstatd.all.policy

5.通過Java VisualVM 連接到服務器監控 Java 程序

在Java VisualVM 程序窗口左側 “ 遠程 ” 項目右鍵選擇 “ 添加遠程主機 ” ,在彈出的對話框中輸入遠程主機的 IP 地址,確認提交後即可看到相應的遠程主機和在上面運行的 Java 程序,連接成功後應該會顯示 Jstatd 及其 PID 。

右擊遠程 選擇添加遠程主機:

技術分享

如果重新指定了jstatd端口,選擇高級設置修改端口,如下圖:默認端口為1099

技術分享

添加後如圖所示:

技術分享

三:Tomcat配置JMX

用hostname -i 查看是否為127.0.0.1,這步非常重要,否則會連接失敗,如果是,必須要配置-Djava.rmi.server.hostname 比如我的配置為 -Djava.rmi.server.hostname=192.168.8.7,而不需要修改hosts文件,修改此文件還可能影響到其他程序。
只需要在TOMCAT_HOME/bin/找到catalina.sh 加上以下參數,重新啟動tomcat就可以了:

JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.8.7  
-Dcom.sun.management.jmxremote.port=8088  
-Dcom.sun.management.jmxremote.ssl=false  
-Dcom.sun.management.jmxremote.authenticate=false"  

註:1. -Dcom.sun.management.jmxremote.port :這個是配置遠程 connection 的端口號的,要確定這個端口沒有被占用

2. -Dcom.sun.management.jmxremote.ssl=false 指定了 JMX 是否啟用 ssl

3. -Dcom.sun.management.jmxremote.authenticate=false 指定了JMX 是否啟用鑒權(需要用戶名,密碼鑒權)

2,3兩個是固定配置,是 JMX 的遠程服務權限的

4. -Djava.rmi.server.hostname :這個是配置 server 的 IP 的

打開JAVA_HOME/bin/下的jvisualvm 或者jconsole 的工具可以直接連接了,如下圖visualvm連接的示意圖:

技術分享

也可以寫個Java類TestJMXClient.java測試下JMX連接是否成功:

import java.util.HashMap;  
import java.util.Map;  
  
import javax.management.MBeanServerConnection;  
import javax.management.remote.JMXConnector;  
import javax.management.remote.JMXConnectorFactory;  
import javax.management.remote.JMXServiceURL;  
  
/** 
 * @author Michael 
 */  
public class TestJMXClient {  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        try {  
            String jndiPath = "jmxrmi";  
            String serverhost = "192.168.8.7";  
            String serverport = "8088";  
            // url=service:jmx:rmi:///jndi/rmi://192.168.8.7:8088/jmxrmi  
            String jmxurl = "service:jmx:rmi:///jndi/rmi://" + serverhost + ":"  
                    + serverport + "/" + jndiPath;  
            System.out.println("jmxurl:" + jmxurl);  
            JMXServiceURL url = new JMXServiceURL(jmxurl);  
            Map<String, Object> enviMap = new HashMap<String, Object>();  
  
            JMXConnector connector = JMXConnectorFactory.connect(url, enviMap);  
  
            MBeanServerConnection mbsc = connector.getMBeanServerConnection();  
            System.out.println("successful connected ");  
            connector.close();  
            System.out.println("close connect");  
        } catch (Exception e) {  
            System.out.println("error");  
            e.printStackTrace();  
        }  
    }  
}  

參考:

http://ihuangweiwei.iteye.com/blog/1219302

http://sjsky.iteye.com/blog/705323

http://www.cnblogs.com/wade-xu/p/4369094.html

Java性能監控工具:VisualVM