GC原理
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
优点:
- 垃圾回收机制有效的防止了内存泄露,可以有效的使用可使用的内存。
- 垃圾回收器通常作为一个单独的低级别的线程运行,在不可预知的情况下对内存堆中已经死亡的或很长时间没有用过的对象进行清除和回收。
- 程序员不能实时的对某个对象或所有对象调用垃圾回收器进行垃圾回收。
如何判断哪些对象可以被GC回收
- 引用计数器法:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0时就可以被回收。它有一个缺点不能解决循环引用的问题;
- 可达性分析算法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。
注意:
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。
java引用分析
- 强引用:发生 gc 的时候不会被回收。
Object strongReference = new Object();
- 软引用:有用但并不是必需的对象,在对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。
软引用可以和一个引用队列联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());
- 弱引用:非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(sr.get());
- 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc时返回一个通知。
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
System.out.println(pr.get());
参考资料:
https://blog.csdn.net/jiahao1186/article/details/81591861