本文來自George的博客:《tomcat內(nèi)存溢出總結(jié)》 Tomcat內(nèi)存溢出的原因 在生產(chǎn)環(huán)境中tomcat內(nèi)存設置不好很容易出現(xiàn)內(nèi)存溢出,。造成內(nèi)存原因是不一樣的,當然處理 法子 也不一樣,。 這里根據(jù) 平時遇到的情況 和相干 材料 進行一個總結(jié),。常見的一般會有下面三種情況 : 1.OutOfMemoryError: heap space 2.OutOfMemoryError: PermGen space 3.OutOfMemoryError: unable to create new native thread. Tomcat內(nèi)存溢出解決方案 對于前兩種情況,在應用本身沒有內(nèi)存透露的情況下可以用設置tomcat jvm參數(shù)來解決,。(-Xms -Xmx -XX:PermSize -XX:MaxPermSize) 最后一種可能需要調(diào)劑操作系統(tǒng)和tomcat jvm參數(shù)同時調(diào)劑才能達到目標 ,。 第一種:堆溢出 在JVM中如果98%的光陰是用于GC且可用的 Heap size 不足2%的時候?qū)伋龃水惓P畔ⅰ?/p> 沒有內(nèi)存透露的情況下,調(diào)劑 -Xms -Xmx 參數(shù)可以解決,。 -Xms:初始堆大小 -Xmx:最大堆大小 但堆的大小受下面三方面影響: 1.相干操作系統(tǒng)的數(shù)據(jù)模型(32-bt還是64-bit)限制,;(32位系統(tǒng) 下,一般限制在1.5G~2G;我在2003 server 系統(tǒng)下(物理內(nèi)存:4G和6G,,jdk:1.6) 1612M,,64為操作系統(tǒng)對內(nèi)存無窮制。) 2.系統(tǒng)的可用虛擬內(nèi)存限制,; 3.系統(tǒng)的可用物理內(nèi)存限制,。 堆的大小可以應用 java -Xmx***M version 命令來。支撐的話會出現(xiàn)jdk的版本號,,不支撐會報錯。 -Xms -Xmx 一般配置成一樣對比 好比如set JAVA_OPTS= -Xms1024m -Xmx1024m 第二種:永久保存區(qū)域溢出 PermGen space的全稱是Permanent Generation space,,是指內(nèi)存的永久保存區(qū)域,。這一部分用于寄放 Class和Meta 的信息,Class 在被 Load 的時候被放入PermGen space 區(qū)域,,它和寄放 Instance 的 Heap 區(qū)域不同,,GC(Garbage Collection)不會在主程序運行期對 PermGen space 進行清算 ,所以如果你的APP會LOAD很多 CLASS 的話,,就很可能出現(xiàn) PermGen space 差錯 ,。這種差錯常見在 web 對 JSP 進行 pre compile 的時候。但目前的 hibernate 和 spring 項目中也很容易出現(xiàn)這樣的問題,。,?page=1 的帖子有討論的這個問題??赡苁怯捎谶@些框架會動態(tài) class,,而且 jvm 的 gc 是不會清算 PemGen space 的,導致內(nèi)存溢出,。 這一個一般是加大-XX:PermSize -XX:MaxPermSize 來解決問題,。 -XX:PermSize 永久保存 區(qū)域初始大小 -XX:PermSize 永久保存 區(qū)域初始最大值 這一般聯(lián)合第一條應用 ,比如 set JAVA_OPTS= -Xms1024m -Xmx1024m -XX:PermSize=128M -XX:PermSize=256M 有一點需要注意:java -Xmx***M version 命令來測試的最大堆內(nèi)存是 -Xmx與 -XX:PermSize的 和 比如系統(tǒng) 支撐 最大的jvm堆大小事1.5G,,那 -Xmx1024m -XX:PermSize=768M 是無法運行的,。 第三種:無法創(chuàng)立新的線程 這種現(xiàn)象對比少見,也對比奇怪,,首要是和 jvm 與系統(tǒng)內(nèi)存的比例有關,。 這種怪事是因為JVM已經(jīng)被系統(tǒng)分配了大宗的內(nèi)存(比如1.5G),并且它至少要占用可用內(nèi)存的一半,。有人創(chuàng)造,,在線程個數(shù)很多的情況 下,你分配給JVM的內(nèi)存越多,,那么,,上述差錯產(chǎn)生的可能性就越大。 產(chǎn)生這種現(xiàn)象的原因如下(從這個blog中領會到原因): 每一個32位的歷程最多可以應用 2G的可用內(nèi)存,因為另外2G被操作系統(tǒng)保存,。這里假設應用 1.5G給JVM,,那么還余下500M可用內(nèi)存。這500M內(nèi)存中的一部分必須 用于系統(tǒng) dll的加載,,那么真正剩下的也許只有400M,,現(xiàn)在要害 的處所 出現(xiàn)了:當你應用 創(chuàng)立 一個線程,在JVM的內(nèi)存里也會創(chuàng)立 一個Thread對象,,但是同時也會在操作系統(tǒng) 里創(chuàng)立 一個真正的物理線程(參考JVM規(guī)范),,操作系統(tǒng) 會在余下的400兆內(nèi)存里創(chuàng)立 這個物理線程,而不是在JVM的1500M的內(nèi)存堆里創(chuàng)立 ,。在jdk1.4里頭,,默認的棧大小是256KB,但是在jdk1.5里頭,,默認的棧大小為1M每線程,,因此,在余下400M的可用內(nèi)存里邊我們最多也只能創(chuàng)立 400個可用線程,。 這樣結(jié)論就出來了,,要想創(chuàng)立更多的線程,你必須減少分配給JVM的最大內(nèi)存,。還有一種做法是讓JVM宿主在你的JNI代碼里邊,。 給出一個有關能夠創(chuàng)立線程的最大個數(shù)的估算公式: (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads 對于jdk1.5而言,假設操作系統(tǒng)保存120M內(nèi)存: 1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads 1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads 在2000/XP/2003的boot.ini里頭有一個啟動選項,,好像是:/PAE /3G ,,可以讓用戶歷程最大內(nèi)存擴充至3G,這時操作系統(tǒng) 只能占用最多1G的虛存,。那樣該當可以讓JVM創(chuàng)立 更多的線程,。 因此這種情況 需要 聯(lián)合 操作系統(tǒng) 進行相干 調(diào)劑 。 因此:我們需要 聯(lián)合 不同情況 對tomcat內(nèi)存分配進行不同的診斷才干 從根本 上解決問題,。 以上就是針對Tomcat內(nèi)存溢出的幾種解決方案 ,。 |
|