1、如何判断对象可以回收
1.1 引用计数法
【jvm没用】被引用就+1,没人引用就是0,就是垃圾
缺点:A、B循环引用,但是没人引用A、B时,应该回收,但是用这个方法却回收不了,会导致内存泄露
1.2 可达性分析算法
【根对象】肯定不是垃圾的对象 GC Root
如果一个对象被根对象,直接or间接引用,那就不是垃圾;否则就是垃圾
Q:哪些对象可以作为GC Root对象?
System Class:Object、Hashmap、System……
Native Stack(操作系统的类)
Busy Monitor(监控加锁的对象)
Thread(线程):里面有很多,比如局部变量引用的对象,可以是一个根对象
eclipse里,有一个插件可以看GCRoot对象,在IDEA,有个jprofiler插件能用
1.3 四种引用(5种?)
强→软→弱→虚→终结器
(我这里想贴一个图,但是csdn一直提示上传失败,心累,回头补上)
1、强:实心的线;
例,B、C对象都是GCRoot,因为他们直接or间接的强引用了A1对象,所以A1不能被GC
2、软(SoftReference):短线的线;如果没有直接被GCRoot对象强引用,则会被回收;
比如,A2被B强引用,被C软引用,则A2不会被GC;当B不再引用A2,只剩一个软引用,则当GC且内存不足时,A2会被GC;
【引用队列】可以配合软弱使用。用法是,当软和弱引出去的对象消失时,他俩就会被放进这个引用队列,这样GC的时候,方便遍历他们
3、弱(WeakReference):小点点的线;同软引用,区别是,只要有GC,就会被回收
4、虚(PhantomReference):一定会关联一个引用队列;只要有GC,就会被回收
例如,前面说的直接内存,Cleaner就是虚引用;虚自己引用的对象,比如图里ByteBuffer被回收时,它一定会被放进引用队列,然后有个线程去逐个检查引用队列,调虚引用的方法,比如直接内存的虚引用就会调Unsafe.freeMemory()释放直接内存
5、终结器(FinalReference):当A4有了finalize()方法,它就生成一个终结器引用;当A4不再被B引用时,终结器引用也会被放入引用队列,然后有个低优先级的线程会来扫,扫到这个引用时,就调A4里的finalize()方法。所以他步骤很多,内存很可能不被正确的释放,所以不推荐使用finalize()
另:附上一篇整理的很好的笔记↓