專案越做越大,啟動載入JAVA記憶體佔用就130M了,點點就記憶體溢出,經調整解決。附下面文檔已是記錄。

 

來源:青菜貓 - BlogJAVA

 

  Tomcat預設可以使用的記憶體為128MB,在較大型的應用專案中,這點記憶體是不夠的,輕微時,會使系統性能急劇下降,嚴重時,將導致系統無法運行,影響系統的穩定性。當記憶體不夠用時,常見的問題就是報tomcat記憶體益處錯誤,從兒導致用戶端包500錯誤的,如下:解決方法主要是加大TOMCAT可利用記憶體,並在程式當中加大記憶體使用。因此根據應用的需求,有必要調整JVM使用記憶體的大小。現在將手工修改tomcat記憶體的方法及注意事項列出,希望能對新人有所説明。

 

  tomcat提供了兩種安裝模式,即免安裝(*.zip)和安裝(*.exe)方式。針對不同的安裝方式下修改tomcat記憶體大小的方法幾注意問題(windows環境):

 

  方式1:當選擇安裝方式時,可以在安裝tomcat的過程進行設置tomcat初始化記憶體的大小。但是假如說在安裝時沒有選擇,或者應用改變了,需要增加tomcat記憶體時怎麼半呢?此時,我們就要手工修改tomcat的一些檔了。

 

  看了很多網上的資料,都是說修改<CATALINA_HOME>\bin\catalina.bat檔的內容,即在裡面增加一行代碼:

 

set JAVA_OPTS=-Xms512m -Xmx512m //表示初始化最小可用記憶體和最大可用記憶體都是512MB(修改相應值即可)

 

  如在catalina.bat的

 

rem ----- Execute The Requested Command

 

echo Using CATALINA_BASE: %CATALINA_BASE%

 

echo Using CATALINA_HOME: %CATALINA_HOME%

 

echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR%

 

echo Using JAVA_HOME: %JAVA_HOME%

 

  這一欄改為

 

rem ----- Execute The Requested Command

 

set JAVA_OPTS=-Xms512m -Xmx512m

 

echo Using CATALINA_BASE: %CATALINA_BASE%

 

echo Using CATALINA_HOME: %CATALINA_HOME%

 

echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR%

 

echo Using JAVA_HOME: %JAVA_HOME%

 

  就可以將JAVA虛擬機器分配記憶體 508.0625MB的!

 

  但是很多人修改後,發現修改並沒有起作用,即通過windows的服務啟動tomcat時,實際的記憶體還是預設的,修改的設置並沒有起作用;而通過<CATALINA_HOME>\bin\startup.bat 啟動卻是生效的。這是為什麼呢?因為在安裝過程中,JVM的初始化參數已經寫在註冊表中了,由於沒有修改註冊表中相關參數,所以以windows服務方式啟動時,修改的並沒有生效。而通過<CATALINA_HOME>\bin\startup.bat 啟動直接是通過<CATALINA_HOME>\bin\catalina.bat檔中的配置的。你需要重新載入到系統服務中才生效,或者你手工在註冊表中查找修改啟動值,載入到服務中的時候參數已經配置好了,自己修改artup.bat不會改變註冊表中的參數設置。

 

  解決方法:修改註冊表中的參數,加入JVM初始化記憶體的參數:

 

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

 

  如加入 -Xms512m -Xmx800m

 

  方式2:針對免安裝的使用者,也可以通過將tomcat註冊為windows的一個服務的方式來實現:我們可以對service.bat檔做一些其他修改,使tomcat更加能滿足我們各種不同需求時的要求

 

1. 如果讓tomcat編譯jsp檔,就在PR_CLASSPATH中加入J2SDK的tools.jar

 

  修改前:

 

set PR_CLASSPATH=%CATALINA_HOME%\bin\bootstrap.jar

 

  修改後:

 

set PR_CLASSPATH=%JAVA_HOME%\lib\tools.jar; %CATALINA_HOME%\bin\bootstrap.jar

 

  2.要使用一個特定的JVM,就要修改jvm的參數;要使註冊的windows服務的啟動方式為自動,增加--Startup Automatic,這個是比較常用的;要用定制的server.xml設定檔並且傳遞多個參數給StartClass,要修改StartParams的值,各個值之間用分號分隔:
 
 修改前:
 
