内存回收策略与垃圾收集器
GC 需要解决的问题
- 哪些内存需要回收
- 什么时候回收
- 如何回收
- 垃圾收集算法
1. Java 堆(对象)回收策略
1.1 引用计数法
- 循环引用问题
1.2 可达性分析算法
-
GC Roots
- 虚拟机栈栈帧中的本地变量表
- 方法区中的 Class 对象、类的静态属性引用的对象、常量引用的对象
- 本地方法栈中引用的对象
- https://www.shangmayuan.com/a/43208998342440369a04f0fd.html
1.3 引用
-
强引用
- Object o = new Object();
-
软引用
-
有用但非必须
- 缓存
-
发生内存溢出异常前,尝试清理软引用对象,回收完成还没有足够内存,就会抛异常
-
-
弱引用
- 下一次垃圾回收就会回收
-
虚引用
- 回收的时候有一个通知
1.4 对象回收过程
-
- 可达性分析
-
- 判断是否有必要执行 finalize()方法
-
- 有必要则放到 F-Queue 队列,稍后由虚拟机自动创建的,优先级比较低的 Finalizer 线程执行,但是不保证等到执行结束,防止死循环等等
2. 永久代(方法区)回收策略
2.1 常量池
- 没有对象引用就可以回收(废弃常量)
2.2 类
-
所有实例都已被回收
-
ClassLoader 已被回收
-
类对应的 Class 对象没有在任何地方被引用
-
JVM 参数
- HotSpot:-Xnoclassgc
- 反射、动态代理、CGLIB 等自定义类加载器的需要虚拟机支持类卸载功能,保证永久代不会溢出
3.1 分代收集理论
-
弱分代假说
- 绝大多数对象都是朝生夕灭的
-
强分代假说
- 熬过越多次垃圾手机过程的对象就越难以消亡
-
跨代引用假说
- 跨代引用相对于同代引用仅占极少数
3.2 标记清除算法
- 内存碎片化问题
3.3 标记复制算法
- 半区复制
3.4 标记整理算法
- 清除后会移动存活对象到同一边
- Stop The World