WebLogic用了一段時(shí)間之後,偶爾總是會(huì)出現(xiàn)OutOfMemory,這對(duì)測(cè)試環(huán)境來(lái)說(shuō),還只要Restart Server 就可以解決,但是在正式環(huán)境上出現(xiàn)可就麻煩大了,因?yàn)橐籖estart Server 所有User就都無(wú)法使用系統(tǒng),所以MEM_ARGS這個(gè)參數(shù)的設(shè)定就很重要。
這是我SIT目前的設(shè)定,依不同的系統(tǒng)做不同的設(shè)定
MEM_ARGS="-Xms768m -Xmx768m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=384m -XX:PermSize=384m -XX:SurvivorRatio=6 -XX:+DisableExplicitGC"
提示:以上記得要寫(xiě)成一行。
Heap Size設(shè)定
-Xms 設(shè)定一開(kāi)始的Heap Size。
-Xmx 設(shè)定Heap Size的最大值 (最好是不是超過(guò)實(shí)體記憶體的80%)。
-XX:NewSize 調(diào)整JVM的Young Generation的size大小。
-XX:MaxNewSize 調(diào)整JVM的Young Generation的size的最大值。
- Xmn Young Generation的size,NewSize 和 MaxNewSize設(shè)定為一樣。
-XX:NewRatio 控制Young generation的比例,如-XX:NewRatio=3表示Young generation與Old generation的比例為1:3,即Young generation佔(zhàn)1/4,Old generation佔(zhàn)3/4。
Young generation又被分成三部分,第一部分Eden,用於生成新的Object。另外兩個(gè)部分為Survivor空間,當(dāng)Eden用完後,會(huì)將 Objects複製到"SS1",當(dāng)SS1空間滿了的時(shí)候,再被複製到"SS2",Objects會(huì)在Survivor空間不斷的被複製,直到他滿足條件進(jìn)入Old generation止。
提示:如果將Heap Size設(shè)的越大,GC的週期就會(huì)拉長(zhǎng),而且每次GC的時(shí)間也會(huì)越長(zhǎng)。
PermGen space
-XX:PermSize 這一部分是用於存放Class和Meta的訊息,Class在被 Load的時(shí)候被放入PermGen space區(qū)域,它和和存放Instance的Heap區(qū)域不同,GC(Garbage Collection)不會(huì)在主程式運(yùn)行期間對(duì)PermGen space進(jìn)行清理,所以如果你的APP會(huì)LOAD很多CLASS的話,就很可能出現(xiàn)PermGen space錯(cuò)誤。這種錯(cuò)誤常見(jiàn)在web伺服器對(duì)JSP進(jìn)行pre compile的時(shí)候。
整個(gè)記憶體配置會(huì)像這樣
-XX:+DisableExplicitGC 加了這個(gè)參數(shù)會(huì)停止掉WLS或是程式內(nèi)直接呼叫GC,減少不必要的GC,將GC交由JVM去執(zhí)行。
Garbage Collection描述:
Garbage Collection分多種等級(jí),0級(jí)就是全部的垃圾回收(Full GC),會(huì)回收Old generation中的垃圾;1級(jí)或以上為部分垃圾回收,只會(huì)回收Young中的垃圾,會(huì)發(fā)生OutOfMemory通常是產(chǎn)生於Old generation或Perm段垃圾回收后,仍然沒(méi)有記憶體空間來(lái)存放新的Java 物件的情況。
當(dāng)一個(gè)URL被訪問(wèn)時(shí),記憶體的配置過(guò)程如下:
A. JVM會(huì)試圖為Java的相關(guān)對(duì)象在Eden中初始化一塊記憶體空間
B. 當(dāng)Eden空間足夠時(shí),記憶體配置結(jié)束。否則到下一步
C. JVM會(huì)試圖釋放在Eden中所有不活躍的對(duì)象(這是屬於1或更高級(jí)的垃圾回收);釋放後若Eden空間仍然不足以放入新對(duì)象,則會(huì)試圖將部分Eden中活躍的對(duì)象放入Survivor區(qū)/OLD區(qū)
D. Survivor區(qū)被用來(lái)作為Eden及OLD的中間交換區(qū)域,當(dāng)OLD區(qū)空間足夠,Survivor區(qū)的對(duì)象會(huì)被移到Old區(qū),否則被保留在Survivor區(qū)
E. 當(dāng)OLD區(qū)空間不足時(shí),JVM會(huì)在OLD區(qū)進(jìn)行完全的垃圾收集(0級(jí))
F. 完全垃圾收集后,若Survivor及OLD區(qū)仍然無(wú)法存放從Eden複製過(guò)來(lái)的部分對(duì)象,就會(huì)導(dǎo)致JVM無(wú)法在Eden區(qū)為新的對(duì)象配置出記憶體區(qū)塊,產(chǎn)生"out of memory的錯(cuò)誤"
以我的設(shè)定為例:
MEM_ARGS="-Xms768m -Xmx768m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=384m -XX:PermSize=384m -XX:SurvivorRatio=6 -XX:+DisableExplicitGC"
在上面的例子中:
YOUNG+OLD: 768M
YOUNG: 256M
Perm: 384M
Eden: YOUNG*6/(6+1+1)=192M
Survivor: YOUNG*1/(6+1+1)=32M
Heap Size: YOUNG+OLD+Perm=1024M
以上是WebLogic記憶體參數(shù)的一些基本的設(shè)定,太難的我也不會(huì),只是整理一些心得而己,提供做一下參考
堆( Heap)是 Java 程序的對(duì)象生活的地方,包含活的對(duì)象,死的對(duì)象以及剩余內(nèi)存 。
當(dāng)對(duì)象不能被運(yùn)行中的程序的指針?biāo)竭_(dá)時(shí),這些對(duì)象成為”垃圾“。
JVM 的堆大小決定了 VM 花費(fèi)在收集垃圾上的時(shí)間和頻度。
收集垃圾可以接受的速度與應(yīng)用有關(guān),應(yīng)該通過(guò)分析實(shí)際的垃圾收集的時(shí)間和頻率來(lái)調(diào)整。
如果堆的大小很大,那么完全垃圾收集就會(huì)很慢,但是頻度會(huì)降低。
如果你把堆的大小和內(nèi)存的需要一致,完全收集就很快,但是會(huì)更加頻繁。
調(diào)整堆大小的的目的是最小化垃圾收集的時(shí)間,以在特定的時(shí)間內(nèi)最大化處理客戶(hù)的請(qǐng)求。
在基準(zhǔn)測(cè)試的時(shí)候,為保證最好的性能,要把堆的大小設(shè)大,保證垃圾收集不在整個(gè)基準(zhǔn)測(cè)試的過(guò)程中出現(xiàn)。
堆劃分為兩個(gè)區(qū)域:新生代和舊生代。
新生代又分為:Eden 和兩片生存空間(survivor spaces)。其中保證有一片空間在任何時(shí)間是空的,當(dāng)垃圾收集發(fā)生時(shí), Eden 中的活的對(duì)象復(fù)制到下一片生存空間,對(duì)象就在生存空間之間復(fù)制,直到到達(dá)最大門(mén)限值(老化),然后復(fù)制到舊生代。
Eden 是新的對(duì)象分配的地方。
很多對(duì)象分配以后很快成為垃圾,這些對(duì)象稱(chēng)為具有 "infant mortality."
對(duì)象生存的時(shí)間越長(zhǎng),需要的收集時(shí)間也越長(zhǎng),因此,收集變慢。
你的應(yīng)用建立和釋放對(duì)象的速度決定了垃圾收集的頻度。因此,在編程時(shí),應(yīng)注意使用對(duì)象的緩沖,而不是新建立對(duì)象。
大多數(shù)對(duì)象在新生代就已經(jīng)死去,因此你能有效的調(diào)整垃圾收集。如果你能安排大多數(shù)對(duì)象的生存期小于一個(gè)收集時(shí)間,那么,垃圾收集是十分高效的。
錯(cuò)誤的”代“配置會(huì)導(dǎo)致頻繁的垃圾收集,影響系統(tǒng)性能。
如果系統(tǒng)花費(fèi)很多的時(shí)間收集垃圾,請(qǐng)減小堆大小。
一次完全的垃圾收集應(yīng)該不超過(guò) 3-5 秒。
一般說(shuō)來(lái),你應(yīng)該使用物理內(nèi)存的 80% 作為堆大小。
在最大工作負(fù)荷的時(shí)候,監(jiān)視 WebLogic 的性能。
使用 -verbosegc 選項(xiàng)測(cè)量有多少時(shí)間和資源用于垃圾收集。
打開(kāi)垃圾收集的詳細(xì)信息輸出以及重定向:
% java -ms64m -mx64m -verbosegc -classpath $CLASSPATH
-Dweblogic.domain=mydomain -Dweblogic.Name=clusterServer1
-Djava.security.policy==/bea/weblogic6x/lib/weblogic.policy
-Dweblogic.management.server=192.168.0.101:7001 -Dweblogic.management.username=system
-Dweblogic.management.password=systemPassword weblogic.Server >> logfile.txt
在 Solaris 系統(tǒng)上,采用下面的命令:
weblogic.Server > server.out 2>&1
Java HotSpot VM 選項(xiàng)
標(biāo)準(zhǔn)的選項(xiàng)在各種平臺(tái)都已經(jīng)有介紹:
由于 -XX 選項(xiàng)需要特別的系統(tǒng)權(quán)限,因此不建議隨便使用。
在 1.3.0 之前的版本, J2SDK 的 Solaris 版本帶有一個(gè)虛擬機(jī)的實(shí)現(xiàn)叫做 Exact VM(EVM),從 1.3.0 開(kāi)始這個(gè)虛擬機(jī)被 Java HotSpot VM 所取代。
Java HotSpot VM 目前認(rèn)識(shí)下面的 -X 選項(xiàng):
-Xincgc 使用訓(xùn)練 GC
-Xnoincgc 不是用訓(xùn)練 GC(缺省)
-XX:MaxHeapFreeRatio=<Maximum> 最大堆剩余百分比(缺省 70)
-X:MinHeapFreeRation=<Minimum> 堆最小剩余百分比(缺省 40)
-Xint 只作解析 (不作 JIT 編譯)
-XX:+UseBoundThreads 綁定用戶(hù)級(jí)別的線程 (只針對(duì) Solaris)
-Xmn<Size> 設(shè)置年輕一代的大?。?young generation )(只對(duì) 1.4)
對(duì)象分配在 Eden,并且在這里死亡,當(dāng) Eden 滿時(shí),引起一個(gè)小的收集(minor collection),一些生存的對(duì)象被移動(dòng)到舊生代,如果舊生代需要收集,則引起大收集(major collection ),這會(huì)比較緩慢。
如果 GC 成為瓶頸,那么需要指定代的大小,檢查 GC 的詳細(xì)輸出,研究 GC 參數(shù)對(duì)性能的影響。
舊生代的收集采用 mark-compact 的方式,其中的一部分叫做”永久代“(permanent generation)很特別,他包括了 JVM 自身的所有反映數(shù)據(jù)(reflective data),例如類(lèi)以及方法。
暫停時(shí)間的含義是應(yīng)用因?yàn)槔占@示出來(lái)的短暫停頓。
吞吐量的含義是在一段比較長(zhǎng)的時(shí)間內(nèi),沒(méi)有用在垃圾收集的時(shí)間和總時(shí)間的百分比。
減少暫停時(shí)間的辦法可以采用小的年輕代和增量收集,但是這以犧牲吞吐率為代價(jià)。
Footprint 是一批工作進(jìn)程的集合,以頁(yè)和緩沖行數(shù)計(jì)量,在物理內(nèi)存有限或者有很多處理器的系統(tǒng)里,footprint 可代表伸縮性。
Promptness 是對(duì)象死去的時(shí)間和內(nèi)存變?yōu)榭捎脮r(shí)的時(shí)間差,在分布系統(tǒng)中(包括 RMI)需要考慮。
很大的新生代能提高吞吐率,但是犧牲了 footprint 和 promptness。
Solaris 的 footprint 可以采用 pmap 命令來(lái)查看。
[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]
上面的三行是 GC 的詳細(xì)輸出,我們可以看到兩次小收集和一次大收集。箭頭前后的兩個(gè)數(shù)字代表 GC 后活的對(duì)象的組合長(zhǎng)度。括號(hào)內(nèi)的數(shù)字代表合計(jì)的空間,等于堆大小減去一片生存空間。
除非你遇到暫停的問(wèn)題,否則,可以分配足夠的內(nèi)存給 JVM,缺省的 64MB 總是太小。
設(shè)置 -Xms 和 -Xmx 為同樣的值能提高 JVM 的預(yù)測(cè),但是如果你的選擇不對(duì)的話, JVM 不會(huì)補(bǔ)償。
當(dāng)增加處理器時(shí),記得增加內(nèi)存,因?yàn)榉峙淇梢圆⑿羞M(jìn)行,而 GC 不是并行的。
NewSize 和 MaxNewSize 綁定新生代的長(zhǎng)度的低端和高端,設(shè)置為一樣大小時(shí)和 -Xms 和 -Xmx 一樣解決新生代的預(yù)測(cè)時(shí)間。
如果生存空間太小,拷貝直接進(jìn)入舊生代,如果太大的話,會(huì)空閑在那里。
除非你碰到過(guò)渡的大收集或者暫停時(shí)間,否則分配足夠的內(nèi)存給新生代,缺省的 MaxNewSize (32MB) 往往太小。
如果需要的話,最大的永久代大小可以使用 MaxPermSize 增加。
直接的 GC 調(diào)用可以采用 -XX:+DisableExplicitGC 來(lái)關(guān)閉。
對(duì)于大服務(wù)器 而言,1.4 的 JVM 能提供 64 bit 尋址能力,提供更大的新生代大小,并發(fā)收集來(lái)減少大收集引起的暫停的影響。
Java HotSpot Client VM 主要用于減少應(yīng)用啟動(dòng)時(shí)間以及內(nèi)存的 footprint 。
Java HotSpot Server VM 和 Java HotSpot Client VM 類(lèi)似,但是在最大性能上作了調(diào)整。用于長(zhǎng)期運(yùn)行的服務(wù)應(yīng)用。
Solaris 和 Linux 的 J2SE 1.3 隨帶 Java HotSpot Server VM 預(yù)安裝。