一、垃圾回收器回收的对象
虚拟机内存区域中程序计数器、虚拟机栈、本地方法栈随线程而生,随线程而灭。这3个区域内存分配和回收都具备确定性。因此不需要过多考虑回收问题。
而Java堆和方法区不一样,这部分内存的分配和回收都是动态的,垃圾回收器所关注的就是这两部分区域。
二、如何判断对象需要回收
1、引用计数算法
给对象添加一个引用计数器,引用一次,计数器加1,引用失效,计数器减1。计数器为0的对象就是会被回收的对象。
优点:引用计数算法实现简单,效率高。缺点:无法解决对象之间循环引用问题。当对象objA和objB互相引用时候,它们的计数器都不为0,因此引用计数算法无法通知GC回收他们。
2、可达性分析算法
可达性分析算法是目前主流的算法判断对象是否存活。
算法思路:通过一系列的“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain)。当一个对象到GC Roots没有任何引用链相连,证明此对象是不可用的,可回收的。
可作为GC Roots的对象包括下面几种:虚拟机栈(栈帧中的本地变量表)中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI引用的对象。
三、引用
无论采用引用计数算法或可达性分析算法,最终判断对象是否存活都与‘引用’有关。Java将引用分为强引用、软引用、弱引用、虚引用4种。引用强度:强引用>软引用>弱引用>虚引用。
1、强引用:值类似“Object obj = new Object()”这类引用,只要强引用存在,垃圾回收器就不会回收掉对象。
2、软引用:用来描述一些有用但并非必须的对象,系统在要发生内存溢出前,会将这些对象列入回收范围之内,在第二次回收时候才会回收它们。
3、弱引用:用来描述非必须对象,在回收器下一次工作时,将会回收掉它们。
4、虚引用:仅有一个作用,在对象被回收后收到一个系统通知。
四、回收方法区
很多人认为方法区(永久代)是没有垃圾回收的,Java虚拟机规范说可以不要求在方法区实现垃圾回收。在方法区实现垃圾回收效率比较低。
永久代垃圾回收主要包含两部分:废弃常量和无用的类。
回收废弃常量和回收Java堆中对象非常类似,而回收类则苛刻的多,需同时满足以下3点:
1、该类所有实例都已经被回收,也就是Java堆中不存在该类的任何实例。
2、加载该类的ClassLoader已经被回收。
3、该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
五、注意