Jconsole簡(jiǎn)介:
Jconsole是一個(gè)JMX兼容的監(jiān)視工具。它使用Java虛擬機(jī)的JMX機(jī)制來(lái)提供運(yùn)行在Java平臺(tái)的應(yīng)用程序的性能與資源耗費(fèi)信息。
監(jiān)控進(jìn)程使用方法如下:
由于JConsole監(jiān)控需要使用JMX代理技術(shù),因此在啟動(dòng)應(yīng)用程序的參數(shù)中添加以下幾個(gè)參數(shù):
-Djava.rmi.server.hostname=192.168.1.80
-Dcom.sun.management.jmxremote.port=8089
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
配置完以上參數(shù)后,本地啟動(dòng)JConsole后,選擇相應(yīng)的進(jìn)程名稱,點(diǎn)擊連接后,就可監(jiān)控了。
關(guān)于JMX的介紹:
http://www./?uid-115295-action-viewspace-itemid-804845
其他使用:
Jconsole界面:
Jconsole界面由以下六個(gè)選項(xiàng)卡組成:
Summary選項(xiàng)卡:顯示JVM和被監(jiān)視值的匯總信息
Memory選項(xiàng)卡:顯示內(nèi)存使用信息。
Threads選項(xiàng)卡:顯示線程使用信息。
Classes選項(xiàng)卡:顯示類(class)加載信息。
MBeans選項(xiàng)卡:顯示MBeans信息
VM選項(xiàng)卡:顯示JVM信息。
以下是詳細(xì)介紹:
查看匯總信息:
Summary選項(xiàng)卡顯示了關(guān)于線程使用、內(nèi)存消耗和class加載的一些關(guān)鍵監(jiān)視信息,以及JVM和操作系統(tǒng)的信息。

Summary
Uptime:JVM已運(yùn)行時(shí)長(zhǎng)。
Total compile time:花費(fèi)在即時(shí)編譯(JIT compilation)中的時(shí)間。
Process CPU time:JVM花費(fèi)的總CPU時(shí)間。
Threads
Live threads:當(dāng)前活動(dòng)的daemon線程加non-daemon線程數(shù)量。
Peak:自JVM啟動(dòng)后,活動(dòng)線程峰值。
Daemon threads:當(dāng)前活動(dòng)的Daemon線程數(shù)量。
Total started:自JVM啟動(dòng)后,啟動(dòng)的線程總量(包括daemon,non-daemon和終止了的)
Memory
Current heap size:堆(heap)占用的內(nèi)存量,以K為單位。
Committed memory:為堆分配的內(nèi)存總量
Maximum heap size:堆占用的最大內(nèi)存量。
Objects pending for finalization:等待析構(gòu)(finalization)的對(duì)象數(shù)量。
Garbage collector information:GC信息,擺闊垃圾回收器名稱,已執(zhí)行的垃圾回收次數(shù)和執(zhí)行垃圾回收總耗時(shí)。
Classes
Current classes loaded:當(dāng)前被加載到內(nèi)存的classes數(shù)量
Total classes loaded:自JVM啟動(dòng)后被加載到內(nèi)存的classes總量,包括后來(lái)卸載的。
Total classes unloaded:自JVM啟動(dòng)后,從內(nèi)存卸載的classes總量。
Operating System:
Total physical memory:物理內(nèi)存總量
Free physical memory:物理內(nèi)存空閑量
Committed virtual memory:為運(yùn)行中的進(jìn)程分配的虛擬內(nèi)存總量
監(jiān)視內(nèi)存消耗:
Memory選項(xiàng)卡提供了內(nèi)存消耗和內(nèi)存池信息。

