jvm垃圾回收机制 二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gogoky/article/details/71487311

     上一节主要介绍了新生代的 Serial  / PraNew / Parallel Scavenge 三种垃圾回收方法和老年代的serial old 和 paralle old收集器,本节主要介绍CMS和G1垃圾收集器。

目录

CMS收集器-标记整理算法

收集过程

CMS  产生的问题

G1(Garbage First)收集器

收集过程

G1特点

  简单调优

区域(Region)

对象的分配策略

G1的垃圾收集模式

G1问题

注意点

总结


CMS收集器-标记整理算法

CMS(Concurrent Mark Sweep)收集器的设计目标是:获取最短回收停顿时间的收集器

HotSpot在JDK1.5推出的第一款真正意义上的并发(Concurrent)收集器; 第一次实现了让垃圾收集线程与用户线程(基本上同时工作。目前很大一部分的Java应用集中在B/S系统的服务端上,这类应用尤其重视服务器的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。而这也恰恰是CMS所擅长的地方。

图一:CMS垃圾回收流程

收集过程

CMS的垃圾收集一共需要经过四个阶段:

  1. 初始标记:此阶段会产生STW;这个过程只是标记出GC ROOTS能直接关联到的对象,耗时短,速度很快;
  2. 并发标记: 这个步是根据前面提到的GC ROOTS 根搜索算法,会判定对象是“存活”还是“已死”;比如说 A -> B (A 引用 B,假设 A 是 GC Roots 关联到的对象),那么这个阶段就是标记出 B 对象, A 对象会在初始标记中标记出来。
  3. 重新标记: 此阶段会产生STW,主要是为了检查校验并发标记期间,因用户程序继续运行而产生变动的那一部分对象的标记记录和新对象;
  4. 并发清除:该步就是清除系统中无用“以死”的对象;之后将为下次gc做准备;
优点 并发收集,此阶段比较耗时;由于采用并发收集可以减少停顿时间
缺点

(1)由于和用户线程一起工作,CMS收集器对CPU资源非常敏感。CPU个数少于4个时,CMS对于用户程序的影响就可能变得很大,出现cpu资源的竞争;

(2)CMS收集器无法处理浮动垃圾,可能出现“promotion fail  -> Concurrent Mode Failure”失败而导致另一次Full GC的产生。在JDK1.5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活;

(3)CMS是基于“标记-清除”算法实现的收集器,手机结束时会有大量空间碎片产生。空间碎片过多,可能会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前出发FullGC;

  (4) 产生2次STW;

使用场景 重视服务器的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。牺牲吞吐量来获取较小的暂停时间。
参数使用

 

  1. -XX:+UseConcMarkSweepGC 此参数将启动 CMS 回收器。默认新生代是 ParNew + CMS,也可以设置 Serial 为新生代收集器。该参数等价于 -Xconcgc。

  2. -XX:ParallelGCThreads 指定线程数。默认并发线程数是:(ParallelGCThreads + 3)/ 4)

  3. -XX:CMSInitiatingOccupancyFraction 由于 CMS 回收器不是独占式的,在垃圾回收的时候应用程序仍在工作,所以需要留出足够的内存给应用程序,否则会触发 FGC。而什么时候运行 CMS GC 呢?通过该参数即可设置,该参数表示的是老年代的内存使用百分比。当达到这个阈值就会执行 CMS。默认是68。 如果老年代内存增长很快,建议降低阈值,避免 FGC,如果增长慢,则可以加大阈值,减少 CMS GC 次数。提高吞吐量。

  4. -XX:+UseCMSCompactAtFullCollection 由于 CMS 使用标记清理算法,内存碎片无法避免。该参数指定每次 CMS 后进行一次碎片整理。

  5. -XX:CMSFullGCsBeforeCompaction 由于每次进行碎片整理将会影响性能,你可以使用该参数设定多少次 CMS 后才进行一次碎片整理,也就是内存压缩。

  6. -XX:CMSInitiatingPermOccupancyFraction 当永久区占用率达到这一百分比时,启动 CMS 回收(前提是 -XX:+CMSClassUnloadingEnabled 激活了)。

  7. -XX:UseCMSInitiatingOccupancyOnly 表示只在到达阈值的时候才进行 CMS 回收。

  8. XX:CMSWaitDuration=2000 由于CMS GC 条件比较简单,JVM有一个线程定时扫描Old区,时间间隔可以通过该参数指定(毫秒单位),默认是2s。

