JVM垃圾收集器

Garbage Collector(GC)自動管理應用程序的動態(tài)內(nèi)存分配請求

垃圾收集器通過以下操作執(zhí)行自動動態(tài)內(nèi)存管理:

  • 從操作系統(tǒng)申請內(nèi)存并將內(nèi)存返回給操作系統(tǒng)
  • 在應用程序請求時將內(nèi)存分發(fā)給應用程序
  • 確定應用程序仍在使用該內(nèi)存的哪些部分
  • 回收未使用的內(nèi)存以供應用程序重用

Java HotSpot垃圾收集器采用各種技術來改進這些操作的效率:

  • 將分代清理(generational scavenging)與年齡(aging)結(jié)合使用旺垒,將精力集中在堆中最可能包含大量可回收內(nèi)存的區(qū)域
  • 使用多個線程并行操作,或者在后臺與應用程序并發(fā)執(zhí)行需要長運行時間的操作
  • 嘗試通過整理(compacting, 壓實)存活的對象來恢復更大的連續(xù)內(nèi)存

虛擬機內(nèi)程序計數(shù)器巍佑、虛擬機棧、本地方法棧3個運行時數(shù)據(jù)區(qū)是線程私有的內(nèi)存區(qū)域瞬逊,內(nèi)存分配回收都比較確定哎媚,隨著方法和線程的結(jié)束占遥,回收內(nèi)存,而堆和方法區(qū)是線程共享的存儲區(qū)域瞻讽,內(nèi)存的分配和回收是動態(tài)的鸳吸,是GC處理的核心

Java 11 GC Tuning Guide 文檔:
Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide, Release 11

Java 9 和11中GC,堆大小速勇,及時編譯的默認設置:

  • 使用Garbage-First (G1) collector (Java 7 和 8 默認是 Parallel GC)
  • GC 線程的最大值受堆大小和可獲得的CPU資源限定
  • 初始堆大小為物理內(nèi)存的 1/64
  • 堆的最大值默認是物理內(nèi)存的 1/4
  • 分層編譯Tiered compiler, 同時使用 C1 and C2編譯器

基于行為的調(diào)優(yōu)

在行為上晌砾,GC主要有兩個不同的目標,一個是控制GC的最長停頓時間烦磁,使得響應更加及時养匈,另一個方面是控制吞吐量,使得GC時間占比較小都伪,Java HotSpot VM GC 可以配置為優(yōu)先滿足這兩個目標之一呕乎,如果滿足首選目標,GC會嘗試最大化另一個目標陨晶,因為堆內(nèi)存大小的限制猬仁,以及其他的配置的影響,也存在GC不能滿足目標的可能

最大暫停時間 Maximum Pause-Time

暫停時間是垃圾收集器停止應用并回收不再使用的內(nèi)存空間的持續(xù)時間先誉,-XX:MaxGCPauseMillis=<n>用來限制暫停的最長時間湿刽,不同GC的默認值不同,調(diào)整得過小可能導致垃圾收集更頻繁地發(fā)生褐耳,從而降低應用程序的整體吞吐量

GC會記錄平均停頓時間和相對平均值的偏差诈闺,如果平均值加上暫停時間的偏差大于目標值,則目標停頓時間未滿足

吞吐量 Throughput

吞吐量是根據(jù)GC所花費和在垃圾收集之外花費的時間application time來衡量的铃芦,由-XX:GCTimeRatio=nnn指定雅镊。垃圾收集時間與應用時間的比率為1/ (1+nnn)襟雷,例如书斜,-XX:GCTimeRatio=19設置垃圾收集為總時間的1/20或5%懦砂。

垃圾收集所花費的時間是所有垃圾收集引起的暫停的總時間悼沿。如果未滿足吞吐量目標凫岖,則GC可能會增加堆的大小,以便在兩次GC停頓時間之間在應用時間更長

內(nèi)存占用

如果已滿足吞吐量和最大暫停時間的設定浮声,則垃圾收集器會減小堆大小怨咪,直到無法滿足其中的吞吐量目標×欧梗可以使用-Xms=<nnn>-Xmx=<mmm>分別設置GC可以使用的最小和最大堆大小

