原文地址:http://blog.csdn.net/sfdev/archive/2008/01/18/2051171.aspx
這幾天,網(wǎng)店系統(tǒng)基礎(chǔ)架構(gòu)進(jìn)行了一次大的升級(jí),升級(jí)之后例行的進(jìn)行了壓力測(cè)試,以前幾次大的項(xiàng)目發(fā)布?jí)毫y(cè)試都沒(méi)有任何問(wèn)題,沒(méi)想到這次出事故啦,而且是內(nèi)存泄露?
系統(tǒng)運(yùn)行環(huán)境:
硬件:Intel(R) Xeon(R) CPU 2.0G、4G RAM、Linux 2.6.9-42.ELsmp #1 SMP
軟件:jboss-4.0.5.GA [Java HotSpot(TM) Server VM (build 1.5.0_10-b03, mixed mode)]
JAVA運(yùn)行參數(shù)-server -Xms2048m -Xmx2048m -XX:NewSize=768m -XX:PermSize=128m -XX:MaxPermSize=128m
現(xiàn)象是這樣的:
對(duì)系統(tǒng)壓力測(cè)試大約4個(gè)小時(shí)左右,系統(tǒng)突然down掉,拋錯(cuò)為java.lang.OutOfMemoryError: requested 12 bytes for intptr_t in /BUILD_AREA/jdk1.5.0_10/hotspot/src/share/vm/runtime/deoptimization.cpp. Out of swap space?
由于是晚上進(jìn)行,所以沒(méi)有觀察到任何比較奇怪的現(xiàn)象出現(xiàn),再次壓力測(cè)試,仍然拋錯(cuò),但稍微有些不同java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?
經(jīng)多次壓力,現(xiàn)象100%可以重現(xiàn);
解決過(guò)程:
1、use jvmstat first
這是SUN自己的性能跟蹤工具,他占用server資源很少;監(jiān)控的結(jié)果令我們失望,因?yàn)镴VM表現(xiàn)完全正常,我們分配的2G內(nèi)存還有很多剩余,并沒(méi)有耗盡;GC也很正常,沒(méi)有出現(xiàn)明顯的Full GC或者是每次GC時(shí)間太長(zhǎng)的情況;
用top命令查看占用內(nèi)存不到3G,也還算富裕;而且系統(tǒng)并沒(méi)有JNI的使用;為什么會(huì)報(bào)OutOfMemoryError呢?未果!
2、search Out of swap space
更多都是遭遇了相同的問(wèn)題,但是好像都沒(méi)有一個(gè)很可行的解決辦法,甚至有人懷疑是JDK的bug,也有人說(shuō)可以用-Xss參數(shù)設(shè)置stack size大小,ss默認(rèn)大小為512k,但是從監(jiān)控上看我們的進(jìn)程也沒(méi)有那么多,但還是嘗試了一把,再次壓力問(wèn)題仍然未解決!
3、try to see heap dump
添加參數(shù)-XX:+HeapDumpOnOutOfMemoryError,讓系統(tǒng)出現(xiàn)OutOfMemoryError時(shí)將當(dāng)時(shí)JVM內(nèi)所有heap dump出來(lái),使用jHAT分析;
很可惜,1.5中對(duì)該參數(shù)的支持超級(jí)有限,記錄下來(lái)的信息很少,并沒(méi)有我們想象的那么多,那么有用,基本上這些信息是無(wú)用的;再次失敗!
4、back to OutOfMemoryError
由于jvmstat 能看見(jiàn)的JVM內(nèi)部信息有限,所以我們打算用專(zhuān)業(yè)工具JProfiler來(lái)進(jìn)行詳查;環(huán)境搞定之后,再次壓力,不到2小時(shí)情況就重現(xiàn)了,但是從JProfiler中觀察到的信息顯示JVM內(nèi)部的確沒(méi)有任何異常,結(jié)論和Jconsole觀察后完全一樣,JVM內(nèi)部沒(méi)有任何問(wèn)題!但為什么會(huì)有此錯(cuò)誤?想不通……
5、focus on java heap with linux
再次search了linux環(huán)境下面java heap的相關(guān)工作原理及組成信息,有發(fā)現(xiàn)了!
其實(shí)java heap由2部分組成:其一為我們熟悉的JVM heap,其二為和OS相關(guān)的Native heap;
JVM heap完全由GC掌控,我們可以通過(guò)參數(shù)-Xms、-Xmx指定其大小,并且可以用工具對(duì)其進(jìn)行監(jiān)控;他管理的東西就是我們所有的Java Object;
而Native heap是平臺(tái)相關(guān)的,我們既不能設(shè)置其使用大小也不能干預(yù)他的使用狀態(tài);他管理的東西一般都是很底層的,比如JIT使用的buffer、GC的底層data structures、JNI調(diào)用的所有相關(guān)對(duì)象、SWING/AWT調(diào)用需要的buffer和data structures……
由此想到,是否我們分配的JVM heap太大了,于是設(shè)置參數(shù)變?yōu)?Xms1536m -Xmx1536m再次壓力,問(wèn)題解決了!!!
雖然問(wèn)題解決了,但是我們還是沒(méi)能從根本上解釋此次故障,因?yàn)橄到y(tǒng)可用的內(nèi)存還有很多,并沒(méi)有耗盡?
難道32位的JAVA所能操作的內(nèi)存只有2G?JVM heap全部占完了會(huì)導(dǎo)致Native heap無(wú)法allocate memory?后續(xù)還需要進(jìn)一步研究此事;
PS:
1、上面我們提到專(zhuān)業(yè)級(jí)的性能監(jiān)控工具JProfiler,他的介紹及其安裝使用可以參考http://blog.chinaunix.net/u/11765/showart_239554.html;
有兩點(diǎn)可以注意下;其一:sh安裝方式下linux默認(rèn)安裝目錄一般為/usr/local/jprofilerX;其二為${JPROFILER_HOME}/bin/linux-x86目錄不一定要放在單獨(dú)項(xiàng)LD_LIBRARY_PATH中,只要classpath中能找到即可;
2、JProfiler、JProbe Profiler、Java Profiler三者是同一個(gè)產(chǎn)品么?
答案當(dāng)然為否;三者都是業(yè)內(nèi)非常優(yōu)秀的Java性能監(jiān)控工具,他們分別屬于不同的公司;
JProfiler:http://www.ej-technologies.com
JProbe Profiler:http://www.quest.com;TOAD就是該公司的產(chǎn)品之一;
Java Profiler:http://www.yourkit.com
其實(shí)現(xiàn)在回過(guò)頭來(lái)看下這個(gè)問(wèn)題,簡(jiǎn)直太easy了,java官方文檔中明確闡述了heap的兩種類(lèi)別,分別會(huì)導(dǎo)致兩類(lèi)的oom,一類(lèi)當(dāng)然是我們非常熟悉的jvm oom,另外一類(lèi)就是native heap oom;
這也提醒之后遇到問(wèn)題時(shí)第一時(shí)間找的不一定是search,可能官方文檔更有效;
posted on 2008-09-21 15:14
歲月如歌 閱讀(449)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
java