CMS 的 GC 日志 就是 CMS

增量式并发收集器

      为了解决缺点(1)cpu敏感的问题,虚拟机提供了一种称为“增量式并发收集器”(Incremental Concurrent Mark Sweep/i-CMS)的CMS收集器变种,所做的事情和单CPU年代PC机操作系统使用抢占式来模拟多任务机制的思想一样,就是在并发标记、清理的时候让GC线程、用户线程交替运行,尽量减少GC线程的独占资源的时间,这样整个垃圾收集的过程会更长,但对用户程序的影响就会显得少一些,也就是速度下降没有那么明显。实践证明,增量时的CMS收集器效果很一般,在目前版本中,i-CMS已经被声明为“deprecated”,即不再提倡用户使用。

CMS  产生的问题

CMS并行GC是大多数应用的最佳选择,然而, CMS并不是完美的,在使用CMS的过程中会产生2个最让人头痛的问题:

  • promotion failed
  • concurrent mode failure

    问题解析: 第一个问题promotion failed是在进行Minor GC时,Survivor Space放不下,对象只能放入老年代,而此时老年代也放不下造成的,多数是由于老年带有足够的空闲空间,但是由于碎片较多,这时如果新生代要转移到老年带的对象比较大,所以,必须尽可能提早触发老年代的CMS回收来避免这个问题(promotion failed时老年代CMS还没有机会进行回收,又放不下转移到老年带的对象,CMS运行期间预留的内存无法满足程序其他线程需要因此会出现下一个问题concurrent mode failure,从而回退到:stop-the-wold GC- Serail Old)。

   尽管CMS使用一个叫做分配担保的机制,每次Minor GC之后要保证新生代的空间survivor + eden > 老年带的空闲空间,但是对象分配是不可预测的,总会有写对象分配在老年带是满足不了的。

   这个问题的直接影响就是它会导致提前进行CMS Full GC, 尽管这个时候CMS的老年带并没有填满,只不过有过多的碎片而已,但是Full GC导致的stop-the-wold是难以接受的。

导致以上两个问题的主要原因是:空间不够,或者是因为空间总量够,但是由于碎片导致了没有连续的大的存储空间

对于问题“promotion failed” 解决办法:

  1. -XX:UseCMSCompactAtFullCollection 每次CMS完进行碎片的整理;-XX:CMSFullGCBeforeCompaction=5 5次CMS后进行一次
  2. -Xmn XX:SurvivorRatio 默认为8,通过它调大新生代或者救助空间 ;

对于问题“concurrent mode failure”  解决办法:

  1.  +XX:CMSInitiatingOccupancyFraction 提前进行CMS垃圾回收,默认的值是68%,可以适当的调小;
  2. -Xms -Xmx调大老年带的空间;

G1(Garbage First)收集器

这是一款兼顾新生代和老年代垃圾收集器,是JDK1.7提供的一个新的面向服务端应用的垃圾收集器,用于取代CMS垃圾回收。

图二: G1垃圾收集器

收集过程

G1收集器的运行步骤主要分为以下4步:

1. 初始标记(Initial Marking)
      该阶段会STW。扫描根集合,仅标记一下GC Roots能直接关联到的对象,将所有通过根集合直达的对象压入扫描栈,等待后续的处理。在G1中初始标记阶段是借助Young GC的暂停进行的,不需要额外的暂停。虽然加长了Young GC的暂停时间,但是从总体上来说还是提高的GC的效率。

2. 并发标记(Concurrent Marking)
     该阶段不需要STW。这个阶段不断的从扫描栈中取出对象进行扫描,将扫描到的对象的字段再压入扫描栈中,依次递归,直到扫描栈为空,也就是说trace了所有GCRoot直达的对象。同时这个阶段还会扫描SATB write barrier所记录下的引用。此步比较耗时,但是和应用程序一起工作,并发执行,和CMS一样,效率提高。

