Java堆內存設置


轉自:https://blog.csdn.net/Qiuzhongweiwei/article/details/81023645

堆內存設置

原理

JVM堆內存分為2塊:永久空間和堆空間。
  • 永久即持久代(Permanent Generation),主要存放的是Java類定義信息,與垃圾收集器要收集的Java對象關系不大。
  • Heap = {Old + NEW = {Eden,from,to}},Old即年老代(Old Generation),New即年輕代(Young Generation)。年老代和年輕代的划分對垃圾收集影響比較大。

年輕代

所有新生成的對象首先都是放在年輕代。年輕代的目標就是盡可能快速的收集掉那些生命周期短的對象。年輕代一般分3個區,1個伊甸區,2個幸存者區(從到)。

大部分對象在伊甸區中生成。當伊甸區滿時,還存活的對象將被復制到幸存者區(兩個中的一個),當一個幸存者區滿時,此區的存活對象將被復制到另外一個幸存者區,當另一個幸存者區也滿了的時候,從前一個幸存者區復制過來的並且此時還存活的對象,將可能被復制到年老代。

2個幸存者區是對稱的,沒有先后關系,所以同一個幸存者區中可能同時存在從伊甸區復制過來對象,和從另一個幸存者區復制過來的對象;而復制到年老區的只有另一個從幸存者區過來的對象。而且,因為需要交換的原因,幸存者區至少有一個是空的。特殊的情況下,根據程序需要,幸存者區是可以配置為多個的(多於2個),這樣可以增加對象在年輕代中的存在時間,減少被放到年老代的可能。

針對年輕代的垃圾回收即Young GC。

年老代

在年輕代中經歷了Ñ次(可配置)垃圾回收后仍然存活的對象,就會被復制到年老代中。因此,可以認為年老代中存放的都是一些生命周期較長的對象。

針對年老代的垃圾回收即Full GC。

持久代

用於存放靜態類型數據,如Java的的的類,方法等。持久代對垃圾回收沒有顯着影響。但是有些應用可能動態生成或調用一些類,例如休眠CGLIB等,在這種時候往往需要設置一個比較大的持久代空間來存放這些運行過程中動態增加的類型。

 

所以,當一組對象生成時,內存申請過程如下:

  1. JVM會試圖為相關的Java的的的對象在年輕代的伊甸園區中初始化一塊內存區域。
  2. 當伊甸區空間足夠時,內存申請結束。否則執行下一步。
  3. JVM試圖釋放在伊甸園區中所有不活躍的對象(年輕的GC)。釋放后若伊甸園空間仍然不足以放入新對象,JVM則試圖將部分伊甸園區中活躍對象放入幸存者區。
  4. 幸存者區被用來作為伊甸園區及年老代的中間交換區域。當年老代空間足夠時,幸存者區中存活了一定次數的對象會被移到年老代。
  5. 當年老代空間不夠時,JVM會在年老代進行完全的垃圾回收(Full GC)。
  6. 完全GC后,若幸存者區及年老代仍然無法存放從伊甸區復制過來的對象,則會導致JVM無法在伊甸園區為新生成的對象申請內存,即出現“內存不足”。

OOM(“Out of Memory”)異常一般主要有如下2種原因:

1.年老代溢出,表現為:java.lang.OutOfMemoryError:Javaheapspace
這是最常見的情況,產生的原因可能是:設置的內存參數XMX過小或程序的內存泄露及使用不當問題。
例如循環上萬次的字符串處理,創建上千萬個對象,在一段代碼內申請上百中號甚至上ģ的內存。還有的時候雖然不會報內存溢出,卻會使系統不間斷的垃圾回收,也無法處理其它請求。這種情況下除了檢查程序,打印堆內存等方法排查,還可以借助一些內存分析工具,比如MAT就很不錯。

2.持久代溢出,表現為:java.lang.OutOfMemoryError:PermGenspace
通常由於持久代設置過小,動態加載了大量的Java類而導致溢出,解決辦法唯有將參數-XX:MaxPermSize參數參數參數調大(一般256米能滿足絕大多數應用程序需求)將部分的Java的的類放到容器共享區(例如Tomcat share lib)去加載的辦法也是一個思路,但前提是容器里部署了多個應用,而這些應用有大量的共享類庫。

