1. 程式人生 > >JConsole使用手冊具體解釋

JConsole使用手冊具體解釋

col classes 不支持 發生 配置 設有 變量 san 內存分配

一篇Sun項目主頁上介紹JConsole使用的文章,前段時間性能測試的時候大概翻譯了一下以便學習,今天整理一下發上來。有些地方也不知道怎麽翻,就保留了原文,可能還好理解點。呵呵,水平有限,翻的不好,大家多多包涵。

JConsole畢竟是JDK自帶的東西,功能盡管沒有一些商業軟件那麽強大,可是穩定性好。在大壓力情況下也不會發生什麽問題。並且。提供了相對全面的系統監控功能,還是值得一用的。

JConsole

JConsole是一個基於JMX的GUI工具。用於連接正在執行的JVM,只是此JVM須要使用可管理的模式啟動。假設要把一個應用以可管理的形式啟動,能夠在啟動是設置com.sun.management.jmxremote

。比如,啟動一個能夠在本地監控的J2SE的應用Java2Demo ,需輸入下面命令:

   JDK_HOME/bin/java -Dcom.sun.management.jmxremote -jar JDK_HOME/demo/jfc/Java2D/Java2Demo.jar  JDK_HOME須要是一個含有JDK5.0的文件夾。
 要啟動JConsole,執行   JDK_HOME/bin/jconsole 一個用於連接的對話框將會打開。
 對話框的Local標簽列出了全部本地正在執行的JVM。還包括進程的ID等信息。

技術分享

Figure 2: Local Tab.

JConsole能夠以三種方式連接正在執行的JVM:

  • Local:使用JConsole連接一個正在本地系統執行的JVM,而且執行程序的和執行JConsole的須要是同一個用戶。JConsole使用文件系統的授權通過RMI連接器連接到平臺的MBeanserver上。這樣的從本地連接的監控能力僅僅有Sun的JDK具有
  • Remote:使用以下的URL通過RMI連接器連接到一個JMX代理:

service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi

hostName
填入主機名稱, portNum為JMX代理啟動時指定的端口。

JConsole為建立連接。須要在環境變量中設置mx.remote.credentials來指定username和password從而進行授權。

  • Advanced:使用一個特殊的URL連接JMX代理。

    普通情況使用自己定制的連接器而不是RMI提供的連接器來連接JMX代理,或者是一個使用JDK1.4的實現了JMX和JMX Rmote的應用。


當JConsole成功建立連接。它從連接上的JMX代理處獲取信息。而且以以下幾個標簽頁呈現信息。

  • Summary tab. 監控JVM和一些監控變量的信息。
  • Memory tab. 內存使用信息
  • Threads tab. 線程使用信息
  • Classes tab. 類調用信息
  • VM tab. JVM的信息
  • MBeans tab.全部MBeans的信息

MBeans tab展示了全部以一般形式註冊到JVM上的MBeans。MBeans tab同意你獲取全部的平臺信息,包含那些不能從其它標簽頁獲取到的信息。註意,其它標簽頁上的一些信息也在MBeans這裏顯示。另外,你能夠使用 MBeans標簽管理你自己的應用的MBeans

使用MBeans Tab監控和管理MBean


註冊到JMX代理的平臺或者應用的MBeans。能夠通過MBeans標簽獲取。

比如,內存的MBeans如以下定義

public interface MemoryMXBean {
     public MemoryUsage getHeapMemoryUsage();
     public MemoryUsage getNonHeapMemoryUsage();
     public int         getObjectPendingFinalizationCount();
     public boolean     isVerbose();
     public void        setVerbose(boolean value);
     public void        gc();
 }

內存的MBean包含四個屬性:

  • HeapMemoryUsage. 用於描寫敘述當前堆內存使用情況的僅僅讀屬性
  • NonHeapMemoryUsage. 用於描寫敘述當前的非堆內存的使用情況的僅僅讀屬性
  • ObjectPendingFinalizationCount.用於描寫敘述有多少對象被掛起以便回收。

  • Verbose.用於動態設置GC是否跟著具體的堆棧信息,為一個布爾變量
內存的MBean支持一個操作——GC,此操作能夠發送進行實時的垃圾回收請求。

技術分享

Figure 3: MBeans Tab.

左邊的樹形結構以名字的方式展示了全部MBeans的列表。一個MBean對象的名字由一個域的名字和一串keyword屬性組成。比如,JVM的平臺的MBeans是在“java.lang”域下的一組,而日誌的MBeans則在"java.util.logging"域下。MBean對象的名字在javax.management.ObjectName 規範中定義。

