面试——Java垃圾回收算法和垃圾回收器

Java垃圾回收算法:
Java垃圾回收算法是Java虚拟机的关键组成部分,它负责自动管理内存并回收不再使用的对象。
标记-清除算法:
标记-清除算法分为两个主要阶段。首先,它会遍历整个堆,标记所有被活动对象引用的对象,然后,在标记阶段之后,它会清除所有未标记的对象,释放它们所占用的内存空间。这个算法相对比较简单,缺点就是会产生内存碎片。
复制算法:
复制算法将堆内存分为两个区域,通常是”From“区和”To“区,当”From“区的对象被标记为存活时,它们将被复制到”To“区,而未被标记的对象将被丢弃,完成复制后,”From“区和”To“区的角色交换。这种算法的优点是简单高效,但它浪费了一半的内存空间。
标记-整理算法:
标记-整理算法在标记阶段与标记-清除算法类似,但在清除阶段,它会将所有存活对象向一端移动,然后清理边界之外的内存。这种方式可以解决标记-清楚算法的内存碎片问题,并且仍然能够高效地回收内存。
分代算法:
分代算法是基于对象的生命周期的概念。它将内存分为几个不同的时代,通常是年轻代和老年代。大部分新创建的对象会被分配到年轻代,而老年代主要用于存放生命周期比较长的对象。这个算法根据代打特性使用不同的垃圾回收算法,如复制算法用于年轻代,标记-整理算法用于老年代。这种分代的方式可以根据对象的不同特点来优化垃圾回收过程。

Java垃圾回收器:

1.Serial垃圾回收器(单线程、复制算法)
Serial垃圾收集器是最基本、发展时间最长的垃圾收集器。他不但只会用一个线程去收集垃圾,在收集垃圾的时候其他的所有工作线程必须停止,即会发生Stop the World现象,对于Stop the world(在垃圾回收开始时停掉其他所有的线程,只供垃圾回收器回收使用,对于系统尤其是高并发系统来说就是一个噩梦),直到垃圾回收结束。
优点:简单高效,对于限定单个CPU的环境来说,Serial垃圾收集器没有线程交互(交换)开销,可以获得最高的单线程手机效率
缺点:会发生SWT现象

2.ParNew垃圾回收器(Serial+多线程)
ParNew是Serial收集器的多线程版本,也使用复制算法,除了使用多线程对垃圾进行收集之外,他和Serial几乎没有什么区别也会发生Stop The World现象。多用于Server模式下。也可以与下文的CMS收集器配合使用

3.Parallel Scavange 收集器(多线程复制算法)
ParallelScavange垃圾回收器是一个新生代的垃圾回收器,同样使用复制算法,也是一个多线程的垃圾回收器,他重点关注的是程序的吞吐量问题;

吞吐量 = CPU运行用户的代码时间 / CPU总的消耗时间 = 运行用户代码时间 / (运行用户代码时间+垃圾回收时间)

它的调优方式有:

—XX:MaxGCPauseMillis
控制最大垃圾回收时间,大于0ms;
—XX:GCTimeRatio
设置垃圾回收时间占总时间的比率,0<n<100的整数;
—XX:+UseAdptiveSizePolicy
不用手动指定一些细节的调整(-Xmn 、-XX:SurvivorRation、-XX:PetenureSizeThreshold),
JVM会根据当前系统的运行情况收集监测性能,自动调节参数

4.Serial Old垃圾回收器(单线程标记整理算法)
Serial Old是Serial的老年代收集版本,他同样是个单线程收集器,使用标记-整理算法,这个垃圾收集器主要运行在客户端的JVM中默认的老年代垃圾回收器。当然也会发生STW(Stop The World)现象
主要应用场景有:

  • 用于Client模式
  • 用于Server模式时
    1.在JDK1.5之前,与ParallelScavenge收集器搭配使用,
    2.作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用;

5.Parallel Old收集器(多线程标记整理算法)
在JDK1.5之前新生代使用ParallelScavenge只能与Serial Old搭配使用,只能保证新生代的吞吐量,无法保证老年代的吞吐量。从JDK1.6开始,ParallelOld成为Parallel Scavenge 的老年代收集器版本;
在注重吞吐量的前提下,使用Parallel Scanvenge + Parallel Old作为组合;在多核CPU且对吞吐量及其敏感的Server系统中推荐使用;

6.CMS收集器(多线程标记清除收集器)
Concurrent Mark Sweep (CMS)垃圾收集器时针对老年代的一个并发线程的垃圾收集器,其目的是获取最短垃圾回收停顿时间,它采用的是多线程的标记—清除,但是它需要更多的内存来完成这个动作;
多应用于:

  • 与用户交互较多的场景
  • 希望系统的停顿时间最短,注重服务的响应速度
  • 给用户带来较好的体验
  • 常见的WEB、B/S系统的服务器应用上

