紧接着上一篇JVM老生常谈之运行时数据区,我们已经连接了Java虚拟机几个运行时数据区,今天我们接着来讲讲Java虚拟机的几个重要的内存回收算法。本文所涉及的知识基本都基于HotSpot虚拟机。
首先,我们先来认识两个普遍用于判断对象是否被引用的算法:引用计数法和可达性算法。
引用计数法其实很简单,如果对象的计数器为0,就说明对象不再被引用,否则就是再被引用。
可达性算法则是通过判断对象是否能够被GC ROOT访问到来判断对象是否还在被引用。
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器就减1。任何时刻计数器为0的对象就是不再被使用的。
但是引用计数法其实是很难解决对象之间相互循环引用的问题,所以,Java虚拟机里面没有选用引用计数算法来管理内存。
我们用下面的例子来验证一下上面说的是否正确。
public class ReferenceCountingGC {
public Object instance = null;
private static final int _1MB = 1024 * 1024;
/**
* 这个成员属性的唯一意思就是占点内存,以便能在GC日志中看清楚是否被回收过
*/
private byte[] bigSize = new byte[2* _1MB];
public static void testGC(){
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
//假设在这行发生gc,objA和ObjB是否能被回收
System.gc();
}
}
可以看到,其实也是有被回收了,也就是意味着虚拟机并没有因为两个对象相互引用就不回收他们。侧面说明虚拟机并不是通过引用计数法来判断对象是否存活。
虽然可引用计数法很简单,也经常被提及,但是HotSpot虚拟机却不是用这个算法来判断对象是否继续被引用,而是使用下面要介绍的算法:可达性分析算法。
在主流商用程序语言的主流实现中,都是称通过可达性分析来判定对象是否存活的。
算法的基本思路就是通过一系列称为GC Roots
的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径被称为引用链,当一个对象到GC Roots
没有任何引用链相连时,则证明此对象不可用的。
上图中,Object1~Object4都可以被GC Root访问到,而Object5~Object7都不可以被访问到,这也就是说。也就是说,Object5、6、7这三个对象就是不可达的,下次垃圾回收的时候,可能就会被回收掉。
其实并不是所有的对象都可以作为GC Roots的对象,只有下列的对象可以作为GC Roots的对象。
既然是引用计数法,那肯定就有各种引用,下面来说说一些引用。
上面介绍了这么多,其实还有一个点没有讲到,我们要宣告一个对象死亡,至少要经历两次标记过程:
finalize()
方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行。如果对象被判定为有必要执行,则会被放到一个F-Queue队列。
finalize()
方法是对象跳脱死亡命运的最后一次机会,稍后GC
将对F-Queue
中对象进行第二次小规模标记,如果对象要在finalize()中重新拯救自己:只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时她将被移出即将回收的集合。
JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种。
JDK1.2之前,只有被引用和没有被引用两种状态
Object obj = new Object()
这类的引用,只要强引用还存在,垃圾收集器永远不会回收被引用的对象简单的对上面做一个总结,在JVM中判断一个对象是都需要回收有两种算法:引用计数法和可达性算法。引用计数法是通过判断引用的计数器的值是否为0来确认回收与否。这种算法听起来很简单,但是存在一个缺陷,就可以可能存在循环引用的情况。
还有一种就是可达性算法,可达性算法是通过判断引用能够被 GC Roots 访问到来确认回收与否。能被称为GC Roots对象也是有条件的主要有四种:虚拟机栈中引用的对象、方法中类静态属性引用的对象、方法中常量引用的对象和本地方法栈(native方法)中JNI引用的对象。
引用分为四种类型:强引用、软引用、弱引用和虚引用。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有