垃圾检测、回收算法

垃圾收集器一般必须完成两件事:检测出垃圾;回收垃圾。怎么检测出垃圾?一般有以下几种方法:

引用计数法:给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1。

好了,问题来了,如果我有两个对象A和B,互相引用,除此之外,没有其他任何对象引用它们,实际上这两个对象已经无法访问,即是我们说的垃圾对象。但是互相引用,计数不为0,导致无法回收,所以还有另一种方法:

可达性分析算法:以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象。这里的根集一般包括java栈中引用的对象、方法区常良池中引用的对象

本地方法中引用的对象等。

总之,JVM在做垃圾回收的时候,会检查堆中的所有对象是否会被这些根集对象引用,不能够被引用的对象就会被垃圾收集器回收。一般回收算法也有如下几种:

1.标记-清除(Mark-sweep)

算法和名字一样,分为两个阶段:标记和清除。标记所有需要回收的对象,然后统一回收。这是最基础的算法,后续的收集算法都是基于这个算法扩展的。

不足:效率低;标记清除之后会产生大量碎片。效果图如下:

2.复制(Copying)

此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。效果图如下:

3.标记-整理(Mark-Compact)

此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。效果图如下:

(1,2,3 图文摘自 http://pengjiaheng.iteye.com/blog/520228,感谢原作者。)

4.分代收集算法

这是当前商业虚拟机常用的垃圾收集算法。分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

为什么要运用分代垃圾回收策略?在java程序运行的过程中,会产生大量的对象,因每个对象所能承担的职责不同所具有的功能不同所以也有着不一样的生命周期,有的对象生命周期较长,比如Http请求中的Session对象,线程,Socket连接等;有的对象生命周期较短,比如String对象,由于其不变类的特性,有的在使用一次后即可回收。试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,那么消耗的时间相对会很长,而且对于存活时间较长的对象进行的扫描工作等都是徒劳。因此就需要引入分治的思想,所谓分治的思想就是因地制宜,将对象进行代的划分,把不同生命周期的对象放在不同的代上使用不同的垃圾回收方式。

如何划分?将对象按其生命周期的不同划分成:年轻代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)。其中持久代主要存放的是类信息,所以与java对象的回收关系不大,与回收息息相关的是年轻代和年老代。这里有个比喻很形象

“假设你是一个普通的 Java 对象,你出生在 Eden 区,在 Eden 区有许多和你差不多的小兄弟、小姐妹,可以把 Eden 区当成幼儿园,在这个幼儿园里大家玩了很长时间。Eden 区不能无休止地放你们在里面,所以当年纪稍大,你就要被送到学校去上学,这里假设从小学到高中都称为 Survivor 区。开始的时候你在 Survivor 区里面划分出来的的“From”区,读到高年级了,就进了 Survivor 区的“To”区,中间由于学习成绩不稳定,还经常来回折腾。直到你 18 岁的时候,高中毕业了,该去社会上闯闯了。于是你就去了年老代,年老代里面人也很多。在年老代里,你生活了 20 年 (每次 GC 加一岁),最后寿终正寝,被 GC 回收。有一点没有提,你在年老代遇到了一个同学,他的名字叫爱德华 (慕光之城里的帅哥吸血鬼),他以及他的家族永远不会死,那么他们就生活在永生代。”

具体区域可以通过VisualVM中的VisaulGC插件查看,如图(openjdk 1.7):

年轻代:是所有新对象产生的地方。年轻代被分为3个部分——Enden区和两个Survivor区(From和to)当Eden区被对象填满时,就会执行Minor GC。并把所有存活下来的对象转移到其中一个survivor区(假设为from区)。Minor GC同样会检查存活下来的对象,并把它们转移到另一个survivor区(假设为to区)。这样在一段时间内,总会有一个空的survivor区。经过多次GC周期后,仍然存活下来的对象会被转移到年老代内存空间。通常这是在年轻代有资格提升到年老代前通过设定年龄阈值来完成的。需要注意,Survivor的两个区是对称的,没先后关系,from和to是相对的。

年老代:在年轻代中经历了N次回收后仍然没有被清除的对象,就会被放到年老代中,可以说他们都是久经沙场而不亡的一代,都是生命周期较长的对象。对于年老代和永久代,就不能再采用像年轻代中那样搬移腾挪的回收算法,因为那些对于这些回收战场上的老兵来说是小儿科。通常会在老年代内存被占满时将会触发Full GC,回收整个堆内存。

持久代:用于存放静态文件,比如java类、方法等。持久代对垃圾回收没有显著的影响。

分代回收的效果图如下:

我这里之所以最后讲分代,是因为分代里涉及了前面几种算法。年轻代:涉及了复制算法;年老代:涉及了“标记-整理(Mark-Sweep)”的算法。

