垃圾回收器与内存分配策略
2021-04-20 10:47:45 10 举报
AI智能生成
垃圾回收器与内存分配策略
作者其他创作
大纲/内容
内存存活判断
引用计数法
实现简单
无法解决循环依赖问题
可达性分析算法
GCRoots
虚拟机栈引用
本地方法栈引用
类静态变量
常量池引用
被lock的变量
引用类型(JDK1.2后有后三种)
强引用
对象不会被回收
软引用
非必须对象,在内存溢出异常前,会将这些对象列入回收范围进行回收
SoftReference
弱引用
发生GC就会被回收
WeakReference
虚引用
最弱用的引用关系,一个对象是否有虚引用的存在完全不会其生存时间构成影响,也无法通过虚引用来去的对象实例
设计目的是在对象被收集器回收时收到一个系统通知
PhantomReference
finalize方法
被可达性分析算法判定为不可大对象,也不一定会被回收
真正宣告一个对象死亡,最多会经历两次标记过程
可达性分析后发现没有与GCRoots相连接的引用链后进行第一次标记
随后进行一次筛选,筛选条件是该对象是否有必要执行finalize方法
如果对象没有finalize方法
或对象finalize方法已经被执行
则被判定该对象无需执行finalize方法
当对象被判定为有必要执行finalize方法,则该对象将会被放置在一个名为F-Queue的队列之中,稍后由虚拟机自动简历的、地调度优先级的Finalize线程去执行他们的finalize方法。(只是触发执行,并不承诺等待运行结束)
finalize方法是对象逃脱死亡命运的最后一次机会,稍后收集器会对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize方法中拯救自己,只要重新与引用链上的任何一个对象建立关联即可,比如把自己赋值给某个类型变量或对象的成员变量,那么在第二次标记时他将会被移出“即将回收”的集合
如果这时候还没有逃脱,那基本上他就真的要被回收了
方法区回收
有些人认为方法区(HotSpot虚拟机中的元空间和永久代)是没有垃圾回收的
Java虚拟机规范中提到过,可以不要求虚拟机在方法去中实现垃圾收集,
事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在(JDK11的ZGC收集器就不支持类卸载)
方法区垃圾回收的性价比通常比较低
Java堆中(尤其是新生代),常规应用一次垃圾收集通畅可以回收70%至99%的内存空间
相比之下,方法区囿于苛刻的判定条件,其区域垃圾收集的回收成果远低于此
方法区垃圾收集主要回收两部分内容
废弃的常量
如字符串在内存中没有直接指向的话,将被移出字符串常量池进行垃圾回收
不再使用的类型
判定条件
该类的所有实例都已经被回收,也就是说Java堆中不存在该类及其任何子类的实例
加载该类的加载器已经被回收
除非是精心设计的,可替换的类加载器(OSGi和JSP)
,很难满足条件
,很难满足条件
该类的java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法
满足上述条件的“被允许”在虚拟机中进行回收
但是否进行类型回收通过参数进行开启
-Xnoclassgc
-XX:+TraceClassLoading
-XX:+TraceClassUnLoading
FastDebug版本才支持
在大量使用反射、动态代理、CGLib等字节码框架,动态生成JSP以及OSGi这类拼房自定义类加载器的场景中,通畅需要Java虚拟机具备类型卸载的能力,以保证不会对方法区造成过大的内存压力
垃圾收集算法
算法分类
从如何判定对象消亡的角度出发
引用计数式垃圾收集(Reference Counting GC)
追踪式垃圾收集(Tracing GC)
也被称为直接垃圾收集和间接垃圾收集。
由于引用计数式垃圾收集在主流虚拟机未涉及,介绍的所有算法均属于追踪式垃圾收集
分带收集理论
大多数对象生存周期都比较短暂,对象生存时间越长,被回收的可能性也就越小
0 条评论
下一页