Jconsole與Jmx 分析JVM狀況(上)

stacey_sz發表於2016-12-01

JVM平臺提供Mbeans說明

Java2 平臺5.0以上版本,有一組API可以讓Java應用程式和允許的工具監視和管理Java虛擬機器(JVM)和虛擬機器所在的本機作業系統。該組APIjava.lang.management。可以通過這些API可以監控localJVM,同時也可以監控遠端JVM


Java平臺提供瞭如下一些介面用於管理JVM平臺

ClassLoadingMXBeanJava 虛擬機器的類載入系統。

CompilationMXBeanJava 虛擬機器的編譯系統。

MemoryMXBeanJava 虛擬機器的記憶體系統。

ThreadMXBeanJava 虛擬機器的執行緒系統。

RuntimeMXBeanJava 虛擬機器的執行時系統。

OperatingSystemMXBeanJava 虛擬機器在其上執行的作業系統。

GarbageCollectorMXBeanJava 虛擬機器中的垃圾回收器。

MemoryManagerMXBeanJava 虛擬機器中的記憶體管理器。

MemoryPoolMXBeanJava 虛擬機器中的記憶體池。

這些Bean我們從 ManagementFactory類中定義。

訪問Mean的方式有兩種

  1. 直接訪問 MXBean介面

  • 通過靜態工廠方法獲取MXBean例項,從本地訪問正在執行的虛擬機器的MXBean介面。

  • 構造MXBean代理例項,通過呼叫ManagementFactory.newPlatformMXBeanProxy將方法呼叫轉發到給定的MBeanServer。代理通常構造為遠端訪問另一個正在執行的虛擬機器的MXBean

  1. 通過 MBeanServer介面間接訪問(暫時還沒來的及研究)

例:

直接呼叫同一Java虛擬機器內的MXBean中的方法。

 

Java程式碼  收藏程式碼
  1. import java.lang.management.ManagementFactory;  
  2. import java.lang.management.OperatingSystemMXBean;  
  3. import java.lang.management.ThreadMXBean;  
  4. public class JmxLocal {  
  5.     public static void main(String[] args) {      
  6.         OperatingSystemMXBean osbean = ManagementFactory  
  7.                 .getOperatingSystemMXBean();  
  8.         System.out.println(osbean.getArch());//作業系統體系結構  
  9.         System.out.println(osbean.getName());//作業系統名字  
  10.         System.out.println(osbean.getAvailableProcessors());//處理器數目  
  11.         System.out.println(osbean.getVersion());//作業系統版本      
  12.         ThreadMXBean threadBean=ManagementFactory.getThreadMXBean();  
  13.         System.out.println(threadBean.getThreadCount());//匯流排程數    
  14.     }  
  15. }  

使用 MXBean代理。訪問遠端Mbean

 

Java程式碼  收藏程式碼
  1. import java.lang.management.ManagementFactory;  
  2. import java.lang.management.ThreadMXBean;  
  3. import javax.management.MBeanServerConnection;  
  4. import javax.management.remote.JMXConnector;  
  5. import javax.management.remote.JMXConnectorFactory;  
  6. import javax.management.remote.JMXServiceURL;  
  7. public class JmxRemote {  
  8.     public static void main(String[] args) {  
  9.         try {  
  10. // connect to a separate VM's MBeanServer, using the JMX RMI functionality  
  11. JMXServiceURL address = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");  
  12.             JMXConnector connector = JMXConnectorFactory.connect(address);  
  13.             MBeanServerConnection mbs = connector.getMBeanServerConnection();  
  14.             ThreadMXBean threadBean = ManagementFactory.newPlatformMXBeanProxy  
  15.             (mbs, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);  
  16.             System.out.println(threadBean.getThreadCount());//執行緒數量        
  17.         } catch(Exception e){  
  18.             e.printStackTrace();  
  19.         }  
  20.     }  
  21. }  

如果要遠端訪問,被訪問Mbean伺服器首選需要命令列選項啟動遠端虛擬機器,這些選項設定虛擬機器的相關JMX代理偵聽請求的埠,以及起作用的安全級別

如下:

-Dcom.sun.management.jmxremote.port=9999 --指定埠

-Dcom.sun.management.jmxremote.authenticate=false–指定是否需要密碼驗證

-Dcom.sun.management.jmxremote.ssl=false–指定是否使用SSL通訊

