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