先來看下一X寶經(jīng)典配置:
/opt/taobao/java/bin/java -Dprogram.name=run.sh –server
-Xms4g //指定 jvm 的最小 heap 大小 (-Xms默認(rèn)是物理內(nèi)存的1/4)
-Xmx4g //指定 jvm 的最大 heap 大小
-Xmn2g
-Xss1m
-XX:PermSize=96m
-XX:MaxPermSize=256m
-XX:SurvivorRatio=10
-XX:+HeapDumpOnOutOfMemoryError //
-XX:HeapDumpPath=/home/admin/logs/java.hprof -verbose:gc -Xloggc:/home/admin/logs/gc.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSInitiatingOccupancyFraction=80
-XX:+UseCompressedOops
-XX:+DisableExplicitGC
-Djava.awt.headless=true
-Dsun.net.client.defaultConnectTimeout=10000
-Dsun.net.client.defaultReadTimeout=30000
-Djava.net.preferIPv4Stack=true
-Djava.endorsed.dirs=/opt/taobao/jboss/lib/endorsed
-classpath /opt/taobao/jboss/bin/run.jar:/opt/taobao/java/lib/tools.jar org.jboss.Main -b 0.0.0.0 -Djboss.server.home.dir=/home/admin/purdecision/.default -Djboss.server.home.url=file:/home/admin/purdecision/.default
這二年來這一堆東西我從來沒有懷疑過,“絕對(duì)正確完美”,據(jù)說是X寶的標(biāo)配。以至于從來沒有去分析了解過(一知半解),可能真的是惰性使然,也可能“忙”吧。無意中看到有人在博客里寫到 “溫故知新”,就像有人說讀think in java一樣每一回都有新的發(fā)現(xiàn)。下面就分析一下為什么要設(shè)置這些參數(shù),有何意義。
上面參數(shù)說明:
-Xmx4g :
指定 jvm 的最大 heap 大小,默認(rèn)值為物理內(nèi)存的1/4,最佳設(shè)值應(yīng)該視物理內(nèi)存大小及計(jì)算機(jī)內(nèi)其他內(nèi)存開銷而定
-Xms4g :
指定 jvm 的最小 heap 大小。些值設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存
-Xmn2g :
設(shè)置年輕代大小為2G。整個(gè)堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般
固定大小為64m,所以增大年輕代后,將會(huì)減小年老代大小。此值對(duì)系統(tǒng)性能影響較大,Sun官方推
薦配置為整個(gè)堆的3/8。(按此說應(yīng)設(shè)置為1.5G)
-Xss1m
每個(gè)線程堆棧大小為1M. 根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。在相同物理內(nèi)存下,減小這個(gè)值能生成更多的線程。(本機(jī)由于forest的原因-Xss2m,原因1:物理內(nèi)存過小 2:window線程不能太多 猜的)
-XX:PermSize=96m
用于存放靜態(tài)文件,如今Java類、方法等。持久代對(duì)垃圾回收沒有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或
者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新
增的類。持久代大小通過-XX:MaxPermSize=<N>進(jìn)行設(shè)置
-XX:PermSize=64MB 最小尺寸,初始分配
-XX:MaxPermSize=256MB 最大允許分配尺寸,按需分配
過小會(huì)導(dǎo)致:java.lang.OutOfMemoryError: PermGen space
MaxPermSize缺省值和-server -client選項(xiàng)相關(guān)。
-server選項(xiàng)下默認(rèn)MaxPermSize為64m
-client選項(xiàng)下默認(rèn)MaxPermSize為32m
(為什么不是64M 可能是webx設(shè)置的持久代空間比較多)
-XX:SurvivorRatio=10
(SurvivorRatio=4設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個(gè)Survivor
區(qū)與一個(gè)Eden區(qū)的比值為2:4,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/6)
這里設(shè)置為10也就是說一個(gè)Survivor區(qū)占整個(gè)年輕代的1/12,這個(gè)參數(shù)是否能小一點(diǎn),畢竟我們的應(yīng)用中沒有創(chuàng)建很大的對(duì)像。
這個(gè)值設(shè)了有什么用?
上面配置中-Xmn2g 年輕代大小,SurvivorRatio為10時(shí) :Eden超過1.66G時(shí)觸發(fā)minor gc(young generation)
我的應(yīng)用gc 日志一直在young gc 就是如此,看來我的應(yīng)用 eden區(qū)還是設(shè)的很大的。
-XX:+HeapDumpOnOutOfMemoryError
參數(shù)表示當(dāng)JVM發(fā)生OOM時(shí),自動(dòng)生成DUMP文件。
-XX:HeapDumpPath=${目錄}參數(shù)表示生成DUMP文件的路徑,也可以指定文件名稱,例如:-XX:HeapDumpPath=${目錄}/java_heapdump.hprof。如果不指定文件名,默認(rèn)為:java_<pid>_<date>_<time>_heapDump.hprof。
-XX:+PrintGCDetails:
輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured:
112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可與上面兩個(gè)混合使用
輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
-XX:+UseConcMarkSweepGC
設(shè)置并發(fā)收集器
可以保證大部分工作都并發(fā)進(jìn)行(應(yīng)用不停止),垃圾回收只暫停很少的時(shí)間,此收集器適合對(duì)響應(yīng)時(shí)間要求
比較高的中、大規(guī)模應(yīng)用。使用-XX:+UseConcMarkSweepGC打開。
并發(fā)收集器主要減少年老代的暫停時(shí)間,他在應(yīng)用不停止的情況下使用獨(dú)立的垃圾回收線程,跟蹤可達(dá)對(duì)
象。在每個(gè)年老代垃圾回收周期中,在收集初期并發(fā)收集器 會(huì)對(duì)整個(gè)應(yīng)用進(jìn)行簡短的暫停,在收集中還會(huì)再暫
停一次。第二次暫停會(huì)比第一次稍長,在此過程中多個(gè)線程同時(shí)進(jìn)行垃圾回收工作。
CMS采用的基礎(chǔ)算法是:標(biāo)記—清除 所有CMS不會(huì)整理、壓縮堆空間。這樣就會(huì)有一個(gè)問題:經(jīng)過CMS收集的堆會(huì)產(chǎn)生空間碎片
-XX:CMSInitiatingOccupancyFraction=80
啟動(dòng)并發(fā)收集器:因?yàn)椴l(fā)收集在應(yīng)用運(yùn)行時(shí)進(jìn)行收集,所以必須保證收集完成之前有足夠的內(nèi)存空間供程
序使用,否則會(huì)出現(xiàn)“Concurrent Mode Failure”。通過設(shè)置-XX:CMSInitiatingOccupancyFraction=<N>
指定還有多少剩余堆時(shí)開始執(zhí)行并發(fā)收集
-XX:+UseCMSCompactAtFullCollection:
打開對(duì)年老代的壓縮。可能會(huì)影響性能,但是可以消除碎片
XX:+UseCompressedOops
通常64位JVM消耗的內(nèi)存會(huì)比32位的大1.5倍,這是因?yàn)閷?duì)象指針在64位架構(gòu)下,長度會(huì)翻倍(更寬的尋址)。
對(duì)于那些將要從32位平臺(tái)移植到64位的應(yīng)用來說,平白無辜多了1/2的內(nèi)存占用,這是開發(fā)者不愿意看到的。
幸運(yùn)的是,從JDK 1.6 update14開始,64 bit JVM正式支持了 -XX:+UseCompressedOops 這個(gè)可以壓縮指針,起到節(jié)約內(nèi)存占用的新參數(shù)
-XX:-DisableExplicitGC
將會(huì)忽略手動(dòng)調(diào)用GC的代碼,如:System.gc(),將-DisableExplicitGC, 改成+DisableExplicitGC即為啟用,默認(rèn)為啟用,什么也不寫,默認(rèn)是加號(hào),但是系統(tǒng)內(nèi)部默認(rèn)的并不是什么都啟用
至此為什么Xmx與xms 一樣,為什么用CMS(并發(fā)收集器),為什么用了cms 要使用-XX:+UseCMSCompactAtFullCollection,為什么用XX:+UseCompressedOops等等,相信大家和我一樣有所了解。不過對(duì)于有些還是不清楚理解有誤,可能還要來來回回?fù)v騰,不足之處請(qǐng)大家補(bǔ)充。