3. 最终标记(Final Marking)
    这个阶段会STW,最终标记主要为了找出程序在并发标记期间因用户程序继续运作而发生变化的对象。这个阶段会处理在并发标记阶段write barrier记录下的引用,同时进行弱引用的处理。这个阶段与CMS的最大的区别是CMS在这个阶段会扫描整个根集合,Eden也会作为根集合的一部分被扫描,因此耗时可能会很长。

4. 筛选回收(Live Data Counting and Evacuation)
     该阶段会STW。清点和重置标记状态。这个阶段有点像mark-sweep中的sweep阶段,这个阶段并不会实际上去做垃圾的收集,只是去根据停顿模型在CSet选出任意多个Region作为垃圾收集的目标,等待evacuation阶段来回收。筛选就是依据用户设置【-XX:MaxGCPauseMillis 】的允许的GC时长,在Cset里对排序的各个Region的回收价值和成本预估,控制GC停顿时间来制定回收计划,达到用户的期望;

G1特点

  简单调优

      G1的设计原则就是简单可行的性能调优,开发人员仅仅需要声明以下参数即可:

 -XX:+UseG1GC -Xmx4g -XX:MaxGCPauseMillis=200
  • -XX:+UseG1GC  //为开启G1垃圾收集器,
  • -Xmx4g //设计堆内存的最大内存为4G,
  • -XX:MaxGCPauseMillis=200 //设置GC的最大暂停时间为200ms。

    如果我们需要调优,在内存大小一定的情况下,我们只需要修改最大暂停时间即可,简单方便。G1将新生代,老年代的物理空间划分取消了。

区域(Region)

     G1里面的Region的概念不同于传统的垃圾回收算法中的分区的概念,但是仍然保留里分代的思想。G1默认把堆内存分为1024个分区,后续垃圾收集的单位都是以Region为单位的,仍然属于分代收集器。Region是实现G1算法的基础,每个Region的大小相等,通过-XX:G1HeapRegionSize参数可以设置Region的大小,这样我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。

图3 G1 Region划分

     从图8中可以看出各个区域逻辑上并不是连续的。并且一个Region在某一个时刻是Eden,在另一个时刻就可能属于老年代。G1在进行垃圾清理的时候就是将一个Region的对象拷贝到另外一个Region中。

   Humongous区域

      在G1中,还有一种特殊的区域,叫Humongous区域。 如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。这些巨型对象,默认直接会被分配在年老代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC

对象的分配策略

对象的分配策略分为3个阶段:

  1. TLAB(Thread Local Allocation Buffer)线程本地分配缓冲区;
  2. Eden区中分配;
  3. Humongous区分配;

   TLAB为线程本地分配缓冲区,它的目的为了使对象尽可能快的分配出来。如果对象在一个共享的空间中分配,我们需要采用一些同步机制来管理这些空间内的空闲空间指针。在Eden空间中,每一个线程都有一个固定的分区用于分配对象,即一个TLAB。分配对象时,线程之间不再需要进行任何的同步。对TLAB空间中无法分配的对象 -> JVM会尝试在Eden空间中进行分配 ->  如果Eden空间无法容纳该对象,就只能在老年代中进行分配空间。

G1的垃圾收集模式

  • YoungGC:收集年轻代里的Region;
  • MixGC:年轻代的所有Region+全局并发标记阶段选出的收益高的Region;

Young GC

    工作方式:Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。在这种情况下,Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中。最终Eden空间的数据为空,GC停止工作,应用线程继续执行。

Mixed GC
    如名字一样,“混合收集” 不仅进行正常的新生代垃圾收集,同时也回收线程标记的老年代分区。它的GC步骤主要分2步:
    (1)全局并发标记(global concurrent marking),在G1 gc之前,会进行全局标记;
    (2)拷贝存活对象(evacuation),排序预估回收;

具体运行步骤可参考图1。下面我们来看一下在G1工作的过程中的几个重要的问题。