優(yōu)化策略

  • 除非知道需要的堆空間大于默認最大堆大小(物理內(nèi)存的四分之一),否則不要為堆設定最大值
  • 應用程序行為的改變會導致堆增長或縮小胧砰。例如鳍鸵,如果應用以更高的速率分配空間,則堆空間需要增長來保持相同的吞吐量
  • 如果堆增長到其最大大小并且未滿足吞吐量目標尉间,則最大堆大小對于吞吐量目標而言太小偿乖。可以將最大堆大小設置為接近物理內(nèi)存的值
  • 如果可以滿足吞吐量目標哲嘲,但暫停時間過長贪薪,設定最大暫停時間,吞吐量可能目標無法滿足眠副,因此需要選擇一個可接受的折中值

判斷對象是否存活

GC回收堆內(nèi)存空間之前首先要判斷對象是否存活

  • 引用計數(shù)算法 Reference Counting
    每個對象都有一個引用計數(shù)器画切,有引用的地方就加1,引用失效的時候就減1囱怕,為0就可以回收
    問題:很難解決對象之間的相互循環(huán)引用的問題

  • 可達性分析算法 Reachability Analysis
    如果程序中的任何其他存活對象的引用無法再訪問它霍弹,對象被認為是垃圾,此時VM可以重用它的內(nèi)存娃弓,通過一系列稱為GC Roots的對象作為起始點典格,從這些節(jié)點開始向下搜索,搜索所有走過的路徑稱為引用鏈Reference Chain台丛,當一個對象到GC Roots沒有任何引用鏈相連時耍缴,說明對象不可用

GC Roots對象的種類

  • 虛擬機棧中引用的對象 Local variables
  • 方法區(qū)類靜態(tài)屬性或常量引用的對象 Static variables
  • 本地方法棧中JNI引用的對象

引用

java.lang.ref package

一個對象的引用,根據(jù)引用強度的強弱挽霉,分為四種防嗡,GC時根據(jù)不同的情況,決定是否回收對應類型對象的內(nèi)存空間

  • 強引用 Strong Reference
    默認的引用類型,只要存在強引用炼吴,GC就不會回收引用的對象本鸣,默認創(chuàng)建都是強引用類型

  • 軟引用 Soft Reference
    當虛擬機內(nèi)部不足,拋出OutOfMemoryError之前硅蹦,GC會清除這些對象的內(nèi)存荣德,通常用于實現(xiàn)對內(nèi)存敏感的緩存闷煤,內(nèi)存不足會自動清除

SoftReference<User>softReference=new SoftReference<User>(new User());
  • 弱引用 Weak Reference
    非必須的對象,當垃圾收集器工作時涮瞻,無論內(nèi)存是否足夠鲤拿,都會回收掉只被弱引用關聯(lián)的對象
WeakReference<User> weakBuilder = new WeakReference<User>(new User());
  • 虛引用 Phantom Reference
    無法通過虛引用獲取一個對象的實例,get()方法返回始終為NULL
    唯一目的就是在這個對象回收時收到一個系統(tǒng)通知署咽,例如在NIO的DirectByteBuffer內(nèi)進行native內(nèi)存釋放的Cleaner
package jdk.internal.ref;
public class Cleaner
    extends PhantomReference<Object>
  • ReferenceQueue
    在檢測到適當?shù)目傻竭_性更改后近顷,垃圾回收器將已注冊的引用對象添加到該隊列中,內(nèi)部事先由GC組成一個PendingList宁否,然后通過在Reference類初始化時窒升,靜態(tài)塊內(nèi)部創(chuàng)建的ReferenceHandler線程將其取出加入到引用隊列中

引用對象的狀態(tài)由兩個屬性表征:

最開始處于Active狀態(tài),當Reference對應的對象可以被垃圾收集器回收時慕匠,GC會將該Reference的狀態(tài)轉(zhuǎn)換為Pending饱须,經(jīng)過ReferenceHandler處理后轉(zhuǎn)變?yōu)?code>Inactive

                         clear/enqueue/GC 
 [active/unregistered]   ------
        |                      |
        | GC                   |
        |                      |--> [inactive/unregistered]
        v                      |
 [pending/unregistered]  ------
                         ReferenceHandler

如果Reference對象創(chuàng)建時指定了ReferenceQueue則對應狀態(tài)為Registered,GC將其加入到PendingList台谊,ReferenceHandler將其讀取出來蓉媳,加入引用隊列后狀態(tài)轉(zhuǎn)變?yōu)?code>Enqueued,用戶線程調(diào)用ReferenceQueue.remove()函數(shù)阻塞式獲取隊列中的對象锅铅,來獲知某個引用要被回收酪呻,這相當于一種通知機制,從隊列中取出后狀態(tài)轉(zhuǎn)變?yōu)?code>Dequeued

