聊聊Java的垃圾回收机制


前言

垃圾回收机制是JVM中非常重要的知识点,也是面试的高频问题。这篇文章就来简单的探讨一下有关JAVA中的垃圾回收的问题,包括堆的分区、垃圾回收算法等。


一、堆的分区

前面提到了堆分了新生代和老年代,新生代又分为eden和survivor区,survivor区又分为from和to区。
在这里插入图片描述
垃圾回收主要在堆中进行,介绍完堆的分区之后,就可以开始进入今天的主题了。
以往我们编写程序时候,经常会创建很多对象,但我们从未对这些对象进行回收,那么是谁帮我们完成了对象的回收呢?
答案:JVM帮我们做了(自动回收垃圾)
垃圾是什么:只要对象不再被使用了,那我们就可以认为该对象就是垃圾,对象所占用的空间就可以被回收。

判断对象是否为垃圾有两个常见的算法:引用计数法和可达性分析法(之前的文章已经介绍,本文不再叙述)

JVM用的就是可达性分析算法来判断对象是否是垃圾,它从GC Roots开始向下搜索,当对象到GC Roots都没有任何引用相连时,说明对象是不可用的,可以被回收。

哪些可以作为GC Roots?
Java线程当前活跃的栈帧里指向GC堆里的对象的引用,GC Root 需要确保引用所指的对象都是活着的,而当前线程栈帧中的对象,在这一时刻是存活的。


二、垃圾回收算法

垃圾回收的第一步就是标记,标记哪些没有被「GC Roots」引用的对象
在这里插入图片描述

2.1标记清除算法和标记复制算法

标记清除算法:最简单残暴的算法,直接将垃圾干掉。但存在内存碎片的问题。
内存碎片:可能有10M的空余内存,但程序申请9M内存空间却申请不下来(10M的内存空间是垃圾清除后的,不连续的)。
在这里插入图片描述
那么有什么算法可以解决内存碎片问题呢?
标记复制算法:把存活的对象复制到另一块空间,复制完了之后,直接把原有的整块空间给干掉,这样就没有内存碎片的问题。但这又会有很多缺点:内存利用率低,得有一块新的区域给复制(移动)过去。

2.2标记整理算法

标记整理算法:把存活的对象移到一边,把垃圾移到一边,那再将垃圾一起删除掉。
在这里插入图片描述
下面用一张表来总结一下三种回收算法的特点:
在这里插入图片描述


三、为什么要分代

由于大部分对象的生命周期都很短,而只有少部分对象可能会存活很长时间。
年轻代特点:区域相对老年代较小,对象生命周期短、存活率低,回收频繁,适合标记复制算法。

老年代特点:区域较大,对象生命周期长、存活率高,回收不及年轻代频繁。这种情况存在大量存活率高的对象,复制算法明显变得不合适。一般是由标记- 清除或者是标记-清除与标记-整理的混合实现。

stop the world(应用停止访问):回收垃圾的时候,程序是有短暂的时间不能正常继续运作。
又由于垃圾回收是会导致stop the world,所以分代的一个原因是为了使stop the world持续的时间尽可能短。

总结:不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点使用不同的回收算法, 以提高垃圾回收的效率,同时使stop the world持续的时间尽可能短。


总结

本文主要介绍了几种常见的垃圾回收算法,每种算法各有利弊,不存在谁比谁好的说法。介绍了垃圾回收为什么要进行分代,一是为了提高垃圾回收的效率,二是尽可能的使STW的时间尽可能的短。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JinziH Never Give Up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值