主要的GC算法
- 引用计数
不赘述了,主要是无法解决互相引用的问题 - 可达性分析
就是从一些叫做GC Roots
的引用开始,一步一步的找能达到的对象,如果没达到,那么就不可达的,就会开始回收它。
HotSpot
采用的是可达性分析。
那么哪些可以作为GC Roots呢?
书上的
在《深入理解Java虚拟机-JVM高级特性与最佳实践》中,简单的提了一下
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(native方法)引用的对象
简单解释下
第一种就是指当前的Java线程中正在调用的方法的引用类型的参数,局部变量,临时值,这个具有随机性。
第二种就是指类对象的引用对象,比如1
2
3public class Solution {
private static List<String> list = new LinkedList<>();
}
这里的list
就是这种。
第三种是指的常量一般指static final
这种,比如1
2
3public class Solution {
public static final String name = "hello";
}
这里的name
就是,当然枚举类中的也是。
第四种就是native
方法了,就是一般是c语言或者c++写的。
再进行拓展
我又去搜了一下。
又找到了更具体的一下,其实哪些能作为GC Roots在一定程度上也是依赖收集器的设计的。
来自RednaxelaFX的答案
- (看情况)所有当前被加载的Java类
- (看情况)Java类的引用类型静态变量
- (看情况)Java类的运行时常量池里的引用类型常量(String或Class类型)
这里还多了Class类型,。。。。
在eclipse
的文档网站,找到了更为详细的
System Class
被bootstrap类加载器加载的类JNI Local
JNI定义的局部变量JNI Global
JNI定义的全局变量Thread Block
当前线程块中的对象Thread
未停止的线程Busy Monitor
调用了wait()或者notify()或者正在进行同步的对象和类Java Local
当前线程虚拟机栈中的本地变量Native Stack
本地方法栈中的对象Finalizable
一个正在在等待finalize的对象Unfinalized
拥有finalize方法,但是不在等待finalize的对象Unreachable
一个不可达的对象,但是仍然被Memory Analyzer标记为GC Root的对象
这个的解释就是对于一些小对象,GC觉得收集它太浪费珍贵的GC时间了,就放弃了。Java Stack Frame
Java栈帧,如果你设定栈帧也为一个对象的话Unknown
其他未知的
总结
上面说的很多重复的,有些是看不懂的。所以我自己总结了下
- 所有线程当前虚拟机栈(栈帧中的本地变量表)中引用的对象,包括局部变量,参数对象。
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(native方法)引用的对象,包括局部变量和全局变量
- 被bootstrap类加载器加载的类
- 当前所有活跃的线程
- 调用了wait()或者notify()或者正在进行同步的对象和类
- 一个正在在等待finalize的对象
- 拥有finalize方法,但是不在等待finalize的对象
- 一个不可达的对象,但是仍然被Memory Analyzer标记为GC Root的对象