這篇文章主要介紹了如何解決tomcat自動關(guān)閉的bug,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
前言
最近一個運行了4年的javaee web項目,經(jīng)常接到客戶反饋系統(tǒng)無法打開。登錄服務器查看服務,發(fā)現(xiàn)是tomcat自動關(guān)閉了?;臼?到4天發(fā)生一次。
運維人員開始以為是其他服務殺死了tomcat服務,沒放在心上,解決方法就是直接重啟tomcat。
最終捅了簍子,運維人員被客戶投訴,扣了一個月的績效。
解決這個bug兜兜轉(zhuǎn)轉(zhuǎn)來到了我這里。既然接到任務,那就開干,沒有解決不了的bug。
系統(tǒng)的運行環(huán)境如下:
tomcat6.0
32位jdk7.0
window server2003 32位,32G內(nèi)存。
查看日志,如果tomcat閃崩,都會在tomcat的bin目錄下生成以"hs_err"開頭的日志文件。打開最新的日志文件,首先看到的是下面一段話:
# There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (malloc) failed to allocate 32756 bytes for ChunkPool::allocate # Possible reasons: # The system is out of physical RAM or swap space # In 32 bit mode, the process size limit was hit # Possible solutions: # Reduce memory load on the system # Increase physical memory or swap space # Check if swap backing store is full # Use 64 bit Java on a 64 bit OS # Decrease Java heap size (-Xmx/-Xms) # Decrease number of Java threads # Decrease Java thread stack sizes (-Xss) # Set larger code cache with -XX:ReservedCodeCacheSize= # This output file may be truncated or incomplete. # # Out of Memory Error (allocation.cpp:211), pid=7864, tid=6556 # # JRE version: Java(TM) SE Runtime Environment (7.0_79-b15) (build 1.7.0_79-b15) # Java VM: Java HotSpot(TM) Server VM (24.79-b02 mixed mode windows-x86 ) # Failed to write core dump.
大概意思就是內(nèi)存不夠了,無法分配32756字節(jié)的空間。同時給出幾個解決方法:
1、減少系統(tǒng)內(nèi)存負載;
2、增加物理內(nèi)存或者交換空間;
3、在64位操作系統(tǒng)上使用64位jdk;
4、減少java heap大小;
5、減少java線程數(shù)量;
6、減少java線程堆棧大小。
通過上面的內(nèi)容可以得出,jvm無法分配32756 bytes的內(nèi)存空間。
從接到任務開始,我一直以為是jvm配置出錯,導致內(nèi)存不夠用,只需調(diào)整下新生代、老年代的配置即可。
繼續(xù)往下看日志文件,找到"GC Heap History (10 events):"這一行,這個記錄jvm最后10次垃圾回收時堆的變化情況。
GC Heap History (10 events): Event: 572312.299 GC heap before {Heap before GC invocations=5046 (full 357): PSYoungGen total 201472K, used 200685K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 100% used [0x573c0000,0x63540000,0x63540000) from space 3328K, 76% used [0x63540000,0x637bb528,0x63880000) to space 3328K, 0% used [0x63880000,0x63880000,0x63bc0000) ParOldGen total 843776K, used 422602K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d872b18,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) Event: 572312.305 GC heap after Heap after GC invocations=5046 (full 357): PSYoungGen total 201472K, used 1103K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 0% used [0x573c0000,0x573c0000,0x63540000) from space 3328K, 33% used [0x63880000,0x63993c90,0x63bc0000) to space 3328K, 0% used [0x63540000,0x63540000,0x63880000) ParOldGen total 843776K, used 423618K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d970b18,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) } Event: 572351.132 GC heap before {Heap before GC invocations=5047 (full 357): PSYoungGen total 201472K, used 199247K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 100% used [0x573c0000,0x63540000,0x63540000) from space 3328K, 33% used [0x63880000,0x63993c90,0x63bc0000) to space 3328K, 0% used [0x63540000,0x63540000,0x63880000) ParOldGen total 843776K, used 423618K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d970b18,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) Event: 572351.137 GC heap after Heap after GC invocations=5047 (full 357): PSYoungGen total 201472K, used 1615K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 0% used [0x573c0000,0x573c0000,0x63540000) from space 3328K, 48% used [0x63540000,0x636d3ec8,0x63880000) to space 3328K, 0% used [0x63880000,0x63880000,0x63bc0000) ParOldGen total 843776K, used 423674K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d97eb18,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) } Event: 572398.649 GC heap before {Heap before GC invocations=5048 (full 357): PSYoungGen total 201472K, used 199759K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 100% used [0x573c0000,0x63540000,0x63540000) from space 3328K, 48% used [0x63540000,0x636d3ec8,0x63880000) to space 3328K, 0% used [0x63880000,0x63880000,0x63bc0000) ParOldGen total 843776K, used 423674K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d97eb18,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) Event: 572398.655 GC heap after Heap after GC invocations=5048 (full 357): PSYoungGen total 201472K, used 1998K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 0% used [0x573c0000,0x573c0000,0x63540000) from space 3328K, 60% used [0x63880000,0x63a73830,0x63bc0000) to space 3328K, 0% used [0x63540000,0x63540000,0x63880000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62138,0x13bc0000) } Event: 576881.689 GC heap before {Heap before GC invocations=5049 (full 357): PSYoungGen total 201472K, used 200142K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 100% used [0x573c0000,0x63540000,0x63540000) from space 3328K, 60% used [0x63880000,0x63a73830,0x63bc0000) to space 3328K, 0% used [0x63540000,0x63540000,0x63880000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51850K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62850,0x13bc0000) Event: 576881.696 GC heap after Heap after GC invocations=5049 (full 357): PSYoungGen total 201472K, used 3155K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 0% used [0x573c0000,0x573c0000,0x63540000) from space 3328K, 94% used [0x63540000,0x63854cb0,0x63880000) to space 3328K, 0% used [0x63880000,0x63880000,0x63bc0000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51850K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e62850,0x13bc0000) } Event: 580535.452 GC heap before {Heap before GC invocations=5050 (full 357): PSYoungGen total 201472K, used 201299K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 198144K, 100% used [0x573c0000,0x63540000,0x63540000) from space 3328K, 94% used [0x63540000,0x63854cb0,0x63880000) to space 3328K, 0% used [0x63880000,0x63880000,0x63bc0000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e64228,0x13bc0000) Event: 580535.459 GC heap after Heap after GC invocations=5050 (full 357): PSYoungGen total 200960K, used 1858K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 197632K, 0% used [0x573c0000,0x573c0000,0x634c0000) from space 3328K, 55% used [0x63880000,0x63a50be0,0x63bc0000) to space 3584K, 0% used [0x634c0000,0x634c0000,0x63840000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e64228,0x13bc0000) }
看了上面的內(nèi)容,并沒有發(fā)現(xiàn)tomcat閃崩是由于老年代,持久代,新生代空間不足引起的。有好幾次因為eden區(qū)空間使用到100%引起的full gc,但是垃圾回收過后eden區(qū)的空間都恢復到正常的水平。
日志中還記錄了tomcat閃崩時heap堆的使用情況:
Heap PSYoungGen total 200960K, used 95671K [0x573c0000, 0x63bc0000, 0x63bc0000) eden space 197632K, 47% used [0x573c0000,0x5cf5d230,0x634c0000) from space 3328K, 55% used [0x63880000,0x63a50be0,0x63bc0000) to space 3584K, 0% used [0x634c0000,0x634c0000,0x63840000) ParOldGen total 843776K, used 423703K [0x23bc0000, 0x573c0000, 0x573c0000) object space 843776K, 50% used [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen total 262144K, used 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) object space 262144K, 19% used [0x03bc0000,0x06e64228,0x13bc0000)
一切都那么正常,同時又那么詭異。
翻看了之前發(fā)生日志,內(nèi)容都是大同小異。
重新翻看了幾遍日志,這次把重點放在日志中建議的解決方案上:
# Reduce memory load on the system # Increase physical memory or swap space # Check if swap backing store is full # Use 64 bit Java on a 64 bit OS # Decrease Java heap size (-Xmx/-Xms) # Decrease number of Java threads # Decrease Java thread stack sizes (-Xss)
其中下面幾個解決方案不采用:
Reduce memory load on the system。 系統(tǒng)內(nèi)存夠用,32G的內(nèi)存,還剩20G沒用,無需減少內(nèi)存。
Increase physical memory or swap space。 系統(tǒng)內(nèi)存夠用,32G的內(nèi)存,還剩20G沒用,無需增加物理內(nèi)存。
Use 64 bit Java on a 64 bit OS。 32位操作系統(tǒng),無法使用64位jdk。
只剩下下面的三個解決方案了:
Decrease Java heap size (-Xmx/-Xms)。 heap堆設置過大,就會影響剩余內(nèi)存。
Decrease number of Java threads
Decrease Java thread stack sizes (-Xss)
而減少java線程的數(shù)量,需要修改代碼,這個也不實際。
最后只剩下
Decrease Java heap size (-Xmx/-Xms)
Decrease Java thread stack sizes (-Xss)
這兩個解決方案了,就從這里入手,曙光就在前方。
先看 Decrease Java thread stack sizes (-Xss) 解決方案
java線程運行也是需要內(nèi)存空間的,-Xss參數(shù)指定每個線程堆棧的大小,為jvm啟動的每個線程分配的內(nèi)存大小。在jdk1.4版本中是256K,JDK1.5及以上版本是1M。
tomcat jvm的參數(shù)設置如下:
JAVA_OPTS=%JAVA_OPTS% -server -Xms1024m -Xmx1024m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k
已經(jīng)通過-Xss設置每個java線程堆棧的大小為256K。
在java語言里, 當你創(chuàng)建一個線程的時候,虛擬機會在JVM內(nèi)存創(chuàng)建一個Thread對象同時創(chuàng)建一個操作系統(tǒng)線程,而這個系統(tǒng)線程的內(nèi)存用的不是JVMMemory,而是系統(tǒng)中剩下的內(nèi)存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
當需要創(chuàng)建線程,而操作系統(tǒng)剩余內(nèi)存不夠分配給一個java線程時,就會報Out of Memory Error的錯誤。
由于已經(jīng)設置通過-Xss設置java線程棧的大小為256K,因此也決定不采用這個解決方案。
現(xiàn)在只剩 下Decrease Java heap size (-Xmx/-Xms) 這個解決方案了。通過減少堆的大小,而留出足夠的內(nèi)存空間給java線程堆棧使用。
32位的window操作系統(tǒng)給每個進程分配的內(nèi)存空間是2G,減去堆的大容量和PermSize的大容量,剩下的容量就留給java線程棧使用。
經(jīng)過分析代碼和之前錯誤的日志,發(fā)現(xiàn)一般在350個線程這樣就出現(xiàn)Out of Memory Error的錯誤。
在出現(xiàn)錯誤時,heap空間才用了不到40%。因此決定將java heap的從1G減少到768M。
修改的jvm參數(shù)如下:
JAVA_OPTS=%JAVA_OPTS% -server -Xms768m -Xmx768m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k
到目前為止,系統(tǒng)已經(jīng)穩(wěn)定運行1個月,各個參數(shù)指標都在正常范圍內(nèi)。heap使用率最高才70%。
總結(jié):
1、經(jīng)過這次解決bug,加深了對java虛擬機的了解,特別是線程棧,內(nèi)存堆,持久代,新生代等概念。
2、一定要仔細閱讀日志文件,一步一步排除掉潛在的解決方案。綜合系統(tǒng)的運行環(huán)境,找出合理的解決方案。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何解決tomcat自動關(guān)閉的bug”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián)成都網(wǎng)站設計公司,關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設計公司行業(yè)資訊頻道,更多相關(guān)知識等著你來學習!
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、網(wǎng)站設計器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
新聞名稱:如何解決tomcat自動關(guān)閉的bug-創(chuàng)新互聯(lián)
文章源于:http://chinadenli.net/article2/doshoc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設、定制開發(fā)、App設計、外貿(mào)建站、動態(tài)網(wǎng)站、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)