JVM使用GC分代收集的原由

JVM采用GC分代收集策略主要是为了优化性能,通过吞吐量和停顿时间来衡量GC效率。调整-XX:MaxGCPauseMillis和-XX:GCTimeRatio参数可以平衡这两者。大多数对象的短生命周期导致了分代思想的产生,年轻代和老年代的划分使得大部分对象在年轻代就被回收,减少GC时间。年轻代进一步细分为Eden和两个Survivor区,经过多次GC后存活的对象进入老年代,防止内存碎片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、首先看两个衡量GC性能的指标

1、吞吐量

该指标表示程序占用CPU执行的时间(包含分配内存的时间,不包括GC时间)占总时间的百分比。

2、停顿时间

该指标表示程序不响应的时间(正在进行垃圾回收)。

吞吐量越大而停顿时间越小,表示GC性能越好。对于不同的应用有不同的需求,例如对于很多web应用来说,停顿时间太长会使用户明显感觉到卡顿,很影响用户体验。

二、于是,通常通过调整以下参数来获得需要的程序性能

1、指定最大停顿时间,表示能容忍的GC时停止应用的持续时长(单位:ms)。
-XX:MaxGCPauseMillis=xxx

2、指定GC比率,表示能够接受的GC时间占总时间的比例
-XX:GCTimeRatio=xx
例如-XX:GCTimeRatio=19,GC占用时间为1/(1+19)=1/20即5%,表示GC占用执行时间的比例为5%

因而,垃圾收集器通常都要考虑到这些因素以满足不同的应用场景。

三、分代垃圾收集

考虑一个细致的问题:一个对象Object什么时候会被认为是垃圾?
在通过任何一个指针都无法访问到的情况下,即不可达。

垃圾回收最直接的方式便是迭代遍历每个可达对象,最后剩下的便是垃圾对象。然而,对于大的应用来讲这么做是可怕的,因为这么做的GC时间与对象数量近似成正比,庞大应用有太多的存活数据,会导致GC的时间相当长。

这也是大多数垃圾收集器都采用分代回收策略的原因,这是应用经验论建立的一种弱代假设。弱代假设表明:大多数对象的存活时间都是很短的。

基于这种经验性的观察,JVM将垃圾回收分为两个部分,年轻代和老年代,进行分代回收。大量的对象在年轻代死亡,能够被快速回收,其它存活到一定age的对象则进入老年代。年轻代和老年代收集相互独立。

在这里插入图片描述

默认java heap内存分代划分图(除并行及G1收集器之外)

绝大多数对象都在Eden区域分配。两个Survivor,任意时刻总有一个是空的,作为Eden空间存活对象转移的目的地。另一个作为下一次拷贝使用,minor GC之后还存活的对象被转移到另一个Survivor区,两个Survivor区的存活对象这样来回拷贝,直到他们存活“年龄”足够大而被拷贝到老年代。

其实年轻代Yong这样划分也是基于一定考虑,为方便垃圾回收时进行整理,也就是说在清理完垃圾对象之后将存活对象进行整理,这样就不会出现大量的内存碎片。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值