关于JVM系列的文章,都是在读了《深刻理解java虚拟机》一书以后的读书笔记总结。java
每一个人入门java的时候,基本上都会听到的关于java的一个邮电就是java的内存管理功能。使用java的时候不须要将过多的心思摆在内存管理的问题上(实际上,内存管理是开发者始终关注的话题,尤为是移动app的开发,万一心情很差就oom了呢)。今天简单总结一下java的垃圾回收的知识点。android
java中引用包括下面四种:算法
强引用app
程序中广泛存在的相似“Object object=new Object()”这种类型的引用属于强引用。垃圾回收器永远不会回收被强引用所引用的对象。学习
软引用cdn
用以描述有用但却并不是必需的对象。对于软引用所引用的对象,在系统将要发生oom异常以前,将会对这些对象列进回收范围之中进行第二次回收。对象
弱引用blog
用于描述非必需的对象,强度较软引用弱。软引用关联的对象只能生存到下一次垃圾收集发生以前。不管当前内存是否足够,它都会在垃圾收集器开始工做的时候被回收。内存
虚引用开发
也称为幽灵引用或者幻引用。虚引用的存在不会对对象的生存时间产生影响,也没法经过虚引用取得对象的实例。为对象设置虚引用的惟一目的就是能在这个对象呗垃圾收集器回收时收到一个系统通知。
引用计数算法
给对象添加一个引用计数器,当有地方引用该对象时,计数器加一;引用失效时,计数器减一。任意时候,只要计数器不为零,就表示该对象尚存在引用关系,不然表示对象不能再被使用。
可达性分析算法
以一系列能够被称为gc-roots的对象为起点并向下搜索,搜索走过的路径为引用链,当对象和gc-roots之间没有任何的引用链的话,则该对象是不可用的,以下图所示:
java中能够被看做是gc roots的对象包括:
gc roots不可达的对象,在被回收以前至少要经历两次被标记的过程,才能肯定是否会被垃圾回收器回收。在对象被发现没有引用链的时候,会被第一次标记而且进行一次筛选(筛选的条件是该对象有没有必要执行finalize()方法,当对象没有覆盖finalize()方法或者该方法已经被虚拟机调用过的话,虚拟机都会认为没有必要执行finalize()方法)。若是对象没能在finalize()方法中从新于引用链上的任意对象创建关联关系,那么对象将会在第二次标记的时候被回收。
算法分为标记和清除两个阶段。首先标记出全部须要回收的对象,在标记完成后统一回收被标记的对象。(这个方法效率较低,并且回收以后会产生大量的不连续的内存碎片)示意图以下所示:
将内存按容量划分为等大的两块,每次只使用其中的一块内存,当这一块内存将用完的时候就将还存活着的对象复制到另外一块内存上面,而后再把已使用过的内存空间一次清理掉。示意图以下所示:
这个算法的一种改进作法是在在回收新生代的时候,将内存分为一块较大的eden空间和两块较小的survivor空间,每次使用eden和其中的一块survivor空间。当回收的时候,将其中还存活的对象一次性地复制到另一块survivor空间上,最后清理掉eden和以前使用的survivor空间。
标记过程于标记-清除算法同样,可是并不直接对可回收对象进行清理,而让全部存活的对象都往一端移动,而后清理端边界之外的内存(针对老年代存活率比较高的现象而提出).示意图如下所示:
它根据对象的存活周期的不一样将内存划分为几块,通常是把Java堆分为新生代和老年代。在新生代中,每次垃圾收集时都会发现有大量对象死去,只有少许存活,所以可选用复制算法来完成收集,而老年代中由于对象存活率高、没有额外空间对它进行分配担保,就必须使用标记—清除算法或标记—整理算法来进行回收。
简单整理如上,若是须要更加深刻的学习的话,建议你们能够看一下《深刻理解JVM》这本书,我的以为写得确实很棒。接下来,还会继续写一些这本书的读书笔记。若是你们喜欢,能够点赞收藏。有什么问题欢迎评论一块儿探讨。你们也能够关注我,我会在工做之余分享本身学习android的一些东西。最后,感谢你宝贵的时间阅读这篇文章,谢谢!