你真的了解GC吗?
发布日期:2021-05-14 09:35:54 浏览次数:24 分类:精选文章

本文共 1196 字,大约阅读时间需要 3 分钟。

GC是什么?

垃圾回收(GC)在计算机科学中是一种自动化的内存管理机制。当某个程序占用的一部分内存空间不再被程序访问时,垃圾回收器会将这些内存空间归还给操作系统。这种机制能够减轻程序员的负担,并预防因内存泄漏导致的错误。

GC的运行机制

垃圾回收需要知道哪些对象可以回收才能进行内存管理。判断对象内存是否能回收主要有以下两种方式:

  • 引用计数法

    这种方法通过维护一个计数器来判断对象的引用次数。当计数器值为0时,该对象的内存可以回收。虽然引用计数法简单,但它无法处理循环依赖的情况(如上文所示的A、B、C对象引用循环)。

  • 可达性分析算法

    JVM中使用可达性分析算法。
    首先确认GC Root对象(如所存活的线程、方法区的静态对象、虚拟机栈中的局部变量表中的对象等)。然后通过分析这些根对象所引用的对象 chains,逐层分析这些对象是否被根对象所引用,最终确定哪些对象是可回收的。
    虽然这个算法理论上是正确的,但在实际应用中,可能会因为被根对象间接引用而导致一些对象无法被回收,导致内存泄漏。因此,正确地理解哪些对象可以当作GC Root是非常重要的。

  • GC回收内存

    内存回收的具体方式主要有以下几种算法:

  • 标记清除算法

    标记清除是最简单粗暴的算法,只需标记会被回收的内存区域,然后直接清除即可。优点是速度快,但缺点是内存碎片化严重,影响后续内存分配。

  • 复制算法

    将内存空间分为两部分,只用其中一半进行存放。每次垃圾回收时,将活跃对象拷贝到另一半内存空间,原有的内存空间直接清除。虽然效率较高,但会浪费大量内存空间(将可用空间减半)。

  • 标记压缩算法

    在标记完对象后,将存活的对象压缩到内存的一端,剩下的内存空间直接清除。这种方式可以显著减少内存碎片,但是需要频繁移动对象内存,性能消耗较大。

  • 分代算法

    分代算法将内存分为新生代和老年代。新生代内存分为三个区段:Eden、Survivor0和Survivor1。在第一次Monitor GC(内存回收)时,Eden区存活的对象会被复制到Survivor0,并清理Eden区。第二次和第三次 Monitor GC 时,Eden和Survivor0的对象会被复制到Survivor1或Survivor0中。
    超过一定次数的Monitor GC后(通常为15次),如果新生代内存还无法满足需求,则会将存活的对象复制到老年代中。老年代使用标记压缩算法回收内存。老年代内存到达阈值时则触发Full GC。

  • 此外,老年代中存在引用到新生代对象的情况也会导致内存回收困难,因此分代算法使用了card table记录老年代中的引用情况,以确保有针对性地进行内存清理。

    特殊情况

    老年代中的对象有时候可能直接或间接引用新生代的对象。为了避免这种情况造成的内存泄漏,需要避免在这些情况下创建无法被回收的对象引用。

    你的技术咨询小号:

    关注更多技术文章,获取实用技能!

    上一篇:惊了,还有这种方式手写ButterKnife
    下一篇:来,带你手写个性能检测工具

    发表评论

    最新留言

    路过,博主的博客真漂亮。。
    [***.116.15.85]2025年04月15日 04时14分01秒