內(nèi)部具體實現(xiàn)上盐须,當加入ReferenceQueue之后玩荠,引用對象中的隊列信息ReferenceQueue<? super T> queue會被自動覆蓋為NULL,下次GC需要回收時就無法再次加入引用隊列丰歌,內(nèi)存空間會被直接回收

                           clear
  [active/registered]     ------->   [inactive/registered]
         |                                 |
         |                                 | enqueue [2]
         | GC              enqueue [2]     |
         |                -----------------|
         |                                 |
         v                                 |
  [pending/registered]    ---              v
         |                   | ReferenceHandler
         | enqueue [2]       |--->   [inactive/enqueued]
         v                   |             |
  [pending/enqueued]      ---              |
         |                                 | poll/remove
         | poll/remove                     |
         |                                 |
         v            ReferenceHandler     v
  [pending/dequeued]      ------>    [inactive/dequeued]

Reference時創(chuàng)建時姨蟋,附加一個引用隊列參數(shù)

Reference(T referent, ReferenceQueue<? super T> queue)
  • FinalReference
    實現(xiàn)Object的finalize()方法的類,在創(chuàng)建對象的時立帖,JVM會實例化一個對應的FinalReference

  • Finalizer
    Finalizer是FinalReference的子類眼溶,該類被final修飾,不可再被繼承晓勇,JVM實際操作的是Finalizer類堂飞,當滿足實例化FinalReference的條件時,JVM會調(diào)用Finalizer.register(Object finalizee)進行注冊绑咱,對應的引用隊列是Finalizer類內(nèi)部的靜態(tài)變量private static ReferenceQueue<Object> queue = new ReferenceQueue<>();绰筛,靜態(tài)塊中的初始化的FinalizerThread線程從引用隊列中取出元素,執(zhí)行其finalize()方法


方法區(qū)的回收

Permanent generation(方法區(qū))存儲描述類和方法的元數(shù)據(jù)描融,需要回收兩個部分的內(nèi)存:廢棄常量和無用的類

其中無用的類需要同時滿足以下三個條件:

  • 類的所有實例已經(jīng)被回收
  • 加載該類的ClassLoader 已經(jīng)被回收
  • 該類的java.lang.Class對象沒有再任何地方被引用铝噩,后續(xù)不會通過反射的方式訪問該類

垃圾收集算法基礎

性能考慮

GC主要關注兩點,吞吐量和延遲

  • 吞吐量是一段長時間周期內(nèi)不考慮的GC的時間占總時間的百分比窿克,吞吐量包括分配內(nèi)存所花費的時間(但通常不需要調(diào)優(yōu)內(nèi)存分配速度)
  • 延遲是應用程序的響應能力骏庸,GC暫停會影響應用程序的響應能力毛甲。

標記 - 清除 Mark-Sweep

首先對所有需要回收的對象進行標記,后來統(tǒng)一回收
這是最基礎的收集算法具被,后續(xù)的收集算法都是基于這種思路玻募,并對其不足進行改進而得到的

不足:

  1. 效率不高
  2. 空間問題,產(chǎn)生大量不連續(xù)的碎片

標記 - 整理 Mark-Compact

讓所有存活對象向一端移動一姿,然后直接清理掉端邊界以外的內(nèi)存

分代收集 Generational Collection

理論上七咧,最直接的垃圾收集算法每次運行時遍歷每個可到達的對象,任何剩余的對象都被認為是垃圾叮叹。這種方法所花費的時間與活動對象的數(shù)量成正比艾栋,這對于維護大量實時數(shù)據(jù)的大型應用程序來說是不可行的

Java HotSpot VM包含許多不同的垃圾收集算法,這些算法都使用稱為分代收集 generational collection 的技術衬横。分代收集利用幾條對大多數(shù)應用程序的經(jīng)驗觀測屬性來最小化回收未使用(垃圾)對象所需的工作裹粤。其中最重要屬性是是弱分代假說 weak generational hypothesis,它表明大多數(shù)對象都只能存活很短的時間

對象壽命的典型分布

堆區(qū)根據(jù)對象存活周期的不同將內(nèi)存分為幾塊蜂林,例如新生代和老年代,區(qū)域填滿時采用不同的收集算法