"%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm auto
 
--StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap
 
--StartParams start --StopParams stop
 
  修改後:
 
"%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll"
 
--StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap
 
--StartParams "-config; %CUSTOM_SERVERXML_FILE%; -nonaming; start" --StopParams stop
 
--Startup Automatic
 
  3. 指定最大和最小的記憶體限制,要增加jvm的初始參數
 
  修改前:
 
"%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions
 
"-Dcatalina.base=%CATALINA_BASE%; -Dcatalina.home=%CATALINA_HOME%; -Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed"
 
--StartMode jvm --StopMode jvm
 
  修改後:
 
"%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions
 
"-Xms128M; -Xmx256M; -Dcatalina.base=%CATALINA_BASE%; -Dcatalina.home=%CATALINA_HOME%; -Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed"
 
--StartMode jvm --StopMode jvm
 
  4.有時註冊windows服務成功後,但是啟動服務時顯示「發生服務特定錯誤: 0.」就是因為jvm沒有指定,修改Jvm auto為Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll"後重新註冊windows服務就可以啟動了。
最近看了阿裡《文初的專欄》OOM和JVM配置優化(二)
 
感覺他把這個問題講透了,現記錄下來:
 
記憶體分配以及管理的幾個基本概念和參數說明:
 
JAVA Hotspot Mode:
 
server 和 client兩種模式,如果不配置,JVM會根據應用伺服器硬體設定自動選擇模式,server模式啟動比較慢,但是運行期速度得到了優化,client啟動比較快,但是運行期回應沒有server模式的優化,適合於個人PC的服務開發和測試。


 
Garbage Collector Policy:
 
在Jdk 1.5的時候已經提供了三種GC,除了原來提供的串列GC(SerialGC)以外,還提供了兩種新的GC:ParallelGC和ConcMarkSweepGC。ParallelGC採用了多執行緒並行管理和回收垃圾物件,提高了回收效率,提高了伺服器的輸送量,適合於多處理器的伺服器。ConcMarkSweepGC採用的是併發方式來管理和回收垃圾物件,降低垃圾回收產生的回應暫停時間。這裡說一下併發和並行的區別,併發指的是多個進程並存執行垃圾回收,那麼可以很好的利用多處理器,而並行指的是應用程式不需要暫停可以和垃圾回收執行緒併發工作。串列GC適合小型應用和單處理器系統(無需多執行緒交互,效率比較高),後兩者適合大型系統。
 
使用方式就是在參數配置中增加-XX:+UseParallelGC等方式來設置。
 
對於這部分的配置在網上有很多的實例可以參考,不過最終採用哪一種GC還是要根據具體的情況來分析和選擇。


 
Heap:
 
OOM的各種經歷已經讓每一個架構師開發人員看到了瞭解Heap的重要性。OOM已經是Heap的臨界點,不得不引起注意,然而Heap對於性能的潛在影響並未被引起重視,不過和GC配置一樣,在沒有對使用方式作仔細分析和研究的情況下,貿然的去修改Heap配置,可能適得其反,這裡就來看一下Heap的一些概念和對於性能的影響。
 
我們的應用所能夠得到的最大的Heap受三部分因素的制約:資料處理模型(32位或者64位作業系統),系統地虛擬記憶體總數和系統的實體記憶體總數。首先Heap的大小不能超過不同作業系統的進程定址範圍,當前大部分系統最高限度是4G,Windows通常是2G,Linux通常是3G。系統的虛擬記憶體也是分配的依據,首先是不能超過,然後由於作業系統支援硬碟來做部分的虛擬記憶體,如果設置過大,那麼對於應用回應來說勢必有影響。再則就是要考慮同一台伺服器上運行多個JAVA虛擬機器所消耗的資源總合也不能超過可用資源。就和前面OOM分析中的一樣,其實由於OS的資料處理模型的限制,機器本身的硬體記憶體資源和虛擬記憶體資源並不一定會匹配,那麼在有限的資源下如何調整好資源配置,對於應用來說尤為重要。




 
關於Heap的幾個參數設置:
 