G1问题

    1、如果仅仅是GC回收新生代对象,如何解决不同Region区域的引用,如何找到所有的根对象呢?

      在垃圾回收的时候都是从Root开始搜索,这会先经过年轻代再到老年代,对于年轻代引用老年代的这种跨代不需要单独处理。但是老年代引用年轻代的会影响young gc,这种跨代需要处理。这里CMS和G1都用到了Card Table,一个Card Table将一个分区在逻辑上划分为固定大小的连续区域,每个区域称之为卡,卡通常较小,一个字节对应一个Card。当一个Card上的对象的引用发生变化的时候,就将这个Card对应的Card Table上的状态置为dirty,young gc的时候扫描状态是dirty的Card即可,CMS的老年代就会记录这样一个Card tbale。对于G1垃圾收集,又引入了Rset(Remembered Set),在老年代中有一块区域用来记录指向新生代的引用。 无论G1还是其他分代收集器,JVM都是使用Card table来避免全局扫描。

      我们知道G1垃圾收集器将内存分为了不同的Region区域,不再以严格的年轻代和老年代来区分内存并进行垃圾回收,如果需要扫描整个old区,势必会浪费很多的时间,且扫描了一些不必要的Region区域。 G1通过RSet,每个Region中都有一个RSet,记录的是其他Region中的对象引用本Region对象的关系,是一种point-in的关系即:谁引用了我的对象。因为G1分了很多Region,需要回收那个区域的时候,只需要判断要回收的区域是否有其他对象引用了该区域里的对象,即只需要找待回收区域的根对象即可,避免无效扫描。若存储point-out关系,将会扫描很多无关的Region区,造成时间性能的浪费。这里面还有另外一个集合:Collection Set,简称:CSet,CSet记录的是GC要收集的Region的集合,CSet里的Region可以是任意代的。在GC的时候,对于old->young和old->old的跨代对象引用,只要扫描对应的CSet中的RSet即可。如果Rset集合的引用对象较多,这里为了提高引用对象的查找和赋值处理问题,又通过卡表(Card Table)来实现查询和赋值,一个Card Table将一个分区在逻辑上划分为固定大小的连续区域,每个区域称之为卡。卡通常较小,介于128到512字节之间。RSet其实是一个Hash Table,Key是别的调用方Region的起始地址,Value是一个集合,里面的元素是Card Table的Index分区的地址。如下图9所示:

图4:回收跟对象的Rset和Cset

如上图所示,要回收年轻代的region A,只需要扫描C,D,F 区域的根对象即可,而不需要扫描整个old区。

分代G1模式下选择CSet有两种子模式,分别对应YoungGC和mixedGC:

  • YoungGC:CSet就是所有年轻代里面的Region;
  • MixedGC:CSet是所有年轻代里的Region加上在全局并发标记阶段标记出来的收益高的Region;

2、如何解决对象在GC过程中分配的问题呢?   
     初始快照算法:snapshot-at-the-beginning (SATB),SATB是维持并发GC的一种手段。G1并发的基础就是SATB。SATB可以理解成在GC开始之前对堆内存里的对象做一次快照,此时活的对象就认为是活的,从而形成一个对象图在GC收集的时候,新产的对象认为是活的对象除此之外其他不可达的对象都认为是垃圾对象。
   如何找到在GC的过程中分配的对象呢?每个region记录着两个top-at-mark-start(TAMS)指针,分别为prevTAMS和nextTAMS。在TAMS以上的对象就是新分配的,因而被视为隐式marked。通过这种方式我们就找到了在GC过程中新分配的对象,并把这些对象认为是活的对象。

3、在GC过程中引用发生变化的问题怎么解决呢?       

三色标记算法

在并发标记中,通过三色标记法来完成对对象是否存活以及追踪的记录。比如我们定义三种颜色并赋予以下的意义:

  • 黑色:根对象,或者该对象与它的子对象都被扫描
  • 灰色:对象本身被扫描,但还没扫描完该对象中的子对象
  • 白色:未被扫描对象,扫描完成所有对象之后,最终为白色的为不可达对象,即垃圾对象;
图5-三色标记方法

如果在GC运行中,对象的引用关系发生来如下的变化

图6 gc过程对象关系发生变化

 

如图11所示,gc运行过程中,C对象的引用关系发生来改变,D引用C显然按照三色标记法C为白色是要被清理的,显然不太合理。所以这里需要记录此种改变。

      在CMS采用的是增量更新(Incremental update),只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象 的字段里,那就把这个白对象变成灰色的,即插入的时候记录下来。