最開始拇泣,JVM會保留整個Java堆的地址空間噪叙,但是只有在需要的時候才分配物理內(nèi)存

Young Generation 對象填滿時,觸發(fā) minor collection 回收該區(qū)域霉翔,時間復雜度與活動對象的數(shù)量成比例睁蕾,通常每次會有部分幸存對象移動到Old Generation,當它填滿時觸發(fā) major collection 進行回收债朵,清理整個堆區(qū)域子眶,通常所需的時間更長,因為涉及更多的對象

復制算法 Copying

新生代代由Eden和兩個Survivor空間組成序芦,大多數(shù)對象最初都是在Eden中分配的臭杰,在任何時候必然由一個Survivor空間是空的,在GC期間充當Eden和另一個Survivor空間中存活對象的目的地谚中;GC之后渴杆,Eden和源Survivor空間都是空的。在下一次GC中宪塔,兩個Survivor空間的用途互換了磁奖。最近被填充的一個作為源Survivor,將其中的存活對象復制到另一個Survivor空間某筐。 對象以這種方式在兩個Survivor之間復制比搭,直到它們被復制了一定次數(shù)或者沒有足夠的空間,此時這些對象將被復制到老年代中(這個過程叫做aging)

新生代和老年代的晉升

每個對象在新生代有個年齡值南誊,如果經(jīng)歷一次minor gc蜜托,對應的年齡就會增加同廉,達到閾值(-XX:MaxTenuringThreshold=n設定蟆湖,n的最大值為15,parallel collector 默認15结窘,CMS 默認為6),即可晉升,移動到老年代

如果Survivor空間中相同年齡所有對象大小之和大于Survivor空間的一半派草,年齡大于或者等于該年齡的對象可以直接進入年老代歧譬,無需達到閾值的要求

術語:
full GC:清理整個Java 堆區(qū)
Stop the World Event : JVM上所有的應用都停止缩焦,直到gc操作完成,無論哪種gc算法嵌赠,無論是新生代還是老年代都會產(chǎn)生STW

影響垃圾收集性能的因素

兩個最重要的因素是總可用內(nèi)存新生代在堆中的比例

堆空間總量 Total Heap

這是影響垃圾收集性能的最重要因素袜炕,因為GC在對應分代的內(nèi)存填滿時發(fā)生


在初始化虛擬機時,保留堆的整個空間初家,-Xmx選項指定保留空間的大小,如果-Xms參數(shù)的值小于-Xmx參數(shù)的值乌助,則不會將所有保留的空間立即交給虛擬機溜在,未提交的空間在圖中標記為virtual,隨后堆的不同分區(qū)他托,可以根據(jù)需要向虛擬空間增長

新生代比例

新生代越大掖肋,發(fā)生的minor collection就越少,但是赏参,堆大小本身是有限的志笼,新生代比例較大意味著老年代比例較小,這將增加major collection的頻率把篓,最佳比例取決于程序內(nèi)對象的生命周期分布纫溃,設定-XX:NewSize=size-XX:MaxNewSize=size韧掩,-XX:NewRatio=ratio

其中如果survivor空間太小紊浩,那么復制收集算法會將數(shù)據(jù)溢出到老年代,如果太大,浪費空間坊谁,設定-XX:SurvivorRatio=ratio


垃圾收集器

JDK 9 到 目前(JDK 11)费彼,Java HotSpot VM包括三種不同類型的收集器,每種收集器具有不同的性能特征

Serial Collector (-XX:+UseSerialGC)

串行收集器使用單個線程來執(zhí)行所有垃圾收集工作口芍,這使得它相對有效箍铲,因為線程之間沒有通信開銷,它最適合單處理器機器鬓椭,因為它無法利用多處理器硬件颠猴,也適用于多處理器上的小型應用程序(內(nèi)存大小為100MB左右)

使用選項-XX:+UseSerialGC顯式啟用串行收集器,使用分代收集的原理膘融,新生代使用復制算法芙粱,老年代使用標記整理算法

Parallel Collector (-XX:+UseParallelGC)

并行收集器也稱為吞吐量收集器throughput collector,它是類似于串行收集器的分代收集器氧映。串行和并行收集器之間的主要區(qū)別在于并行收集器具有多個線程春畔,用于加速垃圾收集。

