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