jvm參數詳解

最近閱讀了《深入理解java虛擬機》這本書,感覺寫的非常不錯。總結一下jvm常用參數,jvm參數對虛擬機優化起着至關重要的作用。jvm參數主要包括三種:堆和棧空間設置、垃圾收集器設置(包括併發gc)以及其他的輔助配置(統計跟蹤、逃逸分析等),下面詳細介紹下這三種參數的配置。至於棧、堆、垃圾回收、線程、字節碼等慢慢會在其他博文中描述。

堆和棧空間設置:

堆空間:heap=young+old,既:堆空間=年輕代+老年代。其中年輕代:young=2*survivor+eden,既:年輕代=兩個survivor空間+1個eden空間。堆空間保存了new出對象和數組的實際數據,也是gc最愛回收的。同時對對空間進行了分代管理:

  • 年輕代:創建的新對象會被放入年輕代的eden空間,而年輕代gc採用複製算法,複製算法會把內存分爲兩個區域(即兩個survivor空間:from和to)。當進行一次minor gc時(既年輕代的gc),minor gc是串行的,eden空間如果沒有被gc root引用的會被回收,而依然存活的會被移動到from空間中,如果from空間在minor gc時對象依舊可以存活,就會對該對象年齡+1,當年齡達到一定數值時會直接放入老年代,沒有達到年齡的存活對象會被複制到to中。這時from和eden空間已經被清空,虛擬機會交換from和to的空間,空的from變成to,to的變成from,保證了to是空的,minor gc會不斷重複這樣的工作,直到to徹底被填滿,這時會將對象移動到老年代。

  • 老年代:老年代空間的對象是經過minor gc反覆錘鍊出來的。老年代使用並行的gc回收期,標記-清除算法,並且產生的是full gc(major gc)。老年代gc雖然是並行的,但full gc會同時對年輕代進行gc,所以大量的full gc會嚴重耗費jvm的性能,甚至卡死應用。另外可以大對象會直接分配到老年代,避免了在minor gc對兩個survivor空間的複製耗時。

永久代:也就是方法棧注意java8中永久代被徹底移除了。永久代包含了Class的元信息和常量池。該區域是gc最不愛回收的。

棧空間:分爲本地方法棧和虛擬機棧,本地方法棧是被聲明爲native的方法存放的空間。虛擬機棧是我們通常說的棧,線程私有,隨着線程銷燬而銷燬,gc是不管這裏的。包含了:局部變量表、操作數棧、動態鏈表、方法出口信息等。我們常用的hotspot把本地方法棧和虛擬機棧合成了一個。

  • -Xmx:最大堆內存,如 java -Xmx1024m
  • -Xms:初始化堆內存大小,如 java -Xmx1024m -Xms1024m,注意如果這最大和初始化堆大小設置相同的話,可以防止jvm的堆內存動態擴容
  • -Xmn:年輕代空間大小,如java -Xmx1024m -Xms1024m -Xmn256m
  • -Xss:線程棧大小,如java -Xmx1024m -Xms1024m -Xmn256m -Xss128k,注意jdk1.5之前每個線程棧默認爲256k,之後是1m,越多的線程棧空間能換取的線程數越少,反之越少的線程棧空間能換取的線程數越多
  • -Xoss:本地方法棧大小,對hotspot無效
  • -XX:NewRatio:設置年輕代與老年代的比例,如java -Xmx1024m -Xms1024m -Xss128k -XX:NewRatio=4
  • -XX:SurvivorRatio:設置survivor空間佔年輕代空間的比例,如:java -Xmx1024m -Xms1024m -Xmn256m -XX:SurvivorRatio=4,eden:survivor=4:2
  • -XX:MaxPermSize:永久代空間大小,如:java -Xmx1024m -Xms1024m -Xss128k -XX:MaxPermSize=16m
  • -XX:MaxTenuringThreshold:年輕代最大gc年齡,如果超過這個閾值會直接接入老年代,如果設置爲0,年輕代不經過survivor空間直接進入老年代,如:java -Xmx1024m -Xms1024m -Xss128k -XX:MaxTenuringThreshold=0
  • -XX:PretenureSizeThreshold:設置大對象直接進入老年代的閾值,當大對象大小超過該值將會直接在老年代分配。如:java -Xmx1024m -Xms1024m -XX:PretenureSizeThreshold=5242880