并行收集器適用于運行在多處理器或多線程硬件上的具有中到大型數(shù)據(jù)集的應用程序岛都,使用-XX:+UseParallelGC選項啟用律姨,新生代使用parallel scavenge garbage collector,老年代parallel garbage collector臼疫,如果啟動-XX:+UseParallelGC選項择份,會默認啟動-XX:+UseParallelOldGC設定,反之亦然

可以使用-XX:ParallelGCThreads=<N>來控制垃圾收集器線程的數(shù)量烫堤。因為多個垃圾收集器線程參與minor collection荣赶,在收集期間從新生代晉升(promotion)到老年代可能產(chǎn)生一些碎片minor collection中的每個垃圾收集線程都會保留老年代的一部分用于晉升鸽斟,將可用空間劃分為“晉升緩沖區(qū)”會導致碎片效應拔创,減少垃圾收集器線程的數(shù)量并增加老年代的大小可以減少這種碎片效應

并行收集器的代分布

并行收集器目標的優(yōu)先級:當同時設定由最大暫停時間目標,吞吐量目標和最小內(nèi)存目標時富蓄,首先滿足最大暫停時間目標剩燥,之才是吞吐量目標,最后是內(nèi)存目標

如果超過98%的總時間花在垃圾收集上并且不到2%的堆空間被回收立倍,則拋出OutOfMemoryError灭红,防止應用程序長時間運行,但由于堆太小進度很慢口注。也可以通過-XX:-UseGCOverheadLimit來禁用此功能

ParNew (-XX:+UseParNewGC)/ CMS (-XX:+UseConcMarkSweepGC)

ParNew GC在新生代中使用多線程進行垃圾收集变擒,與用于清理老年代的CMS算法配合使用
當設定-XX:+UseConcMarkSweepGC時自動使用,在JDK 8中-XX:+UseParNewGC必須和-XX:+UseConcMarkSweepGC配合使用疆导,選項組合-XX:+UseConcMarkSweepGC -XX:-UseParNewGC已經(jīng)棄用赁项,從JDK 9開始葛躏,棄用-XX:+UseParNewGC選項

Concurrent Collectors

Concurrent Mark Sweep (CMS)和 Garbage-First (G1) 垃圾收集器是兩個主要的并發(fā)收集器,并發(fā)收集器在執(zhí)行一些昂貴的工作時與應用程序并發(fā)運行

  • G1垃圾收集器:服務器式收集器悠菜,適用于具有大量內(nèi)存的多處理器計算機舰攒。 它有很高的概率滿足垃圾收集停頓時間的要求,同時實現(xiàn)高吞吐量悔醋,很多參數(shù)可以自適應調(diào)節(jié)摩窃,使用簡單高效。Java 9 開始默認使用G1芬骄,可以使用-XX:+UseG1GC顯式啟用G1
  • CMS收集器:適用于需要較短垃圾收集暫停且可以與GC共享處理器資源的應用程序猾愿,使用選項-XX:++UseConcMarkSweepGC啟用CMS收集器,從JDK 9開始账阻,CMS收集器已經(jīng)被棄用

并發(fā)收集器交換處理器資源(否則可供應用程序使用)以縮短主要收集暫停時間蒂秘。

最明顯的開銷是在GC的并發(fā)部分會使用一個或多個處理器,在N處理器系統(tǒng)上淘太,并發(fā)部分使用可用處理器的 K/N姻僧,其中1 <= K <= ceiling{N/4}。除了在并發(fā)階段使用處理器之外蒲牧,還會產(chǎn)生額外的開銷以實現(xiàn)并發(fā)撇贺。因此,雖然并發(fā)收集器的垃圾收集暫停通常要短得多冰抢,但應用程序吞吐量也往往略低于其他收集器

在多核的計算機上松嘶,應用程序線程在并發(fā)部分期間依然可以獲得處理器,因此并發(fā)垃圾收集器線程不會暫停應用程序挎扰,使得暫停時間縮短翠订,但應用程序可用的處理器資源也會減少,并且應該會有一些減速遵倦,特別是如果應用程序最大限度地使用所有核蕴轨。隨著N的增加,由于并發(fā)垃圾收集導致的處理器資源的減少變得更小骇吭,并發(fā)收集的益處也會增加

Z Garbage Collector

Z垃圾收集器 (ZGC) 是一個可擴展的低延遲垃圾收集器。 ZGC并發(fā)式的執(zhí)行所有昂貴的工作歧寺,不需要停止執(zhí)行應用線程