例:我要測試下面運用程式

Java程式碼  收藏程式碼
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         Thread thread=new Thread();  
  4.         thread.run();  
  5.         try {  
  6.             thread.sleep(100000);  
  7.         } catch (InterruptedException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.         System.out.println("Success");  
  11.           
  12.     }  
  13. }  

 

 

啟動上面運用程式時在VMarguments加上如上配置

遠端監控Jboss或者weblogic需要配置如下:

Jboss設定:

  • 找到run.bat檔案(linux環境下是run.sh)檔案,有一行

setJAVA_OPTS=%JAVA_OPTS% -Dprogram.name=%PROGNAME%

改成

setJAVA_OPTS=%JAVA_OPTS% -Dprogram.name=%PROGNAME%

-Dcom.sun.management.jmxremote.port=9999-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=false

Weblogic設定:

  • 找到你要監控domain下的startWebLogic.cmd檔案(linux環境下是startWebLogic.sh)檔案、將檔案中

setJAVA_OPTIONS=%SAVE_JAVA_OPTIONS%

改成

set JAVA_OPTIONS=%SAVE_JAVA_OPTIONS%

-Dcom.sun.management.jmxremote.port=9998-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=false


Jconsole使用說明:

啟動jconsole

jconsoleJVM自帶管理Mbean的圖形化介面

環境變數中path中加上

C:\ProgramFiles\Java\jdk1.6.0_01\bin

在控制檯中敲jconsole

一個用於連線的對話方塊將會開啟。對話方塊的本地程式列出本地JVM,中程式的ID

 

 

你會看到兩種方式,一種是本地程式,另外一種連線方式遠端程式

JConsole成功建立連線,它從連線上的JMX代理處獲取資訊,並且以下面幾個標籤頁呈現資訊。

概述tab. 監控JVM主要圖形

記憶體tab. 記憶體使用資訊

執行緒tab. 執行緒使用資訊

tab. 類呼叫資訊

VM摘要 tab.JVM的資訊

MBeanstab. 所有MBeans的資訊

如下圖:

 

MBeanstab展示了所有以一般形式註冊到JVM上的MBeansMBeanstab允許你獲取所有的平臺資訊,包括那些不能從其他標籤頁獲取到的資訊。注意,其他標籤頁上的一些資訊也在MBeans這裡顯示。另外,你可以使用MBeans標籤管理你自己的應用的MBeans。當然你也可以新增其它工具提供的MBeans例如Jbossweblogic連線池資訊

 

 

記憶體管理:

管理記憶體有如下幾個Mbeans

MemoryMXBean Java 虛擬機器記憶體系統

MemoryManagerMXBeanJava 虛擬機器中的記憶體管理器。

MemoryPoolMXBeanJava 虛擬機器中的記憶體池。

MemoryPoolMXBean說明:
註冊到JMX代理的平臺或者應用的MBeans,可以通過MBeans標籤獲取。例如,MemoryMXBean如下面定義

 

Java程式碼  收藏程式碼
  1. public interface MemoryMXBean {  
  2. public MemoryUsage getHeapMemoryUsage();  
  3. public MemoryUsage getNonHeapMemoryUsage();  
  4. public int getObjectPendingFinalizationCount();  
  5. public boolean isVerbose();  
  6. public void setVerbose(boolean value);  
  7. public void gc();  
  8. }  

MemoryMXBean包括四個屬性:

  • HeapMemoryUsage.用於描述當前堆記憶體使用情況的只讀屬性

  • NonHeapMemoryUsage.用於描述當前的非堆記憶體的使用情況的只讀屬性

  • ObjectPendingFinalizationCount.用於描述有多少物件被掛起以便回收。

  • Verbose.用於動態設定GC是否跟著詳細的堆疊資訊,為一個布林變數

記憶體的MBean支援一個操作——GC,此操作可以傳送進行實時的垃圾回收請求。

Heap—NonHeap記憶體說明:

程式執行時儲存資料主要有:暫存器,堆疊,堆,常量儲存,非RAM儲存

速度由高到低。

  • 堆記憶體型別(Heap):Java虛擬機器具有一個,堆是執行時資料區域,所有類例項和陣列的記憶體均從此處分配。

  • 非堆記憶體型別(Non-Heap):Java虛擬機器管理堆之外的記憶體(稱為非堆記憶體)。非堆記憶體包括方法區Java虛擬機器的內部處理或優化所需的記憶體。它儲存每個類結構,如執行時常數池、欄位和方法資料,以及方法和構造方法的程式碼。

 

 

