1.如何判断对象是否已经不会再被调用,也就时传统意义上的死亡?
目前来说有两种处理方式
1.1 引用记数法
也就是给对象添加一个引用计数器,当对象被调用时,计数器就加1,当引用失效时,计数器就减1。当计数器为0时则表示当前对象没有被引用,也就是说对象已经死亡。
优点:实现简单,判定效率高
缺点:无法解决对象之间的相互循环引用的问题(致命缺陷),所以大部分主流的虚拟机都没有使用这中方法来管理内存。
循环引用:A a = new A(); B b=new B();
a = b; b = a; a = null; b = null ; 如此a与b的引用计数器永远不会为0,则无法通知GC收集器来回收此部分空间。
1.2 可达性分析算法
通过一系列称之为GC Roots 的对象作为起点,从这些节点向下搜索,走过的路径称之为引用链,当一个对象到GC Root没有任何引用链的时候,则称之为这个对象不可达,证明此对象可以被GC收集器回收
在java语言中能称之为 GC Roots的对象有如下几种:
1.虚拟机栈(栈帧中的局部变量表)中引用的对象
2.方法区中静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈(native 方法)中JNI引用的对象
总结就是,方法调用时,方法中引用的对象;类的静态变量引用的对象;类中常量引用的对象;Native方法中引用的对象。
2.引用
在java中引用分为四种:强引用,软引用,弱引用,虚引用。引用强度依次递减。
强引用 :类似 A a = new A(); 只要强引用还存在,垃圾回收器永远不会回收掉被引用的对象。
软引用(SoftReference) : 用来描述一些还有用但非必需的对象,在系统将要发生内存溢出异常之前,会将这些对象列进回收范围进行第二次回收,要此次回收还没有足够的内存,则会抛出内存溢出异常
弱引用(WeakReference):也是用来描述一些非必需的对象,但它的强度比软引用弱,弱引用的对象只能生存到下一次垃圾回收发生之前,当垃圾收集器工作时,无论内存是否足够,被弱引用关联的对象都会被回收掉 (ThreadLocal中用到的弱引用,可自行分析)
3.回收方法区
永久代垃圾回收分为两部分类容:废弃常量,无用的类
判定一个类时无用的类条件比较苛刻,要同时满足以下三个条件:
1.该类的所有实例已经被回收(java堆中不存在该类的实例)
2.加载该类的classLoader已经被回收
3.该类对应的java.lang.Class对象没有在任何地方引用,无法在任何地方通过反射机制访问该类的方法