參數說明

  • -Xmx3550m:設置JVM 最大堆內存為3550M。
  • -Xms3550m:設置JVM 初始堆內存為3550M此值可以設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。
  • -Xss128k:。設置每個線程的棧大小.JDK5.0以后每個線程棧大小為1M,之前每個線程棧大小為256K應當根據應用的線程所需內存大小進行調整在相同物理內存下,。減小這個值能生成更多的線程但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右需要注意的是:當這個值被設置的較大(例如> 2MB)時將會在很大程度上降低系統的性能。
  • -Xmn2g:設置年輕代。大小為2G在整個堆內存大小確定的情況下,增大年輕代將會減小年老代,反之亦然此值關系到JVM垃圾回收,對系統性能影響較大,官方推薦配置為整個堆大小的3/8。
  • -XX:新尺寸= 1024米:設置年輕代初始值為1024M。
  • -XX:MaxNewSize = 1024米:設置年輕代最大值為1024M。
  • -XX:PermSize = 256米:設置持久代初始值為256M。
  • -XX:MaxPermSize參數參數= 256米:設置持久代最大值為256M。
  • -XX:NewRatio = 4:設置年輕代(包括1個伊甸和2個幸存者區)與年老代的比值表示年輕代比年老代為1:4。
  • -XX:SurvivorRatio = 4:設置年輕代中伊甸區與幸存者區的比值。表示2個幸存者區(JVM堆內存年輕代中默認有2個大小相等的幸存者區)與1個伊甸區的比值為2:4,即1個幸存者區占整個年輕代大小的1/6。
  • -XX:MaxTenuringThreshold = 7:表示一個對象如果在幸存者區(救助空間)移動了7次還沒有被垃圾回收就進入年老代如果設置為0的話,則年輕代對象不經過幸存者區,直接進入年老代,對於需要大量常駐內存的應用,這樣做可以提高效率。如果將此值設置為一個較大值,則年輕代對象會在幸存者區進行多次復制,這樣可以增加對象在年輕代存活時間,增加對象在年輕代被垃圾回收的概率,減少Full GC的頻率,這樣做可以在某種程度上提高服務穩定性。

疑問解答

-Xmn,-XX:NewSize / -XX:MaxNewSize,-XX:NewRatio 3組參數都可以影響年輕代的大小,混合使用的情況下,優先級是什么?
如下:
  1. 高優先級:-XX:新尺寸/ -XX:MaxNewSize 
  2. 中優先級:-Xmn(默認等效-Xmn = -XX:NewSize = -XX:MaxNewSize =?) 
  3. 低優先級:-XX:NewRatio 
推薦使用-Xmn參數,原因是這個參數簡潔,相當於一次設定NewSize / MaxNewSIze,而且兩者相等,適用於生產環境。-Xmn配合-Xms / -Xmx,即可將堆內存布局完成。
-Xmn參數是在JDK 1.4開始支持。
 

垃圾回收器選擇

JVM給出了3種選擇:串行收集器,並行收集器,並發收集器串行收集器只適用於小數據量的情況,所以生產環境的選擇主要是並行收集器和並發收集器。

默認情況下JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在啟動時加入相應參數.JDK5.0以后,JVM會根據當前系統配置進行智能判斷。

串行收集器

  • -XX:+ UseSerialGC:設置串行收集器。

並行收集器(吞吐量優先)

  • -XX:+ UseParallelGC:。設置為並行收集器此配置僅對年輕代有效即年輕代使用並行收集,而年老代仍使用串行收集。
  • -XX:ParallelGCThreads = 20:配置並行收集器的線程數,即:同時有多少個線程一起進行垃圾回收此值建議配置與CPU數目相等。
  • -XX:+ UseParallelOldGC:配置年老代垃圾收集方式為並行收集.JDK6.0開始支持對年老代並行收集。
  • -XX:MaxGCPauseMillis = 100:設置每次年輕代代垃圾回收的最長時間(單位毫秒)如果無法滿足此時間,JVM會自動調整年輕代大小,以滿足此時間。
  • -XX:+ UseAdaptiveSizePolicy:設置此選項后,並行收集器會自動調整年輕代伊甸區大小和幸存者區大小的比例,以達成目標系統規定的最低響應時間或者收集頻率等指標此參數建議在使用並行收集器時,一直打開。

