1. 程式人生 > >JVM虛擬機選項:Xms Xmx PermSize MaxPermSize區別(轉)

JVM虛擬機選項:Xms Xmx PermSize MaxPermSize區別(轉)

生產 申請 java ane 獨立 use 我們 也會 交換

java雖然是自動回收內存,但是應用程序,尤其服務器程序最好根據業務情況指明內存分配限制。
否則可能導致應用程序宕掉。

舉例說明含義:
-Xms128m
表示JVM Heap(堆內存)最小尺寸128MB,初始分配
-Xmx512m
表示JVM Heap(堆內存)最大允許的尺寸256MB,按需分配。

說明:如果-Xmx不指定或者指定偏小,應用可能會導致java.lang.OutOfMemory錯誤,此錯誤來自JVM不是Throwable的,無法用try...catch捕捉。

PermSize和MaxPermSize指明虛擬機為java永久生成對象(Permanate generation)
如,class對象、方法對象這些可反射(reflective)對象分配內存限制,這些內存不包括在Heap(堆內存)區之中。



-XX:PermSize=64MB 最小尺寸,初始分配
-XX:MaxPermSize=256MB 最大允許分配尺寸,按需分配
過小會導致:java.lang.OutOfMemoryError: PermGen space

MaxPermSize缺省值和-server -client選項相關。
-server選項下默認MaxPermSize為64m
-client選項下默認MaxPermSize為32m

經驗:
1、慎用最小限制選項Xms,PermSize已節約系統資源。

=========================================================

近期研究對jvm的內存使用情況進行監控,因此對觀察虛擬機的內存使用方法做了一些收集,對jvm的參數設置了解了一下:

幾個基本概念:

PermGen space:全稱是Permanent Generation space,即永久代。就是說是永久保存的區域,用於存放Class和Meta信息,Class在被Load的時候被放入該區域,GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。
Heap space:存放Instance。Java Heap分為3個區,Young即新生代,Old即老生代和Permanent。Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象。

幾個參數設置的意義:

xms/xmx:定義YOUNG+OLD段的總尺寸
ms為JVM啟動時YOUNG+OLD的內存大小
mx為最大可占用的YOUNG+OLD內存大小。
在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷


NewSize/MaxNewSize:定義YOUNG段的尺寸,
NewSize為JVM啟動時YOUNG的內存大小;
MaxNewSize為最大可占用的YOUNG內存大小。

在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。
PermSize/MaxPermSize:定義Perm段的尺寸,PermSize為JVM啟動時Perm的內存大小;MaxPermSize為最大可占用的Perm內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。
SurvivorRatio:設置YOUNG代中Survivor空間和Eden空間的比例

申請一塊內存的過程:

A. JVM會試圖為相關Java對象在Eden中初始化一塊內存區域
B. 當Eden空間足夠時,內存申請結束。否則到下一步
C. JVM試圖釋放在Eden中所有不活躍的對象(這屬於1或更高級的垃圾回收);釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區/OLD區
D. Survivor區被用來作為Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,否則會被保留在Survivor區
E. 當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)
F. 完全垃圾收集後,若Survivor及OLD區仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區為新對象創建內存區域,則出現”out of memory錯誤”

我們的一種resin服務器的jvm參數設置:

“-Xmx2000M -Xms2000M -Xmn500M -XX:PermSize=250M -XX:MaxPermSize=250M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled
-XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60
-XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log”

是一種典型的響應時間優先型的配置。

Java中有四種不同的回收算法,對應的啟動參數為

–XX:+UseSerialGC
–XX:+UseParallelGC
–XX:+UseParallelOldGC
–XX:+UseConcMarkSweepGC

1. Serial Collector
大部分平臺或者強制 java -client 默認會使用這種。
young generation算法 = serial
old generation算法 = serial (mark-sweep-compact)
這種方法的缺點很明顯,stop-the-world, 速度慢。服務器應用不推薦使用。

2. Parallel Collector
在linux x64上默認是這種,其他平臺要加 java -server 參數才會默認選用這種。
young = parallel,多個thread同時copy
old = mark-sweep-compact = 1
優點:新生代回收更快。因為系統大部分時間做的gc都是新生代的,這樣提高了throughput(cpu用於非gc時間)
缺點:當運行在8G/16G server上old generation live object太多時候pause time過長

3. Parallel Compact Collector (ParallelOld)
young = parallel = 2
old = parallel,分成多個獨立的單元,如果單元中live object少則回收,多則跳過
優點:old old generation上性能較 parallel 方式有提高
缺點:大部分server系統old generation內存占用會達到60%-80%, 沒有那麽多理想的單元live object很少方便迅速回收,同時compact方面開銷比起parallel並沒明顯減少。

4. Concurent Mark-Sweep(CMS) Collector
young generation = parallel collector = 2
old = cms
同時不做 compact 操作。
優點:pause time會降低, pause敏感但CPU有空閑的場景需要建議使用策略4.
缺點:cpu占用過多,cpu密集型服務器不適合。另外碎片太多,每個object的存儲都要通過鏈表連續跳n個地方,空間浪費問題也會增大。

內存監控的方法:

1. jmap -heap pid
查看java 堆(heap)使用情況

   using thread-local object allocation.
        Parallel GC with 4 thread(s)          //GC 方式
         Heap Configuration:       //堆內存初始化配置
         MinHeapFreeRatio=40     //對應jvm啟動參數-XX:MinHeapFreeRatio設置JVM堆最小空閑比率(default 40)
         MaxHeapFreeRatio=70  //對應jvm啟動參數 -XX:MaxHeapFreeRatio設置JVM堆最大空閑比率(default 70)
         MaxHeapSize=512.0MB  //對應jvm啟動參數-XX:MaxHeapSize=設置JVM堆的最大大小
         NewSize  = 1.0MB          //對應jvm啟動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小
         MaxNewSize =4095MB   //對應jvm啟動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小
         OldSize  = 4.0MB            //對應jvm啟動參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小
         NewRatio  = 8         //對應jvm啟動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
         SurvivorRatio = 8    //對應jvm啟動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值
          PermSize= 16.0MB       //對應jvm啟動參數-XX:PermSize=<value>:設置JVM堆的‘永生代’的初始大小
          MaxPermSize=64.0MB  //對應jvm啟動參數-XX:MaxPermSize=<value>:設置JVM堆的‘永生代’的最大大小
 
 
          Heap Usage:               //堆內存分步
          PS Young Generation
          Eden Space:          //Eden區內存分布
            capacity = 20381696 (19.4375MB)  //Eden區總容量
            used     = 20370032 (19.426376342773438MB)  //Eden區已使用
            free     = 11664 (0.0111236572265625MB)  //Eden區剩余容量
            99.94277218147106% used  //Eden區使用比率
         From Space:        //其中一個Survivor區的內存分布
             capacity = 8519680 (8.125MB)
             used     = 32768 (0.03125MB)
             free     = 8486912 (8.09375MB)
             0.38461538461538464% used
        To Space:            //另一個Survivor區的內存分布
            capacity = 9306112 (8.875MB)
            used     = 0 (0.0MB)
            free     = 9306112 (8.875MB)
            0.0% used
        PS Old Generation  //當前的Old區內存分布
            capacity = 366280704 (349.3125MB)
            used     = 322179848 (307.25464630126953MB)
            free     = 44100856 (42.05785369873047MB)
            87.95982001825573% used
        PS Perm Generation  //當前的 “永生代” 內存分布

JVM虛擬機選項:Xms Xmx PermSize MaxPermSize區別(轉)