以上圖表顯示了JVM的內(nèi)存使用和時(shí)間的對(duì)應(yīng)關(guān)系,包括heap和non-heap內(nèi)存以及指定的(specific)內(nèi)存池。內(nèi)存池種類與具體使用的JVM有關(guān),以HotSpot JVM為例,內(nèi)存池有:
l Eden Space(heap):大多數(shù)對(duì)象初始化時(shí)從Eden Space池分配內(nèi)存,即是存在于此池中
l Survivor Space(heap):此池包含的對(duì)象是那些原先在eden space中,但是已經(jīng)經(jīng)歷過(guò)垃圾回收而仍然存在的對(duì)象。
l Tenured Generation(heap):在surviver space中已經(jīng)存在了一段時(shí)間之后的對(duì)象會(huì)移動(dòng)到這個(gè)池中。
l Permanent Generation(non-heap):包含虛擬機(jī)自身的所有反射數(shù)據(jù)。比如class和mothod對(duì)象。對(duì)于使用classdatasharing的JVM,這一代分為只讀和讀寫(xiě)兩個(gè)區(qū)域。
Code Cache (non-heap):HotSpot JVM也包含一個(gè)“代碼緩存”,是編譯和存儲(chǔ)本地代碼所占用的內(nèi)存。
查看關(guān)于內(nèi)存池的詳細(xì)信息:Garbage Collection.
Detail區(qū)域顯示了幾種當(dāng)前內(nèi)存度量:
lUsed:當(dāng)前使用的內(nèi)存總量。使用的內(nèi)存總量是指所有的對(duì)象占用的內(nèi)存,包括可達(dá)和不可達(dá)的對(duì)象。
lCommitted:JVM可使用的內(nèi)存量。Committed內(nèi)存數(shù)量可能隨時(shí)間變化而變化。JAVA虛擬機(jī)可能將某些內(nèi)存釋放,還給操作系統(tǒng),committed內(nèi)存可能比啟動(dòng)時(shí)初始分配的內(nèi)存量要少。Committed內(nèi)存總是大于等于used內(nèi)存。
lMax:內(nèi)存管理可用的最大內(nèi)存數(shù)量。此值可能改變或者為未定義。如果JVM試圖增加使用內(nèi)存(used memory)超出了committed內(nèi)存,那么即時(shí)使用內(nèi)存小于或者等于最大內(nèi)存(比如系統(tǒng)虛擬內(nèi)存較低),內(nèi)存分配仍可能失敗。
右下角的圖表顯示了內(nèi)存池在heap和non-heap消耗的內(nèi)存量。當(dāng)內(nèi)存使用超出了內(nèi)存使用閥值時(shí),柱狀圖會(huì)變紅。你可以通過(guò)設(shè)置MemoryMXBean的一個(gè)屬性來(lái)調(diào)整內(nèi)存占用閥值。
Heap and Non-heap內(nèi)存
JVM管理兩種內(nèi)存:heap和non-heap內(nèi)存,兩種內(nèi)存都是在JVM啟動(dòng)時(shí)建立。
Heap memory是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,用于JVM為所有對(duì)象實(shí)例和隊(duì)列分配的內(nèi)存。Heap可能為固定植或者可變值。垃圾收集器是一個(gè)用于回收對(duì)象占用的heap內(nèi)存的自動(dòng)化內(nèi)存管理系統(tǒng)。
Non-heap memory 包含一個(gè)在所有線程共享的方法區(qū)域(method area)和內(nèi)部進(jìn)程或JVM優(yōu)化所需的內(nèi)存。它存儲(chǔ)了每一個(gè)類的結(jié)構(gòu),比如運(yùn)行常量池,字段和方法數(shù)據(jù),構(gòu)造函數(shù)和方法的代碼。方法區(qū)域邏輯上是 heap的一部分,但是依賴于實(shí)現(xiàn),JVM可能不進(jìn)行垃圾收集或壓縮。像heap一樣,方法區(qū)域可能為固定或可變大小。方法區(qū)域所需要的內(nèi)存沒(méi)有必要是連 續(xù)的。
除了方法區(qū)域之外,一個(gè)JVM實(shí)現(xiàn)的內(nèi)部進(jìn)程或優(yōu)化所需的內(nèi)存也屬于non-heap內(nèi)存。比如JIT編譯器為了提高性能而用于存儲(chǔ)本地機(jī)器碼所需的內(nèi)存。
內(nèi)存池和內(nèi)存管理
內(nèi)存池(Memory pools)和內(nèi)存管理器是JVM內(nèi)存管理系統(tǒng)的關(guān)鍵部分
一個(gè)內(nèi)存池(memory pool)代表JVM管理的一塊內(nèi)存區(qū)域。JVM擁有最少一個(gè)內(nèi)存池,JVM在運(yùn)行中可能創(chuàng)建或刪除內(nèi)存池。一個(gè)內(nèi)存池可以屬于heap內(nèi)存或者non-heap內(nèi)存。
內(nèi)存管理器(memory manager)管理一個(gè)或多個(gè)內(nèi)存池。垃圾回收其是一種負(fù)責(zé)回收被不可打?qū)ο笳加玫膬?nèi)存的內(nèi)存管理器。一個(gè)JVM可以擁有一個(gè)或者多個(gè)內(nèi)存管理器。JVM在運(yùn)行中可能增加或刪除內(nèi)存管理器。一個(gè)內(nèi)存池可以被多于一個(gè)內(nèi)存管理器管理。
垃圾收集:
垃圾收集(GC)是指JVM釋放那些被無(wú)引用對(duì)象占用的內(nèi)存空間。它通常認(rèn)為那些有活動(dòng)引用的對(duì)象是“活”對(duì)象,而那些沒(méi)有引用或不可達(dá)的對(duì)象為“死”對(duì)象”。垃圾收集是釋放被死對(duì)象占用的內(nèi)存的過(guò)程。GC的算法和參數(shù)對(duì)性能有巨大的影響。
HotSpot VM垃圾收集器使用 分代垃圾收集(generational garbage collection)。分代GC利用了大多數(shù)程序中,從經(jīng)驗(yàn)看有如下特點(diǎn):
很多對(duì)象有一個(gè)很短的生存期(比如迭代器iterators、本地變量)
某些對(duì)象擁有很長(zhǎng)的生存期(比如高層持久化對(duì)象)
所 以,分代的GC將內(nèi)存劃分為代(generations)并且賦予每一個(gè)內(nèi)存池。當(dāng)一代用盡了分配的內(nèi)存,VM會(huì)在那個(gè)內(nèi)存池進(jìn)行一次局部 (partial)的垃圾收集(或者叫minor collection)來(lái)收集被死對(duì)象占用的內(nèi)存。局部垃圾收集比全垃圾收集(full GC)快的多。
HotSpot VM定義了2代:young generation (有時(shí)叫做nursery)和old generation。Young generation由一個(gè)eden space和兩個(gè)survivor spaces組成。最初,VM將所有的對(duì)象放入eden space,大多數(shù)對(duì)象死在那里~~~,當(dāng)VM運(yùn)行了一次minor GC,VM將剩余的對(duì)象從eden space移動(dòng)到某個(gè)survivor space中。然后VM將那些在survivor spaces中生存了足夠長(zhǎng)時(shí)間的對(duì)象移動(dòng)到位于old generation中的tenured spaces。當(dāng)tenured spaces滿了以后,將發(fā)生一次full GC,full GC涉及到所有存活的對(duì)象,因此比較慢。Permanent generation保存了所有的虛擬機(jī)自身的反射數(shù)據(jù),比如class和method objects
默認(rèn)情況下代的排列類似于下圖:

