资讯专栏INFORMATION COLUMN

必知必会JVM垃圾回收——对象搜索算法与回收算法

LuDongWei / 2994人阅读

垃圾回收(GC)是JVM的一大杀器,它使程序员可以更高效地专注于程序的开发设计,而不用过多地考虑对象的创建销毁等操作。但是这并不是说程序员不需要了解GC。GC只是Java编程中一项自动化工具,任何一个工具都有它适用的范围,当超出它的范围的时候,可能它将不是那么自动,而是需要人工去了解与适应地适用。

拥有一定工作年限的程序员,在工作期间肯定会经常碰到像内存溢出、内存泄露、高并发的场景。这时候在应对这些问题或场景时,如果对GC不了解,很可能会成为个人的发展瓶颈。

接下来的两文将详细学习下JVM中垃圾回收(GC)的各个知识要点。本文先从GC的算法开始先了解,铺垫好基础,下一篇再详细讲JVM具体的GC实现。

GC对象搜索算法

垃圾回收,第一件事就是要搞清楚哪些东西是垃圾,而后才能对这些垃圾进行回收。

那么有什么办法识别对象是否为无用的垃圾呢?狭义地,怎么判断对象是否没被引用呢?

通常有以下两种算法去识别判断

引用计数算法

这个算法非常简单。给对象一个计数器,每当这个对象被引用了,计数器值加一;引用失效,则减一。但这个对象计数值为0的时候,证明是无用对象,可以被GC程序回收掉。这种算法比较广泛应用在一些脚本语言上,如FLASH、PYTHON等。
但是引用计数算法无法解决对象间相互引用的问题。当a对象引用了b对象,b对象也引用了a对象,这样a、b两个对象的计数器值都不会为0,即使这两个对象都被其他对象所引用,最终导致这些对象一直无法被回收。这种情况往往会出现在比较复杂的编程语言中。

可达性分析算法

可达性分析算法(GC roots算法),广泛应用于主流的商用语言。设置一个根节点,从图论角度来看,只要从该节点可达一个对象,证明这个对象是存活的(被引用)。

通常地,GC会包含以下区域的对象:

虚拟机栈(栈帧中的本地变量表)中引用的对象;

方法区中类静态属性引用的对象;

方法区中常量引用的对象;

本地方法栈中JNI(即一般说的Native方法)引用的对象;

垃圾回收算法

了解完垃圾是怎么找出来后,接下来看看它们是怎么被清除的。以下介绍几种清除的算法。

标记-清除算法(Mark-Sweep)

标记-清除,顾名思义,先标记垃圾,再清除。它是GC最基础的算法,后续很多算法都是基于它上面去改进的。
标记的过程在上面搜索GC对象已经介绍过了。被标记的对象,在统一GC的时候会把标记的对象清除掉。这个算法比较简单,不做过多赘述。


这个算法有一个很明显的缺点,就是在垃圾回收后会产生大量不连续的碎片空间,导致程序要申请较大的对象时常无法找到合适的内存空间,迫使再次GC。

复制算法

复制算法的存在,正是为了解决内存碎片问题。并且这个算法也是分代算法的基础。

将内存分为大小相等的两块,每次程序只使用其中一块,当GC发生的时候,把存活的对象复制到另外一块内存中,整齐的排列,然后清空原来的那块内存。

可以看到,这种算法有点新生代转移到老年代的感觉。

缺点:

把内存可使用的空间减少了一半,造成空间的浪费。

对象存活数量较多的时候,复制性能比较差

这种缺点,在老年代中,对象存活率比较高的场景下是非常场景间。

标记-整理算法(Mark-Compact)

针对复制算法的两个缺点,在老年代一般会用这种标记-整理算法。

把存活的对象移到内存的一段,然后把剩余的空间全部清空掉。

分代收集算法

分代算法并不是一个特定的算法,也没有什么新的内容。而是把内存分成多个区域,一般为新生代、老年代等。然后根据不同区域不同的特点,用不同回收算法去回收垃圾。

例如新生代,对象存活率低,比较适用复制算法。老年代存活率高,比较适用Mark-Compact算法。

目前几乎所有的商业虚拟机都是采用分代收集的。具体不同的收集器在下一文再详细说明。

更多技术文章、精彩干货,请关注
博客:zackku.com
微信公众号:Zack说码

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77297.html

相关文章

  • 程序语言

    摘要:一面应该还问了其他内容,但是两次面试多线程面试问题和答案采访中,我们通常会遇到两个主题采集问题和多线程面试问题。多线程是关于并发和线程的。我们正在共享重要的多线程面试问题和答案。。 2016 年末,腾讯,百度,华为,搜狗和滴滴面试题汇总 2016 年未,腾讯,百度,华为,搜狗和滴滴面试题汇总 【码农每日一题】Java 内部类(Part 2)相关面试题 关注一下嘛,又不让你背锅!问:Ja...

    mtunique 评论0 收藏0
  • 程序语言

    摘要:一面应该还问了其他内容,但是两次面试多线程面试问题和答案采访中,我们通常会遇到两个主题采集问题和多线程面试问题。多线程是关于并发和线程的。我们正在共享重要的多线程面试问题和答案。。 2016 年末,腾讯,百度,华为,搜狗和滴滴面试题汇总 2016 年未,腾讯,百度,华为,搜狗和滴滴面试题汇总 【码农每日一题】Java 内部类(Part 2)相关面试题 关注一下嘛,又不让你背锅!问:Ja...

    stefan 评论0 收藏0
  • Java必知必会之socket

    摘要:上,数据按有限大小的包传输,这些包成为数据报,每个数据报包含一个首部和一个有效载荷。不过,由于数据报长度有限,通常必须将数据分解为多个包,再在目的地重新组合。这两个构造函数,在返回之前会与远程主机建立一个活动的网络连接。 Internet上,数据按有限大小的包传输,这些包成为数据报(datagram),每个数据报包含一个首部(header)和一个有效载荷(payload)。首部包含包发...

    jackzou 评论0 收藏0
  • 2017文章总结

    摘要:欢迎来我的个人站点性能优化其他优化浏览器关键渲染路径开启性能优化之旅高性能滚动及页面渲染优化理论写法对压缩率的影响唯快不破应用的个优化步骤进阶鹅厂大神用直出实现网页瞬开缓存网页性能管理详解写给后端程序员的缓存原理介绍年底补课缓存机制优化动 欢迎来我的个人站点 性能优化 其他 优化浏览器关键渲染路径 - 开启性能优化之旅 高性能滚动 scroll 及页面渲染优化 理论 | HTML写法...

    dailybird 评论0 收藏0

发表评论

0条评论

LuDongWei

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<