ZGC適用于需要低延遲(小于10毫秒暫停)和/或使用非常大的堆(TB量級)的應用燥狰,使用-XX:+UseZGC啟用,從JDK 11開始斜筐,ZGC作為實驗性功能提供


選擇合適的GC

如有必要龙致,先調(diào)整堆大小來提高性能。如果性能仍不符合要求

  1. 如果應用程序具有較小的數(shù)據(jù)集(最大約100 MB)或者在單個處理器上運行且沒有暫停時間要求顷链,則選擇串行收集器-XX:+UseSerialGC
  2. 如果應用程序的極限性能是第一優(yōu)先級考慮并且沒有暫停時間要求目代,或者可以接收一秒或更長的暫停時間,那么可以讓VM選擇收集器或選擇并行收集器-XX:+UseParallelGC
  3. 如果響應時間比總吞吐量更重要,并且垃圾收集暫停必須保證短于一秒左右榛了,那么選擇并發(fā)收集器-XX:+UseG1GC-XX:+UseConcMarkSweepGC.
  4. 如果響應時間是高優(yōu)先級在讶,和/或使用的是非常大的堆內(nèi)存,選擇完全并發(fā)的收集器-XX:+UseZGC

此外性能還取決于堆的大小霜大,應用程序內(nèi)的實時數(shù)據(jù)量以及處理器的數(shù)量和速度构哺,如果推薦的收集器未達到所需性能,則首先嘗試調(diào)整堆和分代的大小战坤。如果性能仍然不足曙强,那么嘗試使用不同的收集器:使用并發(fā)收集器來減少暫停時間,使用并行收集器來提高多核處理器的總吞吐量


參數(shù)配置

選項

-X:非標準選項(不保證所有的 JVM 實現(xiàn)都支持)
-XX:不穩(wěn)定途茫、不建議隨便使用

  • 布爾選項 打開-XX:+<option> 碟嘴,關閉 -XX:-<option>
  • 數(shù)值選項 設定方式-XX:<option>=<number>,數(shù)字可以包含 'm' 'M' , 'k' 'K' f, 'g' 'G'
  • 字符串選項 設定-XX:<option>=<string>

查詢某個參數(shù)的默認值囊卜,例如MaxHeapSize的值

> java -XX:+PrintFlagsFinal  -version | grep MaxHeapSize
    uintx MaxHeapSize                              := 4173332480                          {product}
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