說了Heap的有限資源問題以後,就來看看如何通過配置去改變JVM對於Heap的分配。下面所說的主要是對於JAVA Heap的分配,那麼在申請了JAVA Heap以後,剩下的可用資源就會被使用到Native Heap。
 
Xms: java heap初始化時的大小。預設情況是機器實體記憶體的1/64。這個主要是根據應用啟動時消耗的資源決定,分配少了申請起來會降低啟動速度,分配多了也浪費。
 
 
Xmx:java heap的最大值,預設是機器實體記憶體的1/4,最大也就到1G。這個值決定了最多可用的JAVA Heap Memory,分配過少就會在應用需要大量記憶體作緩存或者零時物件時出現OOM的問題,如果分配過大,那麼就會產生上文提到的第二類OOM。所以如何配置還是根據運行過程中的分析和計算來確定,如果不能確定還是採用預設的配置。
 
Xmn:java heap新生代的空間大小。在GC模型中,根據物件的生命週期的長短,產生了記憶體分代的設計:青年代(內部也分成三部分,類似于整體劃分的作用,可以通過配置來設置比例),老年代,持久代。每一代的管理和回收策略都不相同,最為活躍的就是青年代,同時這部分的記憶體分配和管理效率也是最高。通常情況下,對於記憶體的申請優先在新生代中申請,當記憶體不夠時會整理新生代,當整理以後還是不能滿足申請的記憶體,就會向老年代移動一些生命週期較長的物件。這種整理和移動會消耗資源,同時降低系統運行回應能力,因此如果青年代設置的過小,就會頻繁的整理和移動,對性能造成影響。那是否把年青代設置的越大越好,其實不然,年青代採用的是複製搜集演算法,這種演算法必須停止所有應用程式執行緒,伺服器執行緒切換時間就會成為應用回應的瓶頸(當然永遠不用收集那麼就不存在這個問題)。老年代採用的是串列標記收集的方式,併發收集可以減少對於應用的影響。
 
Xss:執行緒堆疊最大值。允許更多的虛擬記憶體空間位址被JAVA Heap使用。


 
以下是sun公司的性能優化白皮書中提到的幾個例子:


 
1.對於輸送量的調優。機器配置:4G的記憶體,32個執行緒併發能力。
 
java
 
-Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20


 
-Xmx3800m -Xms3800m
 
配置了最大JAVA Heap來充分利用系統記憶體。


 
-Xmn2g
 
創建足夠大的青年代(可以並行被回收)充分利用系統記憶體,防止將短期物件複製到老年代。
 
-Xss128
 
減少預設最大的執行緒棧大小,提供更多的處理虛擬記憶體位址空間被進程使用。
 
-XX:+UseParallelGC
 
採用並行垃圾收集器對年青代的記憶體進行收集,提高效率。
 
-XX:ParallelGCThreads=20
 
減少垃圾收集執行緒,預設是和伺服器可支援的執行緒最大併發數相同,往往不需要配置到最大值。


 
2
 
嘗試採用對老年代並行收集
 
java
 
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
 
-Xmx3550m -Xms3550m
 
記憶體分配被減小,因為ParallelOldGC會增加對於Native Heap的需求,因此需要減小JAVA Heap來滿足需求。
 
-XX:+UseParallelOldGC
 
採用對於老年代併發收集的策略,可以提高收集效率。


 
3
 
提高輸送量,減少應用停頓時間
 
java
 
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31


 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
 
選擇了併發標記交換收集器,它可以併發執行收集操作,降低應用停止時間,同時它也是並行處理模式,可以有效地利用多處理器的系統的多進程處理。


 
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=31
 
表示在青年代中Eden和Survivor比例,設置增加了Survivor的大小,越大的survivor空間可以允許短期物件儘量在年青代消亡。


 
-XX:TargetSurvivorRatio=90
 
允許90%的空間被佔用,超過預設的50%,提高對於survivor的使用率

 

arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()