前些天,服務(wù)器上一個(gè)服務(wù)跑了一個(gè)多月突然當(dāng)?shù)袅???戳讼氯罩?,程序拋出了java.lang.OutOfMemoryError,之前也出現(xiàn)過同樣的錯(cuò)誤,服務(wù)跑了三個(gè)月內(nèi)存溢出。出現(xiàn)這個(gè)異常,初步判斷是程序有內(nèi)存泄漏,接下來需要利用一些工具來分析具體原因。
首先使用jdk自帶的工具jmap轉(zhuǎn)儲(chǔ)(dump)java內(nèi)存堆數(shù)據(jù)到本地文件中。jmap轉(zhuǎn)儲(chǔ)(dump)命令格式如下:
jmap -dump:
表示dump選項(xiàng),表示需要dump的java應(yīng)用程序的進(jìn)程ID
dump-options可以有以下三種參數(shù),參數(shù)之間用逗號(hào)隔開:
live,只dump活動(dòng)的object,如果沒有指定,表示dump所有object
format=b,字節(jié)流格式
file=,是轉(zhuǎn)儲(chǔ)文件的保存路徑
下面是dump命令的一個(gè)例子:
jmap -dump:format=b,file=heap.bin 8023
dump完成后,用Eclipse Memory Analyzer打開轉(zhuǎn)儲(chǔ)文件進(jìn)行分析。Eclipse Memory Analyzer是一個(gè)java內(nèi)存堆轉(zhuǎn)儲(chǔ)文件分析工具,可以生成內(nèi)存分析報(bào)告(包括內(nèi)存泄露Leak Suspects )。下面是分析完成后查看Top Consumers所看到的圖表:
看到這兩張圖表,問題就比較明朗了。berkeley db中的數(shù)據(jù)結(jié)點(diǎn)com.sleepycat.je.tree.BIN占用了大量內(nèi)存,導(dǎo)致內(nèi)存溢出了。為了提高訪問效率,berkeley db會(huì)緩存大量的結(jié)點(diǎn),緩存大小限制可以在EnvironmentConfig設(shè)置,默認(rèn)為jvm內(nèi)存大小限制的60%。而這個(gè)應(yīng)用程序中使用了5個(gè)EnvironmentImpl,并且都未單獨(dú)設(shè)置緩存大小,總的緩存限制為jvm內(nèi)存限制的300%(圖表中BIN結(jié)點(diǎn)已經(jīng)占用了94.55%的內(nèi)存),遠(yuǎn)遠(yuǎn)超出java的內(nèi)存限制。隨著服務(wù)的運(yùn)行,緩存數(shù)據(jù)越來越多,最后導(dǎo)致內(nèi)存溢出錯(cuò)誤。因此,為每個(gè)EnvironmentImpl設(shè)置合適的緩存大小限制,就可以避免再次發(fā)生內(nèi)存溢出。返回比特網(wǎng)首頁>>
聯(lián)系客服