選項 描述
堆椖壬龋空間相關
-Xms -Xmx 堆的最小值和最大值,對于服務器的部署边败,通常設定為相同的值,避免堆大小調(diào)整產(chǎn)生的暫停
-Xss 設定線程調(diào)用棧的大小袱衷,默認是1M,默認操作系統(tǒng)ulimit -s限定最大為8192KB
-Xmn 新生代的大小笑窜,直接設定為固定值致燥,可以通過-XX:NewSize-XX:MaxNewSize分別設定初始大小和最大值
-XX:MaxHeapFreeRatio GC后堆空間的最大空閑比例(默認70%,達到會進行收縮)排截,調(diào)小會減小內(nèi)存占用
-XX:MinHeapFreeRatio GC后堆空間的最小空閑比(默認40%嫌蚤,不足堆空間會進行擴張),調(diào)小會減少內(nèi)存占用
-XX:-ShrinkHeapInSteps 默認情況下開啟断傲,逐步減小堆空間到最大空閑比脱吱,關閉會立即減小,可能導致性能下降
GC類型
-XX:+UseG1GC 使用G1收集器
-XX:+UseSerialGC 使用Serial GC
-XX:+UseParallelGC 使用 Parallel Scavenge GC
-XX:+UseParallelOldGC 使用 Parallel Old GC
-XX:+UseParNewGC deprecated认罩,JDK 9
-XX:+UseConcMarkSweepGC deprecated箱蝠,JDK 9
GC性能設定
-XX:MaxGCPauseMillis=n 設定最長停頓時間,毫秒
-XX:GCTimeRatio=n 吞吐量設定垦垂,1 / (1 + n)宦搬,G1默認為12,GC時間占比8%
-XX:ParallelGCThreads=n 設置STW工作線程的值劫拗,邏輯處理器的數(shù)量不超過8時间校,n的默認值與邏輯處理器的數(shù)量相同,如果有超過8個邏輯處理器页慷,n默認值為邏輯處理器數(shù)量的5/8
新生代相關
-XX:NewRatio=n young : old = 1 : n 憔足,默認n為2
-XX:NewSize 新生代的初始大小胁附,推薦為堆大小的25%到50%
-XX:MaxNewSize 新生代的最大值
-XX:SurvivorRatio=n eden/survivor區(qū)域的比例,默認為8滓彰,即每個survivor占新生代的1/10控妻,默認-XX:+UseAdaptiveSizePolicy是開啟的,JVM會動態(tài)調(diào)整survivor的大小比例找蜜,最小為3
-XX:MaxTenuringThreshold=n 對象晉升老年代的年齡閾值饼暑,parallel gc默認15,CMS默認為6
G1相關設置
-XX:G1HeapRegionSize 堆區(qū)域的大小洗做,默認基于初始和最大堆大小得到弓叛,在1到32 MB之間變化,并且必須是2的冪诚纸,堆包含大約2048個堆區(qū)域
-XX:InitialHeapOccupancyPercent 默認整個堆占比45%時觸發(fā)并發(fā)標記
-XX:ConcGCThreads 并發(fā)標記的線程數(shù)目撰筷,ParallelGCThreads的 1/4
-XX:+G1UseAdaptiveIHOP -XX:InitiatingHeapOccupancyPercent=45 用于自適應控制啟動并發(fā)標記的堆占用百分比,對于前幾個收集周期G1將使用老年代的45%的占用率作為默認閾值
-XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60 新生代的大小畦徘,在這兩個值之間變化毕籽,百分比表示占當前使用的Java堆的比例
-XX:G1HeapWastePercent=5 區(qū)域集合中允許未回收空間百分比,如果收集集合候選中的可回收空間低于該閾值井辆,則G1將停止空間回收階段
-XX:G1MixedGCCountTarget=8 空間回收階段的進行收集的次數(shù)
-XX:G1MixedGCLiveThresholdPercent=85 老年代區(qū)域的存活對象大于該比例关筒,不會在空間回收階段進行垃圾收集
CMS設置
-XX:CMSInitiatingOccupancyFraction 設置啟動CMS的老年代占用率,默認值為-1杯缺,使用-XX:CMSTriggerRatio的值
-XX:CMSTriggerRatio=percent 內(nèi)存占用達到-XX:MinHeapFreeRatio的percent%時啟動CMS蒸播,默認值是80%
其他
-XX:MetaspaceSize 設置觸發(fā)gc的元數(shù)據(jù)空間的大小
-Xlog:gc* 發(fā)生垃圾收集時,打印日志萍肆,等同于PrintGCDetails
-Xlog:gc 使用的是JVM Unified Logging Framework輸出log信息袍榆,等同于PrintGC, -Xlog 使用樣式:-Xlog:tag1[+tag2...][*][=level][:[output][:[decorators][:output-options [,...]]]]
-XX:MaxDirectMemorySize java.nio包使用的內(nèi)存數(shù)量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塘揣,一起剝皮案震驚了整個濱河市包雀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亲铡,老刑警劉巖才写,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奖蔓,居然都是意外死亡琅摩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門锭硼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜕劝,你說我怎么就攤上這事檀头『湟欤” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵暑始,是天一觀的道長搭独。 經(jīng)常有香客問我,道長廊镜,這世上最難降的妖魔是什么牙肝? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮嗤朴,結(jié)果婚禮上配椭,老公的妹妹穿的比我還像新娘。我一直安慰自己雹姊,他們只是感情好股缸,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吱雏,像睡著了一般敦姻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歧杏,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天镰惦,我揣著相機與錄音,去河邊找鬼犬绒。 笑死旺入,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的懂更。 我是一名探鬼主播眨业,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沮协!你這毒婦竟也來了龄捡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤慷暂,失蹤者是張志新(化名)和其女友劉穎聘殖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體行瑞,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡奸腺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了血久。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片突照。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖氧吐,靈堂內(nèi)的尸體忽然破棺而出讹蘑,到底是詐尸還是另有隱情末盔,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布座慰,位于F島的核電站陨舱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏版仔。R本人自食惡果不足惜游盲,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛮粮。 院中可真熱鬧益缎,春花似錦、人聲如沸蝉揍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽又沾。三九已至弊仪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杖刷,已是汗流浹背励饵。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滑燃,地道東北人役听。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像表窘,于是被迫代替她去往敵國和親典予。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容