監控記憶體(MemoryPoolMXBean
記憶體標籤頁通過讀取記憶體系統、記憶體池、垃圾回收的MBean來獲取對記憶體消耗、記憶體池、垃圾回收的情況的統計。

主要統計隨時間變化,對堆的、非堆的以及特殊記憶體池的統計如下圖

 

右下角分別綠色豎條分別表示如下(前面三項堆內記憶體,後面三項非堆內記憶體)
EdenSpace (heap)
記憶體最初從這個執行緒池分配給大部分物件。
SurvivorSpace (heap)
用於儲存在edenspace記憶體池中經過垃圾回收後沒有被回收的物件。
TenuredGeneration (heap)
用於保持已經在survivorspace記憶體池中存在了一段時間的物件。
PermanentGeneration (non-heap):
儲存虛擬機器自己的靜態(refective)資料,例如類(class)和方法(method)物件。Java虛擬機器共享這些類資料。這個區域被分割為只讀的和只寫的,
CodeCache (non-heap):HotSpotJava
虛擬機器包括一個用於編譯和儲存原生程式碼(nativecode)的記憶體,叫做“程式碼快取區”(codecache


詳細資訊區域

 

 

 

已經使用:已使用:當前的記憶體使用量。使用的記憶體包括所有物件佔用記憶體

分配: Java虛擬機器保證能夠獲取到的記憶體量。分配記憶體的量可能隨時間改變。Java虛擬機器可能釋放部分這裡的記憶體給系統,相應的分配的記憶體這時可能少於初始化時分配的給它的量。分配量總數大於或等於已使用的記憶體量。

最大值:記憶體管理系統可以使用的最大記憶體量。這個值可以被改變或者不做設定。如果JVM試圖增加使用的記憶體到大於分配量,記憶體分配可能失敗這就是我們在起web服務時常出現記憶體不夠狀況

分配和最大值我們都可以在運用服務啟動時指定

例如:啟動時設定:

-Xms512m -Xmx1024m

-Xms512m為分配量,1024m為最大分配量


垃圾回收(GarbageCollectorMXBean

提供兩個介面

longgetCollectionCount()

longgetCollectionTime()
GC
時間:垃圾回收使用的總時間和呼叫垃圾回收的次數。通過

getCollectionTime()/getCollectionCount()


記憶體池( MemoryPoolMXBean

提供記憶體管理介面,API詳細介紹請看http://gceclub.sun.com.cn/Java_Docs/jdk6/html/zh_CN/api/java/lang/management/MemoryPoolMXBean.html#setCollectionUsageThreshold%28long%29

UsageThreshold(使用量閾值)

usagethreshold是記憶體池中一個可管理的屬性。預設值由JVM設定。可以通過setUsageThreshold方法設定使用量閾值。如果閾值設定為正數,將啟用此記憶體池中的使用量閾值超過檢查。如果使用率閾值設定為零,將禁用此記憶體池的使用量閾值超過檢查。isUsageThresholdSupported()方法可用於確定是否支援此功能。

Java虛擬機器在其最恰當的時候(通常在垃圾回收時)會對記憶體池逐個進行使用量閾值超過檢查。每個記憶體池均維護一個使用量閾值計數,每次Java虛擬機器檢測到記憶體池使用量超過閾值,此值都會加1getUsageThresholdCount()可以取得超過使用量閾值的次數


CollectionUsage Threshold(回收使用量閾值)

<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }-->

Collectionusage threshold是可進行垃圾回收的記憶體池的一個可配置屬性。JVM堆一個記憶體池進行垃圾回收以後,此記憶體池中的一些記憶體仍然被那些沒有被回收的物件佔用。collectionusage threshold僅允許你在垃圾回收後對記憶體進行檢查。如果JVM發現可用記憶體超出collectionusagethreshold,它將會設定CollectionUsageThresholdExceeded屬性為true。你可以使用CollectionUsageThresholdSupported屬性來控制記憶體池釋放支援collectionusage threshold.

<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }-->

usagethreshold collectionusage thresholdJconsoleMBean設定


如果超過設定值,記憶體Tab會出現如下:

 

相關文章