无招胜有招之Java进阶JVM(五)垃圾回收相关推荐

  1. 浅谈Java虚拟机JVM的垃圾回收机制

    1. 什么是垃圾 要回收垃圾,那么垃圾是什么?简单的逻辑就是不会再被使用的内存对象呗. 2. 怎么判断不再被使用 2.1 引用计数法.统计有多少个引用指向内存对象,如果没有引用指向内存对象,那么该内存 ...

  2. 【数据湖存储】数据湖的终极奥秘,无招胜有招

    作为海量数据存储与分析的重要承载方式的数据湖,从2011年概念诞生至今,已经发展了9个年头.而数据湖是什么?又能为数字化经济带来什么?<阿里云数据湖存储解决方案蓝皮书>将为您揭开数据湖的终 ...

  3. 无招胜有招——面向对象设计模式随笔,

    最近在学习面向对象设计模式,GOF的23种设计模式大概看了一遍,简单总结一下,设计模式主要分为三种模式,分别是创建模式,结构模式,行为模式. 回过头想一下具体有哪些模式,在什么情况下用什么设计模式,好 ...

  4. "无招胜有招"nbsp;史上最全的互…

    课前秀:三个段子 第一个段子:一个毫无餐饮行业经验的人开了一家餐馆,仅两个月时间,就实现了所在商场餐厅坪效第一名;VC投资6000万,估值4亿元人民币,这家餐厅是雕爷牛腩. 只有12道菜,花了500万 ...

  5. Dirty Approach之无招胜有招

    每个网站,几乎都有"新闻"的模块.在中国独有的ICP--Internet Copy and Past--模式下,多数站点也靠"转贴"手段汇集新闻信息.如果说新浪 ...

  6. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    本文介绍了Java中的四种I/O模型,同步阻塞,同步非阻塞,多路复用,异步阻塞.同时将NIO和BIO进行了对比,并详细分析了基于NIO的Reactor模式,包括经典单线程模型以及多线程模式和多Reac ...

  7. java 中间件_从头到尾说一遍Java(中间件)垃圾回收

    之前上学的时候有这个一个梗,说在食堂里吃饭,吃完把餐盘端走清理的,是 C++ 程序员,吃完直接就走的,是 Java 程序员. 确实,在 Java 的世界里,似乎我们不用对垃圾回收那么的专注,很多初学者 ...

  8. 《深入理解Java虚拟机》阅读——垃圾回收机制

    <深入理解Java虚拟机>阅读--垃圾回收机制 前言 why--为什么需要垃圾回收 what--垃圾回收做些什么 where--去哪里回收垃圾 how--垃圾回收是怎么做的 垃圾是否要回收 ...

  9. Java虚拟机(三)——初识JVM的垃圾回收机制

    前言 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随线程而生,随线程而灭.并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回 ...

  10. Java内存管理与垃圾回收

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 整个教程中已经不时的出现一些内存管理和垃圾回收的相关知识.这里进行一个小小的总结. ...

最新文章

  1. OpenCV脸部美化FaceBeautificator的实例(附完整代码)
  2. [JAVA][算法] [字符串匹配]KMP
  3. 转载——Regression Tree 回归树
  4. ibatis 模糊查询 mysql_Mybatis使用MySQL模糊查询时输入中文检索不到结果怎么办
  5. 一年级abb式词语并造句_ABB式词语如何活学活用,家长都收藏了!
  6. C语言基础课第三次作业
  7. Android应用文本字体设置
  8. 梅林固件刷CFE教程
  9. 微星主板开机一直进入bios问题解决办法
  10. Agent Tesla样本分析
  11. Code For Better 谷歌开发者之声——Google Play
  12. 嵌入式操作系统-ucos是什么?
  13. 免费下载知网论文的重要链接
  14. Cytoscape.js 学习
  15. 计算机控制键功能,电脑ctrl键的作用大全
  16. 一则假新闻挑起卡塔尔断交危机?FBI:都怪俄黑客
  17. 好佳居窗帘十大品牌 窗帘的发展故事
  18. 26、流程引擎API
  19. Ubuntu 系列学习(五)ubuntu22.04安装flameshot火焰截图(图文)
  20. 人生法则:蝴蝶效应、青蛙现象、鳄鱼法则、鲇鱼效应、羊群效应、刺猬法则...

热门文章

  1. 习题11-7 奇数值结点链表 (20 分) -链表
  2. 安装和使用VCLSkin美肤插件
  3. 创建线程后为什么马上调用CloseHandle()来关闭句柄
  4. Android 图形驱动初始化
  5. 悲报, GIF 之父因新冠去世
  6. Redis 数据结构 :SDS、链表、字典、跳表、整数集合、压缩列表
  7. 第01讲:必知必会,掌握 HTTP 基本原理
  8. 经典算法刷题笔记pdf
  9. 微服务下分布式事务模式的详细对比
  10. 如此简单 | ElasticSearch 最全详细使用教程