當你在樹中選中一個MBean。屬性,方法,或者通知等一些信息會再右邊顯示出來。假設屬性是可寫的(屬性被標誌為藍色),你能夠進行設置。

你能夠操作在Operations tab中列出的操作。

你也能夠看到由MBean發送出來的通知:默認情況,假設你不訂閱通知的話,JConsole不會收到MBean發生過來的通知。

你能夠點擊"Subscribe"(訂閱)button來堆通知進行定義,而使用"Unsubscribe"button來取消訂閱

技術分享

Figure 4: MBeans Notification.

監控內存


內存標簽頁通過讀取內存系統、內存池、垃圾回收的MBean來獲取對內存消耗、內存池、垃圾回收的情況的統計。


圖:
技術分享


上圖展示了內存隨時間變化的使用情況。有對堆的、非堆的以及特殊內存池的統計。內存池信息能否被獲取。取決與使用的Java虛擬機。以下列表展示了HotSpot虛擬機的內存池情況。


Eden Space (heap): 內存最初從這個線程池分配給大部分對象。
Survivor Space (heap):用於保存在eden space內存池中經過垃圾回收後沒有被回收的對象。
Tenured Generation (heap):用於保持已經在 survivor space內存池中存在了一段時間的對象。


Permanent Generation (non-heap): 保存虛擬機自己的靜態(refective)數據。比如類(class)和方法(method)對象。Java虛擬機共享這些類數據。這個區域被切割為僅僅讀的和僅僅寫的,
Code Cache (non-heap):HotSpot Java虛擬機包含一個用於編譯和保存本地代碼(native code)的內存,叫做“代碼緩存區”(code cache)


具體信息區域給出一些當前線程的信息:
Used :已使用:當前的內存使用量。使用的內存包含全部對象(能被獲取和不能被獲取的)所占用的內存。


Committed :分配量:Java虛擬機保證可以獲取到的內存量。

分配內存(committedmemory)的量可能隨時間改變。Java虛擬機可能釋放部分這裏的內存給系統,對應的分配的內存這時可能少於初始化時分配的給它的量。分配量總數大於或等於已使用的內存量。


Max :內存管理系統能夠使用的最大內存量。

這個值能夠被改變或者不做設定。

假設JVM試圖添加使用的內存到大於分配量(committedmemory)的情況。內存分配可能失敗,即便想使用的內存量小於或者等於最大值(如:系統虛擬內存比較低時)


Usage Threshold The usage threshold of a memory pool. This field will only beshown if the memory pool supports usage threshold.
GC time :垃圾回收使用的總時間和調用垃圾回收的次數。它可能有好幾行,每行代表JVM使用的垃圾回收算法。