並發收集器(響應時間優先)

  • -XX:+ UseConcMarkSweepGC:即CMS收集,設置年老代為並發收集的.cms收集是JDK1.4后期版本開始引入的新GC算法它的主要適合場景是對響應時間的重要性需求大於對吞吐量的需求,能夠承受垃圾回收線程和應用線程共享CPU資源,並且應用中存在比較多的長生命周期對象的的的.cms收集的目標是盡量減少應用的暫停時間,減少全GC發生的幾率,利用和應用程序線程並發的垃圾回收線程來標記清除年老代內存。
  • -XX:+ UseParNewGC:設置年輕代為並發收集可與CMS收集同時使用.JDK5.0以上,JVM會根據系統配置自行設置,所以無需再設置此參數。
  • -XX:CMSFullGCsBeforeCompaction = 0:由於並發收集器不對內存空間進行壓縮和整理,所以運行一段時間並行收集以后會產生內存碎片,內存使用效率降低。此參數設置運行0次Full GC后對內存空間進行壓縮和整理,即每次Full GC后立刻開始壓縮和整理內存。
  • -XX:+ UseCMSCompactAtFullCollection:打開內存空間的壓縮和整理,在Full GC后執行。可能會影響性能,但可以消除內存碎片。
  • -XX:+ CMSIncrementalMode:設置為增量收集模式一般適用於單CPU情況。
  • -XX:CMSInitiatingOccupancyFraction = 70:表示年老代內存空間使用到70%時就開始執行CMS收集,以確保年老代有足夠的空間接納來自年代代的對象,避免Full GC的發生。

其它垃圾回收參數

  • -XX:+ ScavengeBeforeFullGC:年輕代GC優於全GC執行。
  • -XX:-DisableExplicitGC:不響應System.gc()的的的代碼。
  • -XX:+ UseThreadPriorities:啟用本地線程優先級API即使生效,不啟用  java.lang.Thread.setPriority() 則無效。
  • -XX:SoftRefLRUPolicyMSPerMB = 0:軟引用對象在最后一次被訪問后能存活0毫秒(JVM默認為1000毫秒)。
  • -XX:TargetSurvivorRatio = 90:允許90%的幸存者區被占用(JVM默認為50%)提高對於幸存者區的使用率。

輔助信息參數設置

  • -XX:-CITime:打印消耗在JIT編譯的時間。
  • -XX:錯誤文件= / hs_err_pid.log:保存錯誤日志或數據到指定文件中。
  • -XX:HeapDumpPath = / java_pid.hprof:指定轉儲堆內存時的路徑。
  • -XX:-HeapDumpOnOutOfMemoryError:當首次遭遇內存溢出時卸出此時的堆內存。
  • -XX:的OnError =“;”:出現致命錯誤后運行自定義命令。
  • -XX:OnOutOfMemoryError =“;”:當首次遭遇內存溢出時執行自定義命令。
  • -XX:-PrintClassHistogram:按下Ctrl + Break后打印堆內存中類實例的柱狀信息,同JDK的jmap -histo命令。
  • -XX:-PrintConcurrentLocks:按下Ctrl + Break后打印線程棧中並發鎖的相關信息,同JDK的jstack -l命令。
  • -XX:-PrintCompilation:當一個方法被編譯時打印相關信息。
  • -XX:-PrintGC:每次GC時打印相關信息。
  • -XX:-PrintGCDetails:每次GC時打印詳細信息。
  • -XX:-PrintGCTimeStamps:打印每次GC的時間戳。
  • -XX:-TraceClassLoading:跟蹤類的加載信息。
  • -XX:-TraceClassLoadingPreorder:跟蹤被引用到的所有類的加載信息。
  • -XX:-TraceClassResolution:跟蹤常量池。
  • -XX:-TraceClassUnloading:跟蹤類的卸載信息。

關於參數名稱等

  • 標准參數( - ),所有JVM都必須支持這些參數的功能,而且向后兼容;例如:
    • -client - 設置JVM使用客戶端模式,特點是啟動速度比較快,但運行時性能和內存管理效率不高,通常用於客戶端應用程序或開發調試;在32位環境下直接運行Java程序默認啟用該模式。
    • -server - 設置JVM使服務器模式,特點是啟動速度比較慢,但運行時性能和內存管理效率很高,適用於生產環境。在具有64位能力的JDK環境下默認啟用該模式。
  • 非標准參數(-X),默認JVM實現這些參數的功能,但是並不保證所有JVM實現都滿足,且不保證向后兼容;
  • 非穩定參數(-XX),此類參數各個JVM實現會有所不同,將來可能會不被支持,需要慎重使用;
 

JVM服務參數調優實戰

大型網站服務器案例

承受海量訪問的動態的網絡應用

服務器配置:8 CPU,8G MEM,JDK 1.6.X

參數方案:

