問題:
報錯為java.lang.OutOfMemoryError幔亥,內(nèi)存溢出。根據(jù)報錯并不容易定位問題玖像,因為內(nèi)存溢出的位置不一定就是報錯位置紫谷。而是程序運行到報錯行那一刻,產(chǎn)生了內(nèi)存溢出捐寥。為了定位問題笤昨,我們需要工具。
問題定位
關于內(nèi)存溢出握恳,常見bug如下:
1.內(nèi)存中加載的數(shù)據(jù)量過于龐大瞒窒,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);
2.集合類中有對對象的引用乡洼,使用完后未清空崇裁,使得JVM不能回收;
3.代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復的對象實體束昵;
4.使用的第三方軟件中的BUG拔稳;
5.啟動參數(shù)內(nèi)存值設定的過小锹雏;
為了定位問題巴比,我們需要知道在jvm內(nèi)存中的各個對象所占用的實際內(nèi)存是多少。
jdk包內(nèi)為我們提供很多的命令工具來幫助我們解決問題礁遵。如下圖所示:
這些exe文件主要包括用于監(jiān)視虛擬機和故障處理的工具轻绞,這些故障處理的工具被SU公司作為“禮物”附贈給jdk的使用者,并在軟件的使用說明中把它們聲明為“沒有技術支持的實驗性質(zhì)的產(chǎn)品”佣耐,但事實上這些工具都非常穩(wěn)定且強大政勃,能在處理應用程序的性能問題、定位故障時發(fā)揮巨大作用兼砖。
1.定位進程號
首先我們通過cmd命令行轉(zhuǎn)到我們的jdk的bin目錄下奸远,輸入jps -l 查看當前運行的所有進程號(pid)既棺。
2查詢指定線程的內(nèi)存狀態(tài)
語句:jmap -heap [pid]
3查看JVM堆中對象詳細占用情況
語句:jmap -heap
4生成dump文件
用jmap -heap查看并不直觀,我們可以生成一個dump文件作為快照懒叛,即保存了歷史內(nèi)存情況援制,又可以用工具分析內(nèi)存占用情況。
語句:jmap -dump:format=b,file=文件名 [pid]
生成位置默認就在jdk的bin目錄下芍瑞。
利用MAT進行分析dump文件,下面是MAT安裝教程
在Eclipse help -> Eclipse Marketplace下搜索Memory:
安裝后打開導出的文件:
1褐墅、打開MAT面板
2.打開導出文件
3.找到我們的dump文件就可以查看了
5.jdk內(nèi)置的實時內(nèi)存監(jiān)控
在jdk的bin目錄下拆檬,還有一個功能強大的軟件,jvisualvm
打開它妥凳,并找到程序所屬的線程就可以實時監(jiān)控內(nèi)存情況了竟贯。
問題解決
通過對dump文件分析,發(fā)現(xiàn)byte數(shù)組所占哦那個的內(nèi)存空間過大逝钥。而程序中除了正常的channel.write(),只有在read中存在new出來的byte數(shù)組屑那。
嘛,差不多了艘款。