1. 程式人生 > >java虛擬機器的一些記憶體監控

java虛擬機器的一些記憶體監控

記憶體溢位之後,分析原因往往有些困難,這裡在啟動jvm的時候可以增加一些引數,等記憶體溢位發生時jvm會幫我們記錄當時的快照

這是我模擬記憶體溢位的啟動引數:

-Xmx64m -Xms32m -Xmn16m -Xss8m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/liucheng/開發/vm/VMDemo.hprof -XX:OnOutOfMemoryError="/Users/liucheng/開發/vm/sh/clear.sh VMDemo"

設定jvm的記憶體大小相關引數我不說了,重點是後面幾個引數

-XX:+HeapDumpOnOutOfMemoryError 當jvm發生記憶體溢位(om溢位)的時候進行快照記錄;

-XX:HeapDumpPath 設定快照路徑(可以是路徑,也可以是具體到快照檔名),如果不設定,預設會在當前工作空間生成快照。

-XX:OnOutOfMemoryError 設定發生記憶體溢位後呼叫一個sh指令碼(呼叫指令碼更多的目的是將快照檔案轉移到其他伺服器,因為快照檔案非常大,經常發生om又沒有及時清理快照檔案,會很快讓磁碟被塞滿)

ok,開始正題,導致堆記憶體溢位的程式碼:


執行結果:


附上clear.sh指令碼:


生成的快照檔案:


如何分析快照檔案,這裡我推薦3種方式:

一、使用java自帶的命令  jhat

執行 jhat -port 8888 VMDemo.hprof不指定 -port 預設7000訪問 http://localhost:8888

這種方式會將快照資訊以web的方式展現,但是展示資訊有限。


瀏覽器訪問 http://localhost:7000


這裡面每個連結操作都有相應的說明,有興趣的可以百度瞭解,這種方式我不太喜歡,沒有過多瞭解

二、使用mat工具分析

在這裡下載 https://www.eclipse.org/mat/

mat載入快照檔案後:


這個把記憶體情況用餅形圖表達的很清楚。

更多資訊



通過上面這張圖可以看出程式碼中的 list塞入了1407條型別為string的資料

三、使用visualVM

裝載進快照檔案後,選擇執行緒項


以上是都是快照已經生成,事後來找問題的方案,針對正在執行中的jvm來說,可以用以下方式監控jvm各種引數起到除錯作用。

一、使用visualVM

這種方式我就不多說了,除了本地也可以遠端連線,這種都懂,下面我要介紹的是才是好用的

二、使用java自帶的jconsole工具

執行 jconsole 稍等一下下出來一個介面


這次連線一個遠端的jvm來示例

遠端連線之前的準備工作:

在伺服器上執行 hostname -i 得到的ip應該是-Djava.rmi.server.hostname的設定ip然後用如下命令啟動:java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9990 -Dcom.sun.management.jmxremote.rmi.port=9990 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=al.cloud.net -jar eureka-0.0.1-SNAPSHOT.jar

這裡公網ip就不對外公開了,我用本地hosts  al.cloud.net映射了公網伺服器ip,設定成你自己要連線的伺服器上公網ip即可。

以下是引數解釋

-Dcom.sun.management.jmxremote 布林 是否支援遠端JMX訪問,預設true -Dcom.sun.management.jmxremote.port 數值 監聽埠號,方便遠端訪問 -Dcom.sun.management.jmxremote.rmi.port 數值 rmi埠,方便遠端訪問 -Dcom.sun.management.jmxremote.authenticate 布林 是否需要開啟使用者認證,預設開啟 -Dcom.sun.management.jmxremote.ssl 布林 是否對連線開啟SSL加密,預設開啟 -Dcom.sun.management.jmxremote.access.file 路徑 對訪問使用者的許可權授權的檔案的路徑,預設路徑JRE_HOME/lib/management/jmxremote.access-Dcom.sun.management.jmxremote. password.file 路徑 設定訪問使用者的使用者名稱和密碼,預設路徑JRE_HOME/lib/management/ jmxremote.password

本地來測試一下伺服器上的埠是否可以正常通訊  telnet al.cloud.net 9990

開始連線



出現這個是因為ssl項設定為false了 不管它繼續點選連線


後面的都知道操作了。

其實還有一些java自帶的命令方式檢視

比如:

當前執行緒所有堆疊資訊 jstack pid當前執行緒的相關資訊輸出到日誌 kill -3 pid 檢視gc資訊jstat -gc pid
  • S0C : survivor0區的總容量
  • S1C : survivor1區的總容量
  • S0U : survivor0區已使用的容量
  • S1C : survivor1區已使用的容量
  • EC : Eden區的總容量
  • EU : Eden區已使用的容量
  • OC : Old區的總容量
  • OU : Old區已使用的容量
  • PC 當前perm的容量 (KB)
  • PU perm的使用 (KB)
  • YGC : 新生代垃圾回收次數
  • YGCT : 新生代垃圾回收時間
  • FGC : 老年代垃圾回收次數
  • FGCT : 老年代垃圾回收時間
  • GCT : 垃圾回收總消耗時間
gc資訊 2000ms內輸出一次 總共輸出20次jstat -gc pid 2000 20同-gc,還會輸出Java堆各區域使用到的最大、最小空間jstat -gccapacity 程序id
  • NGCMN : 新生代佔用的最小空間
  • NGCMX : 新生代佔用的最大空間
  • OGCMN : 老年代佔用的最小空間
  • OGCMX : 老年代佔用的最大空間
  • OGC:當前年老代的容量 (KB)
  • OC:當前年老代的空間 (KB)
  • PGCMN : perm佔用的最小空間
  • PGCMX : perm佔用的最大空間
同-gc,還會輸出的是已使用空間佔總空間的百分比jstat -gcutil pid垃圾收集統計概述(同-gcutil),附加最近兩次垃圾回收事件的原因jstat -gccause pid
  • LGCC:最近垃圾回收的原因
  • GCC:當前垃圾回收的原因
檢視JIT編譯過的方法數量耗時jstat -compiler pid
  • Compiled : 編譯數量
  • Failed : 編譯失敗數量
  • Invalid : 無效數量
  • Time : 編譯耗時
  • FailedType : 失敗型別
  • FailedMethod : 失敗方法的全限定名
檢視類裝載數量jstat -class pid
  • Loaded : 載入class的數量
  • Bytes : class位元組大小
  • Unloaded : 未載入class的數量
  • Bytes : 未載入class的位元組大小
  • Time : 載入時間