垃圾回收机制
Posted 玹之又玹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了垃圾回收机制相关的知识,希望对你有一定的参考价值。
1.垃圾回收
1.1 概述
有些语言不支持垃圾自动回收,需要手动回收,而java是支持自动垃圾回收的,但是垃圾回收不是java语言首创的,垃圾回收关系的问题:那些区域需要回收,什么时候回收,如何回收。java的自动回收经过长时间的发展,已经非常强大了。
1.2 什么样的对象是垃圾
在运行过程中,没有被任何引用指向的对象,被称为垃圾对象。
1.3 为什么需要GC
如果不及时清理这些垃圾对象,会导致内存溢出。在回收时,还可以将内存碎片进行整理。(例如数组必须是连续空间存储)
1.4 内存溢出和内存泄漏
内存溢出:经过垃圾回收后,内存中仍然无法创建新的对象,内存不够用溢出。
内存泄漏:例如IO流没有close。JDBC连接运行结束后没有colse关闭,或是是生命周期很长的对象,一些经常不用的对象,但是垃圾回收器不能判断为垃圾,这些对象就默默的占用着内存,称为内存泄漏,大量的此类对象存在会导致出现内存溢出,也就是导致内存溢出的原因。
1.5 自动内存管理
好处:解放程序员,对内存管理更加合理,自动化。
缺点:对程序员管理内存的能力降低了,解决问题能力变弱了,不能调整垃圾回收的机制。
2.垃圾回收相关算法
2.1 标记阶段
作用:判断对象是否是垃圾对象,是否有引用指向对象。
相关的标记算法:引用计数算法和可达性分析算法
2.2 引用计数算法
引用计数算法(在现代的jvm中并没有使用)实现原理是有个计数器来记录对象的引用数量
String s1 = new String("aaa");
String s2 = s1; //此时“aaa”这个对象有两个引用变量指向它,计数器值为2
s2 = null; -1
s1 = null; -1
缺点:需要维护计数器,占用空间,频繁操作需要事件开销。无法解决循环引用问题,多个对象之间相互引用,没有其他外部引用指向他们,计数器都不为0,不能回收,产生内存泄漏。
2.3可达性分析算法/根搜索算法
实现思路:从一些为根对象(GCRoots)的对象出发去查找,与根对象直接或者间接连接的对象就是存活的对象,不与根对象引用链连接的对象就是垃圾对象。
2.4 GC Roots可以是那些元素?
1.在虚拟机栈中被使用的。
2.在方法中存储的静态成员变量指向的对象
3.作为同步锁使用的 Synchronized
4.在虚拟机内部使用的对象
2.5 对象放finalization机制
当一个对象被标记为垃圾后,在真正被回收之前,会调用一次Object类中的finalize(),是否还有逻辑需要进行处理。自己不要调用finalize(),留给垃圾回收器调用。
有了finalization机制的存在,在虚拟机中把对象状态分为三种:
1.可触及的: 不是垃圾,与根对象连接的对象状态。
2.可复活的:判定为垃圾了,但是还没有调用finalize(),(在finalize()中对象可能被别的引用变量指向,从而再次复活);
3.不可触及的:判定为垃圾了,且finalize()方法也已经被执行过了,这种就是必须被回收的对象。
2.6 垃圾回收阶段算法
标记--复制算法:
将内存分为大小相等的两份空间, 把当前使用的空间中存活的对象 复制到另一个空间中, 将正在使用的空间中垃圾对象清除.
优点: 减少内存碎片
缺点: 如果需要复制的对象数量多,效率低.
适用场景: 存活对象少 新生代适合使用标记复制算法
标记-清除算法
清除不是真正的把垃圾对象清除掉,
将垃圾对象地址维护到一个空闲列表中,后面有新对象到来时,覆盖掉垃圾对象即可.
特点:
实现简单
效率低,回收后有碎片产生
标记-压缩算法
第一阶段和标记清除算法一样,从根节点开始标记所有被引用对象
第二阶段将所有的存活对象压缩到内存的一端,按顺序排放。之后,清理边界外所有的空间。
优点
消除了标记-清除算法当中,内存区域分散的缺点,我们需要给新对象分配内存时,JVM 只需要持有一个内存的起始地址即可。消除了复制算法当中,内存减半的高额代价。
缺点
从效率上来说,标记-压缩算法要低于复制算法。
移动对象的同时,如果对象被其他对象引用,则还需要调整引用的地址
移动过程中,需要全程暂停用户应用程序。即:STW
分代搜集
年轻代(Young Gen)
年轻代特点:区域相对老年代较小,对象生命周期短、存活率低,回收频繁。
这种情况复制算法的回收整理,速度是最快的。复制算法的效率只和当前存活对象大小有关,因此很适用于年轻代的回收。而复制算法内存利用率不高的问题,
通过 hotspot 中的两个 survivor 的设计得到缓解。
老年代(Tenured Gen)
老年代特点:区域较大,对象生命周期长、存活率高,回收不及年轻代频繁。
这种情况存在大量存活率高的对象,复制算法明显变得不合适。一般是由标记-
清除或者是标记-清除与标记-压缩的混合实现。
1.Mark 阶段的开销与存活对象的数量成正比。
2.Sweep 阶段的开销与所管理区域的大小成正相关。
3.Compact 阶段的开销与存活对象的数据成正比。
分代的思想被现有的虚拟机广泛使用。几乎所有的垃圾回收器都区分新生代和老
以上是关于垃圾回收机制的主要内容,如果未能解决你的问题,请参考以下文章