CMS的运行过程
1.初始标记
只是标记一下GC Roots能直接关联的对象,速度很快但仍然需要暂停所有的工作线程;
目前主流的JVM都是准确式GC,可以直接得知哪些内存存放着对象引用,所以系统执行GC Roots停顿时,并不需要全部、逐个查找全局性和执行上下文的引用位置;
在HotSpot中,是是用一组称为OopMap 的数据结构来达到这个目的的:

  • 在类加载时计算对象内什么偏移量上是哪个数据
  • 在JIT编译的时候,也会记录栈和寄存器中哪些位置是引用

这样在GC扫描的时候就可以直接得到信息

2.并发标记
进行GC Roots跟踪的过程,从刚才产生的集合中标记存活的对象,并发执行不需要暂停工作线程;
但是并不能保证标记出所有的存活对象;

3.重新标记
为了修正并发标记期间因为用户程序继续运行而导致标记变动的那一部分对象的标记记录;需要“Stop The World”且停顿时间比初始标记时间长但远比并发标记的时间短;

4.并发清除
回收所有的垃圾对象;
清除GC Roots不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并发标记和并发清除阶段垃圾收集线程是和用户线程并行工作的,所以总体来看CMS的内存回收和用户线程是一起并发执行的

CMS收集器显著的三个缺点:

  1. 对CPU资源敏感:并发收集虽然不会暂停用户线程,但是因为占用了一部分的CPU资源,所以造成系统变慢,吞吐量降低,
    解决方法:增量式并发收集器,类似于抢占式来模拟多任务机制的思想,让收集线程和用户线程交替运行,减少收集线程的运行时间
  2. 无法处理浮动垃圾,可能出现Concurrent Mode Failure失败
    (1)在并发清除时,用户线程产生新的垃圾叫做浮动垃圾,这使得在并发清除之前需要预留一定的内存空间,不能像其他收集器一样等到老年代快要填满的时候在进行收集
    (2)如果CMS预留空间无法满足程序要求,就会出现一次Concurrent ModeFailure失败;这使得CMS启动临时预案:使用Serial Old来处理老年代垃圾,这将会导致另一次的Full GC
  3. 产生大量的内存碎片:由于CMS采用的是标记-清除算法,所以在垃圾回收之后不能进行压缩操作,造成内存碎片问题;若在内存碎片不足以值称创建一个新的的大型对象的时候,会触发Full GC对新生代+老年代进行垃圾回收
    解决方法:
    (1)-XX:+UseCMSCompactAtFullCollection使得CMS出现问题时不进行Full GC而是开启内存碎片的整合过程
    (2)-XX:+CMSFullGCsBeforeCompaction 设置n次的不压缩碎片的Full GC之后来一次压缩整理

7.G1收集器
G1 (Garbage-First)垃圾收集器,是在JDK1.7之后才出的一款商用的垃圾回收器;

G1的收集步骤:

  1. 初始标记(Initial Marking):仅标记一下GC Roots能关联的对象,且修改TAMS(Next Top At Mark
    Start)让下一个阶段并行运行时用于程序能在可用的region中创建对象 ,需要Stop The World 但是速度很快
  2. 并发标记(Concurrent Marking):在进行GC Roots 遍历的时候,标记出刚才存活的对象
  3. 最终标记(Final Marking) :为了修改在并发标记期间因为用户的并行运行而导致标记变动的那一部分的记录,需要Stop The World且停顿的时间比初始标记稍长,但是比并发标记短
  4. 筛选回收(Live Data Counting and Evacuation):采取复制算法,从一个或多个region复制存活对象到堆的另一个region,并且在此过程中压缩和释放内存,可采用并发进行,降低停顿时间,并增加吞吐量

它的特点有以下几种:

特点1:并行与并发
G1收集器能充分利用CPU、多核环境下的硬件优势,使用多个CPU核心来缩短Stop The World的停顿时间。部分其他的垃圾回收器需要在GC的时候使工作线程停下来,而G1和CMS一样都可以通过并发回收的方式让收集线程和工作线程一起并行执行;

特点2:分代收集,收集范围包括新生代和老年代
虽然G1不需要与其他的垃圾回收器配合,自己可以管理整个堆的GC,但是他还是保留了分区的概念。他能够采用不同的方式去处理新生的对象和存活时间很长的对象;

特点3:内存布局
G1将内存分为若干个等大小的区域(region),Eden/Survivor/Old分别是region的逻辑集合,物理上存在并不一定连续;

特点4:实现多种垃圾收集算法
从整体上看,是基于标记-整理算法;
从局部看,是基于复制算法;
他们都不会产生内存碎片,有效的利用了系统资源;

特点5:可预测的GC停顿
G1除了追求低停顿外,还能建立可预测的停顿时间模型;其可以明确的指定M毫秒时间片内,垃圾消耗时间不超过N毫秒;

为什么G1可以实现预测停顿时间模型:

  • 可以有计划的避免在Java堆中进行全区域的垃圾回收;
  • G1根据各个region获取其收集价值的大小,在后台维护一个优先列表;
  • 每次根据允许的收集时间,优先回收价值最大的region(名称Garbage -First的由来)
  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值