write_barrier(obj,field,newobj){
    if(newobj.mark == FALSE){
        newobj.mark = TRUE
        push(newobj,$mark_stack)
    }
    *field = newobj
}

      在G1中,通过Write Barrier就可以了解到哪些引用对象发生了什么样的变化,删除的时候记录所有的对象,它有3个步骤:
     (1) 在开始标记的时候生成一个快照图SATB标记存活对象;
     (2) 在并发标记的时候所有被改变的对象入队(在write barrier里把所有旧的引用所指向的对象都变成非白的);
     (3) 可能存在游离的垃圾,将在下次被收集; 

4、可预测的停顿
      G1记录跟踪了各个Region获取垃圾收集的价值大小,在后台维护一个优先列表;每次根据用户设置的允许的收集时间,优先回收价值最大的Region,可以有计划的避免全区的垃圾收集,这也是Garbage-First的由来,也是与CMS最大的区别;这就保证了在有限的时间内可以获取尽可能高的收集效率;

5、什么情况下会发生fullgc?

    导致CMS FullGC的原因有两个:
       1. Promotion Failure
       在年轻代晋升的时候老年代没有足够的连续空间容纳,很有可能是内存碎片导致的。
       2. Concurrent Mode Failure
        在并发过程中jvm觉得在并发过程结束前堆就会满了,需要提前触发Full GC。

    导致G1 Full GC的原因可能有两个,与CMS类似:
    1. Evacuation的时候没有足够的to-space来存放晋升的对象;
    2. 并发处理过程完成之前空间耗尽
       G1的初衷就是要避免Full GC的出现,Full GC会会对所有region做Evacuation-Compact,而且是单线程的STW,非常耗时间。

     其他:
    system.gc()调用;
    永久代空间不足,注意动态代理,反射,常量等用的比较多的服务;

6、Full-GC的影响?

  1. 服务体验:服务停止,严重影响用户的体验;
  2. 数据一致性:分布式服务中容易引起主备切换,出现脑裂;

注意点

(1)不断调优暂停时间指标

    通过XX:MaxGCPauseMillis=x可以设置启动应用程序暂停的时间,G1在运行的时候会根据这个参数选择CSet来满足响应时间的设置。一般情况下这个值设置到100ms或者200ms都是可以的(不同情况下会不一样),但如果设置成50ms就不太合理。暂停时间设置的太短,就会导致出现G1跟不上垃圾产生的速度,最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。

(2)不要设置新生代和老年代的大小

    G1收集器在运行的时候会调整新生代和老年代的大小。通过改变代的大小来调整对象晋升的速度以及晋升年龄,从而达到我们为收集器设置的暂停时间目标。设置了新生代大小相当于放弃了G1为我们做的自动调优我们需要做的只是设置整个堆内存的大小,剩下的交给G1自己去分配各个代的大小。

    G1的运行过程是这样的,会在Young GC和Mix GC之间不断的切换运行,同时定期的做全局并发标记,在实在赶不上回收速度的情况下使用Full GC(Serial GC)。初始标记是搭在YoungGC上执行的,在进行全局并发标记的时候不会做Mix GC,在做Mix GC的时候也不会启动初始标记阶段。当MixGC赶不上对象产生的速度的时候就退化成Full GC,这一点是需要重点调优的地方。

优点

G1主要用来取代CMS垃圾收集器,优点是:

1、简单:开发者控制调优变的简单;

2、并行与并发:充分利用cpu,减少STW的时间;

3、可预见性:可预测的停顿模型,G1可选取部分区域进行回收,可以缩小回收范围,控制减少全局停顿;
4、空间整理:回收时分区Region进行适当移动整理,避免了CMS的垃圾碎片;

5、划分模式:堆内存的划分Region;

6、大空间分配:超大堆的表现更出色;