如同下文鏈接中說(shuō)明的,如果垃圾收集器成為瓶頸,你可以通過(guò)自定義代大小來(lái)提高性能。使用jconsole可以發(fā)現(xiàn)你的性能情況對(duì)垃圾收集器參數(shù)的敏感程度。詳細(xì)情況見(jiàn):
Tuning Garbage collection with the 5.0 HotSpot VM
監(jiān)視線程使用:
線程選項(xiàng)卡提供了關(guān)于線程使用的信息。

左下角列出的為所有的活動(dòng)線程。如果你在過(guò)濾(filter)對(duì)話框輸入字符串,那么線程列表將盡顯示那些包含你輸入字符串的線程。在線程列表上點(diǎn)擊線程名,可以顯示在右側(cè)顯示縣城信息,包括線程名,狀態(tài)和調(diào)用堆棧。
圖表顯示了活動(dòng)線程/時(shí)間。有三行內(nèi)容:
Magenta:線程總數(shù)
Red:峰值線程數(shù)
Blue:活動(dòng)線程數(shù)。
關(guān)于線程、daemon線程詳細(xì)信息,請(qǐng)查看鏈接:java.lang.Thread
監(jiān)視Class加載:
Classes選項(xiàng)卡顯示了關(guān)于class loading的信息:

圖表顯示了 類加載/時(shí)間
紅線是類加載總數(shù)(包括后來(lái)卸載的)
藍(lán)線表示當(dāng)前的類加載數(shù)量。
選項(xiàng)卡底部的Detail節(jié)顯示了自JVM啟動(dòng)后類加載的總量,當(dāng)前加載量和卸載量。
監(jiān)視和管理MBeans:
MBean選項(xiàng)卡顯示了所有在platform. MBeanserver上注冊(cè)的MBeans的信息。

左邊的樹(shù)形結(jié)構(gòu)顯示了所有的MBean,按其對(duì)象名排序。當(dāng)在樹(shù)種選擇了一個(gè)MBean之后,其屬性、操作、通知和其他信息會(huì)在右邊顯示。
如果屬性值是可寫(xiě)的(可寫(xiě)會(huì)藍(lán)色顯示),你可以設(shè)置屬性值。你也可以調(diào)用在操作選項(xiàng)卡中顯示的操作。
顯示圖表:
你可以通過(guò)雙擊屬性值的方法顯示一個(gè)屬性值/時(shí)間圖表,比如,如果你雙擊java.lang.GarbageCollector.Copy Mbean的CollectionTime屬性,你會(huì)得到如下圖所示的顯示:

查看VM信息。
VM選項(xiàng)卡提供了JVM的信息。

這些信息包括:
Uptime:JVM啟動(dòng)后的總時(shí)間。
Processes CPU Time:JVM啟動(dòng)后消耗的總CPU時(shí)間。
Total Compile Time:即時(shí)編譯(JIT compilation)消耗的總時(shí)間。JVM的具體實(shí)現(xiàn)決定JIT編譯何時(shí)發(fā)生。Hotspot VM使用adaptive compilation,在這種方式zhogn ,VM使用標(biāo)準(zhǔn)的解釋器(interpreter)運(yùn)行一個(gè)應(yīng)用程序,但是會(huì)分析其代碼判斷性能瓶頸或者”hot spots”。
配置tomcat使用jconsole
修改catalina腳本
Windows平臺(tái):修改catalina.bat,在dorun和dostart段開(kāi)頭增加一行(注意是一行):
set JAVA_OPTS=%JAVA_OPTS% -Djava.rmi.server.hostname=192.168.1.101
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port="9004"
-Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"
Unix/Linux平臺(tái):修改catalina.sh,在dorun和dostart段開(kāi)頭增加一行(注意是一行):
JAVA_OPTS="$JAVA_OPTS "-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port="9004"
-Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"
啟動(dòng)jconsole
啟動(dòng)tomcat之后,根據(jù)上文中的jconsole簡(jiǎn)介中的命令啟動(dòng)jconsole,如果是在服務(wù)器本地運(yùn)行jconsole,會(huì)出現(xiàn)如下界面:

直接進(jìn)行連接即可。
如果是遠(yuǎn)程監(jiān)控,需要點(diǎn)擊遠(yuǎn)程選項(xiàng)卡并輸入相關(guān)信息,示例如下:

“主機(jī)名或ip”處填寫(xiě)需要監(jiān)視的主機(jī)ip,端口為服務(wù)器上上文中添加的-Dcom.sun.management.jmxremote.port="portNumber"設(shè)定的端口,本文以9004為例。在設(shè)定為:-Dcom.sun.management.jmxremote.authenticate="false" 的情況下,用戶名和口令留空即可。
如果需要使用JConsole遠(yuǎn)程監(jiān)控 Tomcat可以在命令行直接輸入:
JConsole 192.168.1.101:9004
進(jìn)階安全設(shè)定
在上文中的配置適用于在測(cè)試環(huán)境中監(jiān)視tomcat,如果是在生產(chǎn)環(huán)境中監(jiān)視tomcat則需要在安全性上有進(jìn)一步要求。
配置jmx訪問(wèn)密碼
1. 修改上文中的catalina腳本中的JAVA_OPT參數(shù),將
-Dcom.sun.management.jmxremote.authenticate="false" 修改為:
-Dcom.sun.management.jmxremote.authenticate="true"
2. 將$JRE/lib/management/jmxremote.password.template文件在同目錄下復(fù)制一份,重命名為$JRE/lib /management/jmxremote.password,編輯jmxremote.password,添加允許訪問(wèn)的用戶名及密碼,比如添加用戶 zxwh,密碼為zxme,則在文件尾添加一行:
zxwh zxme
注意用戶密碼不能包含空格,tab等字符
3. 編輯$JRE_HOME/lib/management/jmxremote.access文件,對(duì)剛才添加的用戶賦予一定的權(quán)限:
zxwh readonly (或者readwrite)
4. 確認(rèn)jmxremote.password和jmxremote.access兩個(gè)文件中的用戶是相同的。注意如果jmxremote.access中沒(méi)有對(duì)應(yīng)用戶的話,配置是無(wú)效的。
注:以上配置文件的位置都是可以更改的,具體配置方法在此不再贅述。
5. 由于jmxremote.password中的密碼都是明文保存的,所以jmxremote.password、jmxremote.access文件的權(quán)限要注意,應(yīng)該設(shè)置為只有owner才可讀,當(dāng)然這個(gè)用戶也必須是啟動(dòng)tomcat的用戶。
6. 啟動(dòng)jconsole進(jìn)行連接,在用戶名和口令處輸入設(shè)定的用戶和密碼。
7. 使用密碼認(rèn)證方式進(jìn)行連接,不但可以提高安全性,而且可以對(duì)用戶的權(quán)限進(jìn)行設(shè)置。如果不使用密碼認(rèn)證的方式,則無(wú)法對(duì)用戶的權(quán)限進(jìn)行限制。
配置使用ssl進(jìn)行加密連接
1. 在服務(wù)器上使用keytool創(chuàng)建密鑰對(duì)
keytool是java平臺(tái)自帶的一個(gè)密鑰和證書(shū)管理工具,使用keytool創(chuàng)建密鑰對(duì):
keytool -genkey -alias tomcat -keystore /somepath/tomcatKeyStore
按照提示輸入相關(guān)信息(包括設(shè)定密碼、姓、組織名等),這些信息是可以隨便輸入的,但從產(chǎn)品角度講應(yīng)該統(tǒng)一設(shè)定。輸入的密碼在今后操作中均需要使用。
2. 導(dǎo)出公鑰
keytool -export -alias tomcat -keystore /somepath/tomcatKeyStore -file /somepath/jconsole.cert
3. 將公鑰導(dǎo)入至需要運(yùn)行jconsole的機(jī)器。
keytool –import –alias jconsole –keystore /somepath/jconsoleKeyStore -file /somepath/jconsole.cert
4. 修改tomcat的catalina腳本
將-Dcom.sun.management.jmxremote.ssl="false"修改為:
-Dcom.sun.management.jmxremote.ssl="true",并在 JAVA_OPTS變量行添加:
-Djavax.net.ssl.keyStore=/somepath/jconsoleKeyStore
-Djavax.net.ssl.keyStorePassword=設(shè)定的密碼
5. 使用如下參數(shù)啟動(dòng)jconsole :
jconsole -J-Djavax.net.ssl.trustStore=/somepath/jconsoleKeyStore
6. 填入主機(jī)名、用戶、口令連接服務(wù)器。
其他問(wèn)題
1. 在執(zhí)行shutdown.sh或者shutdown.bat腳本關(guān)閉tomcat時(shí)出現(xiàn)如下錯(cuò)誤,tomcat無(wú)法關(guān)閉:
錯(cuò)誤: 代理拋出異常: java.rmi.server.ExportException: Port already in use: 9004;
nested exception is:
java.net.BindException: Address already in use: JVM_Bind
|