最近項目中的仿真模塊出現了java.lang.OutOfMemoryError:java heap space(內存不足)異常,簡單查了一下,懷疑可能是內存泄露或者內存溢出;
內存泄露指的是程序中動態分配內存給一些臨時對象,但是對象不會被GC(java垃圾回收機制gabage collection)所回收,它始終占用內存。即被分配的對象可達但已無用;
內存溢出指的是程序運行過程中無法申請到足夠的內存而導致的一種錯誤。內存溢出通常發生於OLD段或Perm段垃圾回收后,仍然無內存空間容納新的Java對象的情況;
從定義上可以看出內存泄露是內存溢出的一種誘因,不是唯一因素;
有時單單從代碼上很難知道是哪里的問題,所以需要借助一下JDK提供的工具,實時了解程序中的資源的使用情況,JDK為我們提供了JSTATD和Java VisualVM進行遠超監控:
一、啟動JSTATD:在JDK的bin目錄下新建jstatd.all.policy文件(其實目錄可以自己選擇)鍵入一下代碼用於啟動JSTATD:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
保存;然后使用以下命令啟動JSTATD:
jstatd -J-Djava.security.policy=/jstatd.all.policy文件的目錄/jstatd.all.policy -p 端口號(用於Java VisualVM遠程鏈接)
二、檢查JSTATD是否已經啟動
鍵入 jps ,如果看到jstatd已經起來了,說明啟動成功;
三、在本地JDK的安裝目錄下bin目錄,找到jvisualvm.exe文件雙擊打開,
打開后輸入ip,端口
然后我們就可以實時的進行監控了
如果遠程連接jstatd后,節點加載不出來,可以在jstatd啟動時開啟日志打印,方便定位問題
jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.101.56 -J-Djava.rmi.server.logCalls=true
-J-Djava.security.policy=jstatd.all.policy
=號后面的是文件的絕對路徑;-J-Djava.rmi.server.logCalls=true
打開日志,如果客戶端有連接過來的請求,可以監控到,便於排錯;-J-Djava.rmi.server.hostname=192.168.101.56
指明本機 hostname 對應的本機地址,確保該地址可以給客戶機訪問。因為有的服務器 hostname 對應的 ip 不一定是外網能連上的,最好在這里直接明確指定;-p 9099
指定服務的端口號,默認是1099。也是可選參數。
注意:jstatd啟動后,會開啟一個隨機端口,通過sudo netstat -lutnp |grep jstatd命令查看jstatd對應的端口
可以看到有個33193的端口,這個端口需要對外開放出來
sudo iptables -I INPUT -p tcp --dport 33193 -j ACCEPT
使用上面的命令開放33193端口
然后就可以通過jvisualvm遠程監控了;
ps:如果需要監控GC,需要安裝插件:窗體點擊工具->插件->可用插件,選擇需要的插件進行下載,還有插件對應的網站已經被Oracle公司關閉了,遷移到github,因此
https://visualvm.github.io/pluginscenters.html在這個網站上,找到你jdk對應的下載地址(注意小版本號),例如我的是jdk1.8.0_111,那么就是
就是這個地址,然后
jvisualvm窗體點擊工具->插件->設置,點擊編輯,把url改成對應的下載地址,然后進行下載,下載完需要重啟jvisualvm;