缺点 会产生3次STW,但是时间较短;
使用场景 Java 9 的默认垃圾收集器,该收集器和之前的收集器大不相同,该收集器可以工作在young 区,也可以工作在 old 区。
参数使用
  1. -XX:+UseG1GC 开启 G1 收集器。

  2. -XX:MaxGCPauseMillis 用于指定最大停顿时间,如果任何一次停顿超过这个设置值时,G1 就会尝试调整新生代和老年代的比例,调整堆大小,调整晋升年龄的手段,试图达到目标。和 PS 一样,停顿时间小了,对应的吞吐量也会变小。这点值得注意。

  3. -XX:ParallelGCThreads 由于是并行并发的,可以指定GC 工作线程数量。

  4. -XX:InitiatingHeapOccupancyPercent 该参数可以指定当整个堆使用率达到多少时,触发并发标记周期的执行。默认值时45,即当堆的使用率达到45%,执行并发标记周期,该值一旦设置,始终都不会被 G1修改。也就是说,G1 就算为了满足 MaxGCPauseMillis 也不会修改此值。如果该值设置的很大,导致并发周期迟迟得不到启动,那么引起 FGC 的几率将会变大。如果过小,则会频繁标记,GC 线程抢占应用程序CPU 资源,性能将会下降。

  5. -XX:GCPauseIntervalMillis 设置停顿时间间隔。

CMS与G1的区别:

(1) 分代收集
    CMS收集器是老年代的收集器,gc的时候会回收整个Old区,可以配合新生代的Serial和ParNew收集器一起使用;
    G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用,对G1来说没有old gc的概念,而是区分Fully young gc和Mixed gc,前者对应年轻代的垃圾回收,后者混合了年轻代和部分老年代的收集,因此每次收集肯定会回收年轻代,老年代根据内存情况可以不回收或者回收部分或者全部。 G1的分代更多是逻辑上的概念,G1将内存分成多个等大小的region,Eden/ Survivor/Old分别是一部分region的逻辑集合,物理上内存地址并不连续。
(2)  设计目标
    CMS收集器以最小的停顿时间为目标的收集器,提高系统响应能力;
    G1收集器可预测垃圾回收的停顿时间,尽量避免出现GC;
(3) 内存空间
   CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片
   G1收集器全局看使用“标记清理”,局部的Region使用的是“标记-整理”算法,进行了空间整合,大幅度降低了内存空间碎片。
(4) 垃圾回收过程区别

    重新标记过程 和 回收方式(可预测回收模型)的不同。

总结

    参数的设定及垃圾回收器的选择一定要根据具体的服务及场景来判断选择,没有完美的唯一解决方案。比如C端服务器交互密集型,需要保证吞吐量,我们可以选择G1 或者 “吞吐量优先”的 Parallel Scavenge + Parallel Old,还有PreNew + CMS的组合也是系统常用的,兼顾了吞吐量和停顿时间的性能考虑,或者是:Parallel Scavenge + old serial ,对于一般请求量不大,不要求实时性的单核cpu系统也可以采用  Serial + Serial old 即可满足需求,效率也很高。

备注:常用参数

JVM常用配置参数

配置参数 功能
-Xms 初始堆大小。如:-Xms4g
-Xmx 最大堆大小。如:-Xmx4g
-Xmn 新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%
-Xss JDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的。
-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3
-XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
-XX:PermSize 永久代(方法区)的初始大小
-XX:MaxPermSize 永久代(方法区)的最大值

GC日志打印参数参考

gc日志打印参数
  1. -XX:+PrintGCDateStamps 打印 GC 日志时间戳。

  2. -XX:+PrintGCDetails 打印 GC 详情。

  3. -XX:+PrintGCTimeStamps: 打印此次垃圾回收距离jvm开始运行的所耗时间。

  4. -Xloggc: 将垃圾回收信息输出到指定文件

  5. -verbose:gc 打印 GC 日志

  6. -XX:+PrintGCApplicationStopedTime 查看 gc 造成的应用暂停时间

  7. XX:+PrintTenuringDistribution, 对象晋升的日志

  8. -XX:+HeapDumpOnOutOfMemoryError 内存溢出时输出 dump 文件。


参考资料:
《深入了解jvm虚拟机》
https://blog.csdn.net/qq_31156277/article/details/79962445
https://www.cnblogs.com/yang-hao/p/5936059.html
https://www.cnblogs.com/ASPNET2008/p/6496481.html
https://www.cnblogs.com/yunxitalk/p/8987318.html
https://blog.csdn.net/qq_31156277/article/details/79951819
https://blog.csdn.net/hutongling/article/details/69908443

 

展开阅读全文

没有更多推荐了,返回首页