垃圾收集器設置:
在jdk1.6中提供的gc年輕代分爲:Serial、Parallel Scavenge、ParNew,而老年代分爲:Serial、Parallel、CMS。在jdk1.7中加入了G1。其中Serial爲串行gc,是jvm參數指定-client時使用的默認gc。Parallel和ParNew爲串行gc,jvm參數指定-server時使用的默認gc爲Parallel Scavenge,同樣CMS爲老年代並行gc,G1爲jdk1.7實驗性gc,爲java9默認的gc。
串行gc在垃圾回收時會stop the world,既停止當前用戶線程,然後進行垃圾回收,這樣做的目的是防止用戶線程繼續運行產生內存碎片。而串行gc在垃圾回收時通常不會stop the world,而CMS gc會進行多次垃圾回收(期間會進行一次短暫的stop the world)或者壓縮來減少內存碎片。
另外Parallel Scavenge和ParNew的區別在於Parallel Scavenge更關注與吞吐量,既吞吐量配置參數可控。
G1垃圾回收器將內存從分代轉換爲分塊,將內存分配爲多塊大小相等的heap,每個heap有獨立的eden、survivor、old空間,在內存邏輯上都是連續的。採用並行標記壓縮方式。

  • -XX:+UseSerialGC:在新生代和老年代使用串休gc
  • -XX:+UseParNewGc:在新生代使用並行gc
  • -XX:+UseParallelOldGC:在老年代使用並行gc
  • -XX:ParallelGCThread:設置Parallel gc的垃圾回收線程數,通常與cpu數量相同
  • -XX:MaxGCPauseMillis:設置最大垃圾收集停頓時間,垃圾回收器會盡量控制回收的時間在該值範圍內
  • -XX:GCPauseIntervalMillis:設置停頓時間間隔
  • -XX:GCTimeRatio:設置吞吐量大小,0~100之間的整數。若該值爲n,那麼jvm將會花費不超過1/(1+n)的時間用於垃圾回收。
  • -XX:+UseAdaptiveSizePolicy:開啓自適應gc策略,jvm會根據運行時吞吐量等信息自動調整eden、old等空間大小以及晉升老年代年齡
  • -XX:+UseConcMarkSweepGC:新生代使用ParNew,老年代使用CMS和Serial,其中老年代的Serial用於作爲CMS失敗時調用的備選gc
  • -XX:+ParallelCMSThreads:CMS線程數量
  • -XX:CMSInitiatingOccupancyFraction:設置老年代空間被使用多少後觸發CMS gc,默認爲68%
  • -XX:CMSFullGCsBeforeCompaction:設置多少次CMS回收後,進行一次內存壓縮
  • -XX:+CMSClassUnloadingEnabled:在類卸載後進行CMS回收
  • -XX:+CMSParallelRemarkEnabled:啓用並行重標記
  • -XX:CMSInitiatingPermOccupancyFraction:當永久代空間被使用多少後觸發CMS gc,百分比(在使用時CMSClassUnloadingEnabled必須被配置)
  • UseCMSInitiatingOccupancyOnly:只有當gc達到配置的閾值時才進行回收
  • XX:+CMSIncrementalMode:使用增量模式,適合單CPU
  • XX:+UserG1GC:使用G1回收器,與G1相關的虛擬機參數都只能在jdk1.7以上使用
  • XX:+UnlockExperimentalVMOptions:允許使用實驗性參數
    輔助設置:
  • -XX:+PrintGC:輸出GC垃圾回收日誌
  • -verbose:gc:與-XX:+PrintGC相同
  • -XX:+PrintGCDetail:輸出詳細的GC垃圾回收日誌
  • -XX:+PrintGCTimeStamps:輸出GC回收的時間戳
  • -XX:+PrintGCApplicationStoppedTIme:輸出GC垃圾回收時所佔用的停頓時間
  • -XX:+PrintGCApplicationConcurrentTime:輸出GC並行回收時所佔用的時間
  • -XX:+PrintHeapAtGC:輸出GC前後詳細的堆信息
  • -Xloggc:filename:把GC日誌輸出到filename指定的文件
  • -XX:+PrintClassHistogram:輸出類信息
  • -XX:+PrintTLAB:輸出TLAB空間使用情況
  • -XX:+PrintTenuringDistribution:輸出每次minor GC後新的存活對象的年齡閾值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章