Java中GCRoots包括哪些
在垃圾回收过程中如何判断一个对象是否是垃圾,有两种算法。一种是引用记数法,一种是可达性分析法。
- 引用记数法是早期垃圾回收器中使用的算法,每一个对象维护一个该对象被引用的记数,每引用一次,记数加1,每减少引用1次,引用减1,当引用为0时,表示该对象不再被引用,可以作为垃圾被清除。但是引用记数法有一个最致命的问题,就是无法解决循环引用的问题。
- 可达性分析法,是通过从GCRoots出发,找出内存中的引用链,那么链中的对象表示可达,即不能作为被垃圾回收的。引用链之外的对象即可作为垃圾回收。Java中使用的是可达性分析法。
所以在可达性分析法中,判断哪些引用是GCRoots是垃圾回收的起点,那么这篇文章,就说说哪些引用是GCRoots。
GCRoots
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象,(一般指被static修饰的对象,加载类的时候就加载到内存中。)
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的native方法)中引用的对象
比如下面的代码:
其中,类静态变量 MAPPER,loadAccount 方法的局部变量 account1、account2、accountList 都可以作为 GC Roots(ArrayList 内部是用 Object[] elementData 数组来存放元素的)。
在调用 loadAccount 方法时,堆中的对象都是可达的,因为有 GC Roots 直接或间接引用到这些对象,此时若发生垃圾回收,这些对象是不可被回收的。loadAccount 执行完后,弹出栈帧,方法内的局部变量都被回收了,虽然堆中 ArrayList 对象还指向 elementData 数组,而 elementData 指向 Account 对象,但没有任何 GC Roots 的引用链能达到这些对象,因此这些对象将变为垃圾对象,被垃圾回收器回收掉。