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 : 垃圾回收總消耗時間
- NGCMN : 新生代佔用的最小空間
- NGCMX : 新生代佔用的最大空間
- OGCMN : 老年代佔用的最小空間
- OGCMX : 老年代佔用的最大空間
- OGC:當前年老代的容量 (KB)
- OC:當前年老代的空間 (KB)
- PGCMN : perm佔用的最小空間
- PGCMX : perm佔用的最大空間
- LGCC:最近垃圾回收的原因
- GCC:當前垃圾回收的原因
- Compiled : 編譯數量
- Failed : 編譯失敗數量
- Invalid : 無效數量
- Time : 編譯耗時
- FailedType : 失敗型別
- FailedMethod : 失敗方法的全限定名
- Loaded : 載入class的數量
- Bytes : class位元組大小
- Unloaded : 未載入class的數量
- Bytes : 未載入class的位元組大小
- Time : 載入時間