Java虛擬機器(JVM)中的記憶體設定詳解
Java虛擬機器(JVM)中的記憶體設定詳解
在一些規模稍大的應用中,Java虛擬機器(JVM)的記憶體設定尤為重要,想在專案中取得好的效率,GC(垃圾回收)的設定是第一步。
PermGen space:全稱是Permanent Generation space.就是說是永久儲存的區域,用於存放Class和Meta資訊,Class在被Load的時候被放入該區域Heap space:存放Instance。
GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤
Java Heap分為3個區
1.Young
2.Old
3.Permanent
Young儲存剛例項化的物件。當該區被填滿時,GC會將物件移到Old區。Permanent區則負責儲存反射物件,本文不討論該區。
JVM的Heap分配可以使用-X引數設定,
-Xms
初始Heap大小
-Xmx
java heap最大值
-Xmn
young generation的heap大小
JVM有2個GC執行緒
第一個執行緒負責回收Heap的Young區
第二個執行緒在Heap不足時,遍歷Heap,將Young 區升級為Older區
Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因為第二個執行緒被迫執行會降低JVM的效能。
為什麼一些程式頻繁發生GC?
有如下原因:
1.程式內呼叫了System.gc()或Runtime.gc()。
2.一些中介軟體軟體呼叫自己的GC方法,此時需要設定引數禁止這些GC。
3.Java的Heap太小,一般預設的Heap值都很小。
4.頻繁例項化物件,Release物件 此時儘量儲存並重用物件,例如使用StringBuffer()和String()。
如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態,許多Server端的Java程式每次GC後最好能有65%的剩餘空間
經驗之談:
1.Server端JVM最好將-Xms和-Xmx設為相同值。為了優化GC,最好讓-Xmn值約等於-Xmx的1/3。
2.一個GUI程式最好是每10到20秒間執行一次GC,每次在半秒之內完成。
注意:
1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC執行時,所有的使用者執行緒將暫停,也就是GC期間,Java應用程式不做任何工作。
2.Heap大小並不決定程式的記憶體使用量。程式的記憶體使用量要大於-Xmx定義的值,因為Java為其他任務分配記憶體,例如每個執行緒的Stack等。
Stack的設定
每個執行緒都有他自己的Stack。
-Xss
每個執行緒的Stack大小
Stack的大小限制著執行緒的數量。如果Stack過大就好導致記憶體溢漏。-Xss引數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。
硬體環境
硬體環境也影響GC的效率,例如機器的種類,記憶體,swap空間,和CPU的數量。
如果你的程式需要頻繁建立很多transient物件,會導致JVM頻繁GC。這種情況你可以增加機器的記憶體,來減少Swap空間的使用。
4種GC
1、第一種為單執行緒GC,也是預設的GC,該GC適用於單CPU機器。
2、第二種為Throughput GC,是多執行緒的GC,適用於多CPU,使用大量執行緒的程式。第二種GC與第一種GC相似,不同在於GC在收集Young區是多執行緒的,但在Old區和第一種一樣,仍然採用單執行緒。-XX:+UseParallelGC引數啟動該GC。
3、第三種為Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程式停滯的時間。這種GC可以在Old區的回收同時,執行應用程式。-XX:+UseConcMarkSweepGC引數啟動該GC。
4、第四種為Incremental Low Pause GC,適用於要求縮短因GC造成程式停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區物件。-Xincgc引數啟動該GC。
單檔案的JVM記憶體進行設定
預設的java虛擬機器的大小比較小,在對大資料進行處理時java就會報錯:java.lang.OutOfMemoryError。
設定jvm記憶體的方法,對於單獨的.class,可以用下面的方法對Test執行時的jvm記憶體進行設定。
java -Xms64m -Xmx256m Test
-Xms是設定記憶體初始化的大小
-Xmx是設定最大能夠使用記憶體的大小(最好不要超過實體記憶體大小)
tomcat啟動jvm記憶體設定
Linux:
在/usr/local/apache-tomcat-5.5.23/bin目錄下的catalina.sh新增:JAVA_OPTS='-Xms512m -Xmx1024m'要加“m”說明是MB,否則就是KB了,在啟動tomcat時會報記憶體不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啟動tomcat,OK設定生效.夠成功的分配200M記憶體.但是如果不是執行startup.bat啟動tomcat而是利用windows的系統服務啟動tomcat服務,上面的設定就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M記憶體就OOM了..windows服務執行的是bin/tomcat.exe.他讀取登錄檔中的值,而不是catalina.bat的設定.解決辦法:
修改登錄檔HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Tomcat Service Manager/Tomcat5/Parameters/JavaOptions
原值為
-Dcatalina.home="C:/ApacheGroup/Tomcat 5.0"
-Djava.endorsed.dirs="C:/ApacheGroup/Tomcat 5.0/common/endorsed"
-Xrs加入 -Xms300m -Xmx350m
重起tomcat服務,設定生效
weblogic啟動jvm記憶體設定
在weblogic中,可以在startweblogic.cmd中對每個domain虛擬記憶體的大小進行設定,預設的設定是在commEnv.cmd裡面。
JBoss
預設可以使用的記憶體為64MB
$JBOSSDIR$/bin/run.config
JAVA_OPTS = "-server -Xms128 -Xmx512"
Eclipse
在所在目錄下,鍵入
eclipse.exe -vmargs -Xms256m -Xmx512m
256m表示JVM堆記憶體最小值
512m表示JVM堆記憶體最大
Websphere
進入控制檯去設定:應用程式伺服器 > server1 > 程式定義 > Java 虛擬機器
JAVA_OPTS為:-Xms 520m -Xmx 1500m -Xss 128k
jboss效能優化:記憶體緊張的問題
JAVA_OPTS: -Xms 520m -Xmx 1220m -Xss 15120k +XX:AggressiveHeap
這個JAVA_OPTS犯了2個致命的錯誤:
1. +XX:AggressiveHeap會使得 Xms 1220m沒有意義。這個引數讓jvm忽略Xmx引數,瘋狂地吃完一個G實體記憶體,再吃盡一個G的swap。
另外Xmx作為允許jvm使用的最大記憶體數量,不應該超過實體記憶體的90%。
而之所以使用了這個引數,是因為不加的話,JBoss會在執行一天左右的時間後迅速崩潰,上機課是,甚至出現過半個小時就崩潰的情況。
之所以要用這個引數,用swap支援伺服器執行,是因為犯了下面的錯誤:
2. -Xss 15120k
這使得JBoss每增加一個執行緒(thread)就會立即消耗15M記憶體,而最佳值應該是128K,預設值好像是512k.
3. -Xms指定初始化記憶體大小
所作的修改:
1.修改JAVA_OPTS,去掉+XX:AggressiveHeap,修改Xss。現在的JAVA_OPTS為:
-Xms 520m -Xmx 1500m -Xss 128k
2.修改deploy/jbossweb-tomcat55.sar/service.xml
將maxThreads根據目前的訪問量由預設的250降為75,並使用jboss 4預設未寫在標準service.xml裡面而jboss 3寫入了的2個引數:
maxSparseThreads=200,minSparseThreads=100
3.修改oracle-ds.xml將最大連線數有150降為50.
JVM的垃圾回收機制詳解和調優
1.JVM的gc概述
為放置所有的複製全部發生以及希望物件從eden擴充套件到舊域,可以把MaxTenuring Threshold設定成0.設定完成後,實際上就不再使用救助空間了,因此應把SurvivorRatio設成最大值以最大化Eden空間,設定如下: |
一、設定JVM記憶體設定
1. 設定JVM記憶體的引數有四個:
-Xmx Java Heap最大值,預設值為實體記憶體的1/4,最佳設值應該視實體記憶體大小及計算機內其他記憶體開銷而定;
-Xms Java Heap初始值,Server端JVM最好將-Xms和-Xmx設為相同值,開發測試機JVM可以保留預設值;
-Xmn Java Heap Young區大小,不熟悉最好保留預設值;
-Xss 每個執行緒的Stack大小,不熟悉最好保留預設值;
2. 如何設定JVM記憶體分配:
(1)當在命令提示符下啟動並使用JVM時(只對當前執行的類Test生效):
java -Xmx128m -Xms64m -Xmn32m -Xss16m Test
(2)當在整合開發環境下(如eclipse)啟動並使用JVM時:
a. 在eclipse根目錄下開啟eclipse.ini,預設內容為(這裡設定的是執行當前開發工具的JVM記憶體分配):
-vmargs -Xms40m -Xmx256m -vmargs表示以下為虛擬機器設定引數,可修改其中的引數值,也可新增-Xmn,-Xss,另外,eclipse.ini內還可以設定非堆記憶體,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。
此處設定的引數值可以通過以下配置在開發工具的狀態列顯示:
在eclipse根目錄下建立檔案options,檔案內容為:org.eclipse.ui/perf/showHeapStatus=true
修改eclipse根目錄下的eclipse.ini檔案,在開頭處新增如下內容:
-debug options -vm javaw.exe 重新啟動eclipse,就可以看到下方狀態條多了JVM資訊。
b. 開啟eclipse-視窗-首選項-Java-已安裝的JRE(對在當前開發環境中執行的java程式皆生效)
編輯當前使用的JRE,在預設VM引數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m
c. 開啟eclipse-執行-執行-Java應用程式(只對所設定的java類生效)
選定需設定記憶體分配的類-自變數,在VM自變數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m
注:如果在同一開發環境中同時進行了b和c設定,則b設定生效,c設定無效,如:
開發環境的設定為:-Xmx256m,而類Test的設定為:-Xmx128m -Xms64m,則執行Test時生效的設定為:
-Xmx256m -Xms64m
(3)當在伺服器環境下(如Tomcat)啟動並使用JVM時(對當前伺服器環境下所以Java程式生效):
a. 設定環境變數:
變數名:CATALINA_OPTS
變數值:-Xmx128m -Xms64m -Xmn32m -Xss16m
b. 開啟Tomcat根目錄下的bin資料夾,編輯catalina.bat,將其中的�TALINA_OPTS%(共有四處)替換為:-Xmx128m -Xms64m -Xmn32m -Xss16m
二、檢視設定JVM記憶體資訊
Runtime.getRuntime().maxMemory(); //最大可用記憶體,對應-Xmx
Runtime.getRuntime().freeMemory(); //當前JVM空閒記憶體
Runtime.getRuntime().totalMemory(); //當前JVM佔用的記憶體總數,其值相當於當前JVM已使用的記憶體及freeMemory()的總和
關於maxMemory(),freeMemory()和totalMemory():
maxMemory()為JVM的最大可用記憶體,可通過-Xmx設定,預設值為實體記憶體的1/4,設值不能高於計算機實體記憶體;
totalMemory()為當前JVM佔用的記憶體總數,其值相當於當前JVM已使用的記憶體及freeMemory()的總和,會隨著JVM使用記憶體的增加而增加;
freeMemory()為當前JVM空閒記憶體,因為JVM只有在需要記憶體時才佔用實體記憶體使用,所以freeMemory()的值一般情況下都很小,而JVM實際可用記憶體並不等於freeMemory(),而應該等於maxMemory()-totalMemory()+freeMemory()。及其設定JVM記憶體分配。
在一些規模稍大的應用中,Java虛擬機器(JVM)的記憶體設定尤為重要,想在專案中取得好的效率,GC(垃圾回收)的設定是第一步。
PermGen space:全稱是Permanent Generation space.就是說是永久儲存的區域,用於存放Class和Meta資訊,Class在被Load的時候被放入該區域Heap space:存放Instance。
GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤
Java Heap分為3個區
1.Young
2.Old
3.Permanent
Young儲存剛例項化的物件。當該區被填滿時,GC會將物件移到Old區。Permanent區則負責儲存反射物件,本文不討論該區。
JVM的Heap分配可以使用-X引數設定,
-Xms
初始Heap大小
-Xmx
java heap最大值
-Xmn
young generation的heap大小
JVM有2個GC執行緒
第一個執行緒負責回收Heap的Young區
第二個執行緒在Heap不足時,遍歷Heap,將Young 區升級為Older區
Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因為第二個執行緒被迫執行會降低JVM的效能。
為什麼一些程式頻繁發生GC?
有如下原因:
1.程式內呼叫了System.gc()或Runtime.gc()。
2.一些中介軟體軟體呼叫自己的GC方法,此時需要設定引數禁止這些GC。
3.Java的Heap太小,一般預設的Heap值都很小。
4.頻繁例項化物件,Release物件 此時儘量儲存並重用物件,例如使用StringBuffer()和String()。
如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態,許多Server端的Java程式每次GC後最好能有65%的剩餘空間
經驗之談:
1.Server端JVM最好將-Xms和-Xmx設為相同值。為了優化GC,最好讓-Xmn值約等於-Xmx的1/3。
2.一個GUI程式最好是每10到20秒間執行一次GC,每次在半秒之內完成。
注意:
1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC執行時,所有的使用者執行緒將暫停,也就是GC期間,Java應用程式不做任何工作。
2.Heap大小並不決定程式的記憶體使用量。程式的記憶體使用量要大於-Xmx定義的值,因為Java為其他任務分配記憶體,例如每個執行緒的Stack等。
Stack的設定
每個執行緒都有他自己的Stack。
-Xss
每個執行緒的Stack大小
Stack的大小限制著執行緒的數量。如果Stack過大就好導致記憶體溢漏。-Xss引數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。
硬體環境
硬體環境也影響GC的效率,例如機器的種類,記憶體,swap空間,和CPU的數量。
如果你的程式需要頻繁建立很多transient物件,會導致JVM頻繁GC。這種情況你可以增加機器的記憶體,來減少Swap空間的使用。
4種GC
1、第一種為單執行緒GC,也是預設的GC,該GC適用於單CPU機器。
2、第二種為Throughput GC,是多執行緒的GC,適用於多CPU,使用大量執行緒的程式。第二種GC與第一種GC相似,不同在於GC在收集Young區是多執行緒的,但在Old區和第一種一樣,仍然採用單執行緒。-XX:+UseParallelGC引數啟動該GC。
3、第三種為Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程式停滯的時間。這種GC可以在Old區的回收同時,執行應用程式。-XX:+UseConcMarkSweepGC引數啟動該GC。
4、第四種為Incremental Low Pause GC,適用於要求縮短因GC造成程式停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區物件。-Xincgc引數啟動該GC。
單檔案的JVM記憶體進行設定
預設的java虛擬機器的大小比較小,在對大資料進行處理時java就會報錯:java.lang.OutOfMemoryError。
設定jvm記憶體的方法,對於單獨的.class,可以用下面的方法對Test執行時的jvm記憶體進行設定。
java -Xms64m -Xmx256m Test
-Xms是設定記憶體初始化的大小
-Xmx是設定最大能夠使用記憶體的大小(最好不要超過實體記憶體大小)
tomcat啟動jvm記憶體設定
Linux:
在/usr/local/apache-tomcat-5.5.23/bin目錄下的catalina.sh新增:JAVA_OPTS='-Xms512m -Xmx1024m'要加“m”說明是MB,否則就是KB了,在啟動tomcat時會報記憶體不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啟動tomcat,OK設定生效.夠成功的分配200M記憶體.但是如果不是執行startup.bat啟動tomcat而是利用windows的系統服務啟動tomcat服務,上面的設定就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M記憶體就OOM了..windows服務執行的是bin\tomcat.exe.他讀取登錄檔中的值,而不是catalina.bat的設定.解決辦法:
修改登錄檔HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions
原值為
-Dcatalina.home="C:\ApacheGroup\Tomcat 5.0"
-Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed"
-Xrs加入 -Xms300m -Xmx350m
重起tomcat服務,設定生效
weblogic啟動jvm記憶體設定
在weblogic中,可以在startweblogic.cmd中對每個domain虛擬記憶體的大小進行設定,預設的設定是在commEnv.cmd裡面。
JBoss
預設可以使用的記憶體為64MB
$JBOSSDIR$/bin/run.config
JAVA_OPTS = "-server -Xms128 -Xmx512"
Eclipse
在所在目錄下,鍵入
eclipse.exe -vmargs -Xms256m -Xmx512m
256m表示JVM堆記憶體最小值
512m表示JVM堆記憶體最大
Websphere
進入控制檯去設定:應用程式伺服器 > server1 > 程式定義 > Java 虛擬機器
在/usr/tomcat/bin/catalina.sh中加入
export JAVA_OPTS='-Xms[初始化記憶體大小] -Xmx[可以使用最大記憶體]'
例如:export JAVA_OPTS='-Xms256m -Xmx512m'
Windows上:
在catalina.bat裡設定初始記憶體和最大記憶體:
set CATALINA_OPTS="-Xms30m -Xmx512m"
檢查一下Catalina.bat檔案,在每個“%_RUNJAVA%”後面都應該有“�TALINA_OPTS%”
有的Catalina.bat檔案在“%_RUNJAVA%”後面跟著“%JAVA_OPTS%”,
如果是這樣,應該設定:
set JAVA_OPTS=-Xms30m -Xmx512m
或者在每個“%_RUNJAVA%”後面加上“�TALINA_OPTS%”
------------------------------------
如何設定Tomcat的JVM虛擬機器記憶體大小
可以給Java虛擬機器設定使用的記憶體,但是如果你的選擇不對的話,虛擬機器不會補償。可通過命令列的方式改變虛擬機器使用記憶體的大小。如下表所示有兩個引數用來設定虛擬機器使用記憶體的大小。
引數
描述
-Xms
JVM初始化堆的大小
-Xmx
JVM堆的最大值
這 兩個值的大小一般根據需要進行設定。初始化堆的大小執行了虛擬機器在啟動時向系統申請的記憶體的大小。一般而言,這個引數不重要。但是有的應用程式在大負載的 情況下會急劇地佔用更多的記憶體,此時這個引數就是顯得非常重要,如果虛擬機器啟動時設定使用的記憶體比較小而在這種情況下有許多物件進行初始化,虛擬機器就必須 重複地增加記憶體來滿足使用。由於這種原因,我們一般把-Xms和-Xmx設為一樣大,而堆的最大值受限於系統使用的實體記憶體。一般使用資料量較大的應用程 序會使用持久物件,記憶體使用有可能迅速地增長。當應用程式需要的記憶體超出堆的最大值時虛擬機器就會提示記憶體溢位,並且導致應用服務崩潰。因此一般建議堆的最 大值設定為可用記憶體的最大值的80%。
Tomcat預設可以使用的記憶體為128MB,在較大型的應用專案中,這點記憶體是不夠的,需要調大。
Windows下,在檔案/bin/catalina.bat,Unix下,在檔案/bin/catalina.sh的前面,增加如下設定:
JAVA_OPTS='-Xms【初始化記憶體大小】 -Xmx【可以使用的最大記憶體】'
需要把這個兩個引數值調大。例如:
JAVA_OPTS='-Xms256m -Xmx512m'
表示初始化記憶體為256MB,可以使用的最大記憶體為512MB。
另 外需要考慮的是Java提供的垃圾回收機制。虛擬機器的堆大小決定了虛擬機器花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應用有關,應該通過分析 實際的垃圾收集的時間和頻率來調整。如果堆的大小很大,那麼完全垃圾收集就會很慢,但是頻度會降低。如果你把堆的大小和記憶體的需要一致,完全收集就很快, 但是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。在基準測試的時候,為保證最好的效能,要把堆的大小 設大,保證垃圾收集不在整個基準測試的過程中出現。
如果系統花費很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應該不超過 3-5 秒。如果垃圾收整合為瓶頸,那麼需要指定代的大小,檢查垃圾收集的詳細輸出,研究 垃圾收集引數對效能的影響。一般說來,你應該使用實體記憶體的 80% 作為堆大小。當增加處理器時,記得增加記憶體,因為分配可以並行進行,而垃圾收集不是並行的。
Tomcat 5常用優化和配置
1、JDK記憶體優化:
Tomcat預設可以使用的記憶體為128MB,Windows下,在檔案{tomcat_home}/bin/catalina.bat,Unix下,在檔案{tomcat_home}/bin/catalina.sh的前面,增加如下設定:
JAVA_OPTS='-Xms[初始化記憶體大小] -Xmx[可以使用的最大記憶體]
一般說來,你應該使用實體記憶體的 80% 作為堆大小。
2、聯結器優化:
在tomcat配置檔案server.xml中的配置中,和連線數相關的引數有:
maxThreads:
Tomcat使用執行緒來處理接收的每個請求。這個值表示Tomcat可建立的最大的執行緒數。預設值150。
acceptCount:
指定當所有可以使用的處理請求的執行緒數都被使用時,可以放到處理佇列中的請求數,超過這個數的請求將不予處理。預設值10。
minSpareThreads:
Tomcat初始化時建立的執行緒數。預設值25。
maxSpareThreads:
一旦建立的執行緒超過這個值,Tomcat就會關閉不再需要的socket執行緒。預設值75。
enableLookups:
是否反查域名,預設值為true。為了提高處理能力,應設定為false
connnectionTimeout:
網路連線超時,預設值60000,單位:毫秒。設定為0表示永不超時,這樣設定有隱患的。通常可設定為30000毫秒。
maxKeepAliveRequests:
保持請求數量,預設值100。
bufferSize:
輸入流緩衝大小,預設值2048 bytes。
compression:
壓縮傳輸,取值on/off/force,預設值off。
其中和最大連線數相關的引數為maxThreads和acceptCount。如果要加大併發連線數,應同時加大這兩個引數。web server允許的最大連線數還受制於*作系統的核心引數設定,通常Windows是2000個左右,Linux是1000個左右。
3、tomcat中如何禁止和允許列目錄下的檔案
在{tomcat_home}/conf/web.xml中,把listings引數設定成false即可,如下:
<servlet>
...
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
...
</servlet>
4、tomcat中如何禁止和允許主機或IP地址訪問
<Host name="localhost" ...>
...
<Valve className="org.apache.catalina.valves.RemoteHostValve"
allow="*.mycompany.com,www.yourcompany.com"/>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="192.168.1.*"/>
...
</Host>
伺服器的配置
JAVA_OPTS='-server -Xms512m -Xmx768m -XX:NewSize=128m -XX:MaxNewSize=192m -XX:SurvivorRatio=8'
tomcat 的jvm 記憶體溢位問題的解決
最近在熟悉一個開發了有幾年的專案,需要把資料庫從mysql移植到oracle,首先把jdbc的連線指向mysql,打包放到tomcat裡面,可以跑起來,沒有問題,可是當把jdbc連線指向oracle的時候,tomcat就連續拋java.lang.OutOfMemoryError的錯誤,上網google了一下,瞭解了一下tomcat的執行機制,也解決了問題,share出來,以備查。
1、首先是:java.lang.OutOfMemoryError: Java heap space
解釋:
Heap size 設定
JVM堆的設定是指java程式執行過程中JVM可以調配使用的記憶體空間的設定.JVM在啟動的時候會自動設定Heap
size的值,其初始空間(即-Xms)是實體記憶體的1/64,最大空間(-Xmx)是實體記憶體的1/4。可以利用JVM提供的-Xmn -Xms
-Xmx等選項可進行設定。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
提示:在JVM中如果98%的時間是用於GC且可用的Heap size 不足2%的時候將丟擲此異常資訊。
提示:Heap Size 最大不要超過可用實體記憶體的80%,一般的要將-Xms和-Xmx選項設定為相同,而-Xmn為1/4的-Xmx值。
解決方法:
手動設定Heap size
修改TOMCAT_HOME/bin/catalina.bat,在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
Java程式碼
- set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m或修改catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
2、其次是:java.lang.OutOfMemoryError: PermGen space
原因:
PermGen space的全稱是Permanent Generation
space,是指記憶體的永久儲存區域,這塊記憶體主要是被JVM存放Class和Meta資訊的,Class在被Loader時就會被放到PermGen
space中,它和存放類例項(Instance)的Heap區域不同,GC(Garbage
Collection)不會在主程式執行期對PermGen space進行清理,所以如果你的應用中有很CLASS的話,就很可能出現PermGen
space錯誤,這種錯誤常見在web伺服器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar,
其大小超過了jvm預設的大小(4M)那麼就會產生此錯誤資訊了。
解決方法:
1. 手動設定MaxPermSize大小
修改TOMCAT_HOME/bin/catalina.bat(Linux下為catalina.sh),在Java程式碼 - “echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: [*]set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m “echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:set
JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m
catalina.sh下為:
Java程式碼 - JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m" JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m"另外看到了另外一個帖子,覺得挺好,摘抄如下:
分析java.lang.OutOfMemoryError: PermGen space
發現很多人把問題歸因於: spring,hibernate,tomcat,因為他們動態產生類,導致JVM中的permanent heap溢位 。然後解決方法眾說紛紜,有人說升級 tomcat版本到最新甚至乾脆不用tomcat。還有人懷疑spring的問題,在spring論壇上討論很激烈,因為spring在AOP時使用CBLIB會動態產生很多類。
但問題是為什麼這些王牌的開源會出現同一個問題呢,那麼是不是更基礎的原因呢?tomcat在Q&A很隱晦的回答了這一點,我們知道這個問題,但這個問題是由一個更基礎的問題產生。
於是有人對更基礎的JVM做了檢查,發現了問題的關鍵。原來SUN
的JVM把記憶體分了不同的區,其中一個就是permenter區用來存放用得非常多的類和類描述。本來SUN設計的時候認為這個區域在JVM啟動的時候就
固定了,但他沒有想到現在動態會用得這麼廣泛。而且這個區域有特殊的垃圾收回機制,現在的問題是動態載入類到這個區域後,gc根本沒辦法回收!
對於以上兩個問題,我的處理是:
在catalina.bat的第一行增加:
Java程式碼 - set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m在catalina.sh的第一行增加:
Java程式碼
- JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
- 原文出處:http://aiape.iteye.com/blog/1485491
相關文章
- 關於虛擬機器記憶體和JVM記憶體設定的思考虛擬機記憶體JVM
- Java虛擬機器記憶體區域詳解Java虛擬機記憶體
- JVM虛擬機器詳解JVM虛擬機
- win10虛擬記憶體怎麼設定 win10虛擬記憶體設定步驟詳解Win10記憶體
- JAVA 虛擬機器可用記憶體Java虛擬機記憶體
- Java 虛擬機器之三:Java虛擬機器的記憶體結構Java虛擬機記憶體
- Java8虛擬機器(JVM)記憶體溢位實戰Java虛擬機JVM記憶體溢位
- 對jvm虛擬機器 記憶體溢位的思考JVM虛擬機記憶體溢位
- 詳解Java 虛擬機器(第⑥篇)——記憶體分配與回收策略Java虛擬機記憶體
- Java虛擬機器詳解(二)------執行時記憶體結構Java虛擬機記憶體
- JVM(二)Java虛擬機器組成詳解JVMJava虛擬機
- JVM虛擬機器記憶體結構簡析JVM虛擬機記憶體
- jvm記憶體區域之虛擬機器棧JVM記憶體虛擬機
- jdk8:jvm虛擬機器記憶體模型JDKJVM虛擬機記憶體模型
- 深入理解JVM虛擬機器-JVM記憶體區域與記憶體溢位JVM虛擬機記憶體溢位
- 深入理解Java虛擬機器之JVM記憶體佈局篇Java虛擬機JVM記憶體
- 【伺服器】Ubuntu虛擬記憶體設定伺服器Ubuntu記憶體
- Java虛擬機器之記憶體區域Java虛擬機記憶體
- 【JVM之記憶體與垃圾回收篇】虛擬機器棧JVM記憶體虛擬機
- Java虛擬機器(JVM)Java虛擬機JVM
- java虛擬機器記憶體的各個區域Java虛擬機記憶體
- eclipse中設定JVM記憶體EclipseJVM記憶體
- Java虛擬機器記憶體模型學習筆記Java虛擬機記憶體模型筆記
- win10虛擬記憶體怎麼設定 win10虛擬記憶體設定方法Win10記憶體
- 怎麼設定虛擬記憶體win10 win10虛擬記憶體如何設定記憶體Win10
- Java虛擬機器記憶體分配與回收策略Java虛擬機記憶體
- Java虛擬機器記憶體區域劃分Java虛擬機記憶體
- win10電腦虛擬記憶體怎麼設定 win10虛擬記憶體設定的方法Win10記憶體
- Java虛擬機器的記憶體空間有幾種Java虛擬機記憶體
- Java虛擬機器的記憶體空間有幾種!Java虛擬機記憶體
- 深入理解JVM虛擬機器11:Java記憶體異常原理與實踐JVM虛擬機Java記憶體
- Java虛擬機器:Jvm概念和原理詳解以及GC機制的分析Java虛擬機JVMGC
- JVM虛擬機器和Oracle資料庫記憶體管理的學習JVM虛擬機Oracle資料庫記憶體
- win10虛擬記憶體怎麼設定最好 win10虛擬記憶體設定多少好Win10記憶體
- Java虛擬機器:記憶體管理與執行引擎Java虛擬機記憶體
- JVM掃盲-3:虛擬機器記憶體模型與高效併發JVM虛擬機記憶體模型
- 深入理解JVM虛擬機器1:JVM記憶體的結構與消失的永久代JVM虛擬機記憶體
- win10 虛擬記憶體怎麼設定好 win10 虛擬記憶體設定方法Win10記憶體
- 解讀JVM虛擬機器JVM虛擬機