(


右下角的棒狀圖表顯示了被JVM的內存池消耗的內存。假設內存使用超過 usage threshold,則棒會變紅。

usagethreshold是用於支持內存檢查的Memory Pool MBean的一個屬性。MemoryPoolMXBean定義了一系列方法用於檢查內存。
public interface MemoryPoolMXBean {
....
// Usage threshold
public long getUsageThreshold();
public void setUsageThreshold(long threshold);
public boolean isUsageThresholdExceeded();
public boolean isUsageThresholdSupported();
// Collection usage threshold
public long getCollectionUsageThreshold();
public void setCollectionUsageThreshold(long threshold);
public boolean isCollectionUsageThresholdSupported();
public boolean isCollectionUsageThresholdExceeded();
}


每種內存池可能有兩種內存初始話支持: usage threshold和collection usage threshold特殊的內存池可能兩種都不支持。

Usage Threshold

usage threshold是內存池中一個可管理的屬性。它使用低負荷的內存監控。設置usage threshold為正值則usage threshold檢查內存池。設置usage threshold為零,則關閉檢查。默認值由JVM設置。JVM一般讓usage threshold在最合適的時候檢查內存,典型的在GC的過程中和某些分配內存的時候。假設JVM發現當前的內存使用超過了usage threshold,它將會把UsageThresholdExceeded屬性設置為true
有些內存池可能不支持usage threshold。你能夠使用UsageThresholdSupported屬性來推斷一個內存池是否支持usage threshold。例 如。一個比較完好(generational garbage collector)的垃圾回收器(如HotSpot的虛擬機),most of the objects are allocated in the young generation,從eden內存池中產生。

eden pool被設計成能夠被裝滿;再eden pool中運行垃圾回收將會釋放他


Collection Usage Threshold

Collection usage threshold是可進行垃圾回收的內存池的一個可配置屬性。JVM堆一個內存池進行 垃圾回收以後,此內存池中的一些內存仍然被那些沒有被回收的對象占用。collection usage threshold僅同意你在垃圾回收後對內存進行檢查。假設JVM發現可用內存超出collection usage threshold,它將會設置CollectionUsageThresholdExceeded屬性為true。


你能夠使用CollectionUsageThresholdSupported屬性來控制內存池釋放支持 collection usage threshold.
usage threshold 和collection usage threshold是MBean標簽中的一組。比如,在左邊的樹形結構中選擇TenuredGen,設置tenured generation memory pool的usage threshold為6m。

例如以下圖所看到的

技術分享

Figure 6: Setting Usage Threshold.

TenuredGen memory pool的內存使用超過6MBytes時,代表 TenuredGen memory pool的柱狀圖將會呈現紅色來代表使用的內存超過了usage threshold。代表堆內存的柱狀圖也將變為紅色。你能夠選擇柱狀圖或者在圖表中指定內存池來查看某個指定內存池的信息。假設把鼠標房子柱狀圖上。將會顯示出內存池的名字

技術分享

Figure 7: Low Memory.

開啟/關閉虛擬機的具體跟蹤

如上所述,內存系統的MBean定義了一個叫做Verbose布爾變量,讓你能動態的打開或關閉具體的GC跟蹤。具體的GC跟蹤。將會在JVM啟動時顯示。默認的HotSpot的GC具體輸出為stdout.

技術分享

Figure 8: Setting Verbose GC.

死鎖檢查

線程標簽頁提供關於應用的線程執行信息

技術分享

Figure 9: Threads Tab.

左下角列出了所以正在執行的線程。假設你在過濾器中輸入一個字符。線程列表將僅顯示線程名字包括你輸入字符的線程。通過點擊某個線程,你能夠獲取這個線程的相關信息。

線程的MBean標簽提供了一些Thread標簽沒有提供實用的操作。

  • findMonitorDeadlockedThreads. 假設發生線程死鎖,能夠通過這個檢查出來。操作返回一組死鎖的線程ID
  • getThreadInfo. 返回線程的信息。包含線程的名稱、堆棧信息,導致當前線程堵塞的鎖,假設有的話,還返回哪兒線程持有這個鎖。和這個線程信息的統計。
  • getThreadCpuTime.返回指定線程消耗的CPU時間。

為使用上面這些屬性,能夠到MBeans標簽下,在MBeans樹上選擇Threading MBean。它列出了當前監控的JVM全部屬性的操作。

技術分享

Figure 10: MBeans Tab Threading.

為檢查你的應用是否進入死鎖(比如,你的應用掛起),你能夠使用findMonitorDeadlockedThreads操作。

技術分享

Figure 11: Find Deadlocked Threads.

一旦你選擇了findMonitorDeadlockedThreadsbutton,將會有一個彈出窗體顯示結果。在上面樣例中,JConsole連接了一個存在3個死鎖線程的演示樣例應用SampleTest。

如上所看到的,檢查出ID為12,10和11的線程死鎖。想查詢很多其它的線程信息,能夠使用getThreadInfo操作。線程的MBean支持getThreadInfo操作的四種形式,

  • 對一個給定的線程ID,給出最深的堆棧情況
  • 堆一系列的線程ID,給出最深的堆棧情況
  • Of a given thread ID with no stack trace.
  • Of an array of thread IDs with no stack trace.
相應死鎖情況,你通常會比較關系堆棧情況。

你能夠在getThreadInfo操作的第一個參數中輸入死鎖的線程ID和你想跟蹤的堆棧深度。

技術分享

Figure 12: ThreadInfo for Thread ID = 12.

雙擊stackTrace屬性的值域將會顯示一個復合對話框。你能夠在堆棧中來回查看。圖13,14顯示了死鎖線程-1的復合對話框中的第一層堆棧和第二層堆棧。

技術分享

Figure 13: Top Frame of the Stack Trace of DeadlockedThread-1.

技術分享

Figure 14: Second Frame of the Stack Trace of DeadlockedThread-1.

線程標簽頁提供了一個友好的界面供查看線程的堆棧。你能夠找到死鎖線程的名字,使用getThreadInfo 查找線程信息。然後又能夠使用線程標簽頁來分析死鎖。

控制日誌等級

Logging MBean定義了LoggerNames屬性,用於描寫敘述日誌名稱。為找到你的應用的日誌。能夠選擇在MBeans樹中java.util.logging 下的Logging MBean。雙擊LoggerNames屬性

技術分享

Figure 15: List of All Logger Names.

Logging MBean也支持三種操作:

  • getParentLoggerName. 返回指定logger的父logger
  • getLoggerLevel. 返回指定logger的日誌等級
  • setLoggerLevel.設置指定logger到一個新的等級
全部三個操作都把日誌名稱作為第一個參數。

技術分享

Figure 16: Setting Log Level.

獲取操作系統資源信息-Sun平臺下的擴展

JDK5.0擴展了操作系統的MBean,以此能夠獲取一下系統資源的信息,如:

  • 處理的CPU
  • 總共的和空暇的物理內存
  • 可獲得的虛擬內存。

    (即保證能夠分配給執行的進程的虛擬內存)

  • 總共的和空暇的交換區
  • 打開的文件總數(僅僅能在Unix下使用)
當打開MBeans標簽下的Operating System MBean,你能夠看到平臺能夠運行的全部屬性和操作。

你能夠監控不論什麽一個屬性隨時間的變化——如。CPU時間-雙擊屬性的值域部分。

技術分享

Figure 17: MBeans Tab OS.

除此之外,VM標簽和Summary標簽提供了操作系統資源的一些信息

管理應用的MBean
被監控的SampleTest應用有它自己的Hello MBean:

com.sun.example:type=Hello
假設CacheSize 屬性發生改變,Hello MBean將會發送一個通知。
你能夠和管理平臺的MBeans一樣使用MBeans標簽頁來管理你的應用的MBean。

比如,當CacheSize 屬性變化的時候你想監控。你首先能夠在 Notification標簽頁中訂閱。假設你改變CacheSize,你能夠看到一個通知被發送。

技術分享

Figure 18: Notifications.

相關信息

  • Monitoring and Management for the Java Platform
  • Monitoring and Management Tools

JProfiler試用手記

JProfiler是一款Java的性能監控工具。能夠查看當前應用的 對象、對象引用、內存、CPU使用情況、線程、線程執行情況(堵塞、等待等),同一時候能夠查找應用內存使用得熱點。即:哪個對象占用的內存比較多;或者CPU熱點。即:哪兒方法占用的較大得CPU資源。我使用的是4.3.2版本號,曾經試用過3**版本號,只是那個bug比較多。easy死。4**版本號穩定多了。

有了上面那些信息對於系統的調優會有非常大幫助。這裏提供有幾篇文章供參考:獲取、介紹,簡單入門,使用JProfiler解決實際問題。這幾篇文章基本介紹了常見東西了,以下說點心得。

  1. JProfiler監控是要消耗系統資源的,所以普通情況下不要用於性能測試時候的監控。
  2. 假設要用於相對大壓力情況下,能夠有選擇的打開監控項。不用全部都打開。主要有兩個,一個是內存監控,打開的情況下能夠查找內存分配熱點。一個是CPU監控,打開的情況下能夠查看CPU使用熱點。

    技術分享
    如圖所看到的,紅筆標註部分。假設兩個都關閉的話,還是能夠跑一定壓力的,同一時候還能夠監控對象數量。

  3. 個 人覺得最好用的(也是用的最多的)是查詢當前的對象的數量。

    數量監控非常重要,假設你使用了單例,那麽你僅僅會看到有一個對象存在,假設多了就說明程序有問題 了。相同,假設應用進行一系列操作。檢查一下該銷毀的對象是否還繼續存在,假設沒有釋放,就得考慮是否存在內存溢出了。

  4. JProfiler還提供了一個比較好的檢查內存溢出得工具。他能夠查找某個對象的引用情況,即:當你發現某個該釋放掉的對象沒有釋放,就能夠看一下哪個實例在引用它,找到了根即找到了溢出點。
    詳細操作例如以下:在 “Memory Views”界面中右鍵選擇你要監控的對象。選擇第一項“Take Heap Snapshot for Selection”,選擇完畢後會進入“Heap Walker”界面,界面以下提供幾個功能,選擇“References”就可以 。如圖:技術分享
  5. JProfiler提供不同的觀察粒度。提供對類的監控、對包的監控、對J2EE組件的監控,同一時候過濾器也比較好用,直接定位你關註的包或類就可以。

  6. JProfiler的監控可能與應用之間存在一定時間差。所以有些時候須要等待刷新,才幹顯示正確系統情況。

JConsole使用手冊具體解釋