引用计数法
在对象中添加一个引用计数器每当有一个地方引用它的时候,计数器的值就加一;当引用失效的时,计数器的值就减一;任何时刻计数器为零的对象就是不可能再被使用。但是这种算法不能解决循环引用的问题。
可达性分析算法
通过一系列称为“GC Roots”的根对象作为起始节点集,根据这些节点开始,根据引用开始向下搜索,搜索过程中所走过得路径称为“引用链”(Reference Chain),如果某个对象到“GC Roots”没有任何引用链,则证明这个对象不可能再被使用。
可以作为GC Roots的对象:
- 在虚拟机栈(栈中的本地变量表)中的引用对象,比如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等
- 在方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 在本地方法中JNI(即通常所说的Native方法)引用的对象
- Java虚拟机内部的引用,如基本类型对应的Class对象,一些常驻的异常对象(NullPointException , OutOfMemoryError ),还有系统的类加载器。
- 所有被同步锁(synchronized关键字)持有的对象
- 反应Java虚拟机内部情况的JMXBean、JVMTI中注册的回调,本地代码缓存等。
java中的引用
- 强引用:是最传统的引用,指的是在程序代码之中普遍存在的引用赋值。无论什么情况下强引用的对象不能被回收掉
- 软引用:用来描述一些还有用,但非必要的对象。只被软引用关联的对象,在系统发生内存溢出异常前,会把这些对象列进回收范围之中进行二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。实现类SoftReference
- 弱引用:用来描述那些非必须对象,但是它的强度比软引用更强一些,被弱引用关联的对象只能生存到下一次垃圾发生为止。提供WeakReference类来实现弱引用。
- 虚引用:也称为“幽灵引用”或者“幻影引用”,是最弱的一种引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被回收器回收的时候收到一个系统通知。实现类PhantomReference
回收方法区
《java虚拟机规范》中提到可以不要求方法区实现垃圾收集。方法区的垃圾收集主要回收两部分内容:废弃的常量和不在使用的类型。
判断一个类不在使用的条件
- 该类的实例都被回收
- 加载该类的类加载器被回收
- 该类对应的java.lang.Class对象没有被任何地方引用,无法在任何地方通过反射访问该类的方法
在大量使用反射、动态代理、CGLib等字节码框架,动态生成JSP以及OSGI这类频繁自定义类的场景中,通常需要Java虚拟机具备类型卸载的能力,以保证不会对方法区造成过大的内存压力。