-server -Xmx3550m -Xms3550m -Xmn1256m -Xss128k -XX:SurvivorRatio = 6 -XX:MaxPermSize = 256m -XX:ParallelGCThreads = 8 -XX:MaxTenuringThreshold = 0 -XX:+ UseConcMarkSweepGC

調優說明:

  • -Xmx與-Xms相同以避免JVM反復重新申請內存。-XMX的大小約等於系統內存大小的一半,即充分利用系統資源,又給予系統安全運行的空間。
  • -Xmn1256m設置年輕代大小為1256MB。此值對系統性能影響較大,太陽官方推薦配置年輕代大小為整個堆的3/8。
  • -Xss128k設置較小的線程棧以支持創建更多的線程,支持海量訪問,並提升系統性能。
  • -XX:SurvivorRatio = 6設置年輕代中Eden區與Survivor區的比值。系統默認是8,根據經驗設置為6,則2個幸存者區與1個Eden區的比值為2:6,一個幸存者區占整個年輕代的1/8。
  • -XX:ParallelGCThreads = 8配置並行收集器的線程數,即同時8個線程一起進行垃圾回收。此值一般配置為與CPU數目相等。
  • -XX:MaxTenuringThreshold = 0設置垃圾最大年齡(在年輕代的存活次數)。如果設置為0的話,則年輕代對象不經過Survivor區直接進入年老代。對於年老代比較多的應用,可以提高效率;如果將此值設置為一個較大值,則年輕代對象會在幸存者區進行多次復制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概率根據被海量訪問的動態網絡應用之特點,其內存要么被緩存起來以減少直接訪問數據庫,要么被快速回收以支持高並發海量請求,因此其內存對象在年輕代存活多次意義不大,可以直接進入年老代,根據實際應用效果,在這里設置此值為0。
  • -XX:+ UseConcMarkSweepGC設置年老代為並發收集.CMS(ConcMarkSweepGC)收集的目標是盡量減少應用的暫停時間,減少完全GC發生的幾率,利用和應用程序線程並發的垃圾回收線程來標記清除年老代內存,適用於應用中存在比較多的長生命周期對象的情況。

內部集成構建服務器案例

高性能數據處理的工具應用

服務器配置:1個CPU,4G MEM,JDK 1.6.X

參數方案:

-server -XX:PermSize = 196m -XX:MaxPermSize = 196m -Xmn320m -Xms768m -Xmx1024m

調優說明:

  • -XX:PermSize = 196m -XX:MaxPermSize = 196m根據集成構建的特點,大規模的系統編譯可能需要加載大量的Java類到內存中,所以預先分配好大量的持久代內存是高效和必要的。
  • -Xmn320m遵循年輕代大小為整個堆的3/8原則。
  • -Xms768m -Xmx1024m根據系統大致能夠承受的堆內存大小設置即可。
在64位服務器上運行應用程序,構建執行時,用jmap -heap 11540命令觀察JVM堆內存狀況如下:
 

附加到進程ID 11540,請稍候... 
調試程序已成功附加。
服務器編譯檢測到使用線程局部對象分配的
JVM版本是20.12-b01 



具有4個線程的並行GC 


堆配置:
   MinHeapFreeRatio = 40 
   MaxHeapFreeRatio = 70 
   MaxHeapSize = 1073741824(1024.0MB)
   NewSize = 335544320(320.0MB)
   MaxNewSize = 335544320(320.0MB)
   OldSize = 5439488(5.1875MB)
   NewRatio = 2 
   SurvivorRatio = 8 
   PermSize = 205520896(196.0MB)
   MaxPermSize = 205520896(196.0MB)


堆使用情況:
PS Young Generation    伊甸園
空間:
容量= 255852544(244.0MB)
   使用= 101395504(96.69828796386719MB)
   free = 154457040(147.3017120361328MB)
   39.63044588683081%
來自太空:
   容量= 34144256(32.5625MB)
   使用= 33993968(32.41917419433594MB)
   自由= 150288(0.1433258056640625MB)
   99.55984397492803%用於
太空:
   容量= 39845888(38.0MB)
   使用= 0(0.0MB)
   自由= 39845888( 38.0MB)
   0.0%使用
PS舊代
   容量= 469762048(448.0MB)
   使用= 44347696(42.29325866699219MB)
   免費= 425414352(405.7067413330078 MB)
   9.440459523882184%使用
PS Perm Generation 
   容量= 205520896(196.0MB)
   使用= 85169496(81.22396087646484MB)
   free = 120351400(114.77603912353516MB)
   41.440796365543285%使用

結果是比較健康的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM