- 一、强引用
- 二、软引用
- 三、弱引用
- 四、虚引用
- 五、总结
- 六、对比
- 普通变量赋值即为强引用,如A a= new A();
- 如果一个对象具有强引用,GC绝不会回收它,当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
- 只有通过GC Root的引用链,发现强引用不到该对象,该对象才能被回收。
- SoftReference a = new SoftReference(new A());
- 如果仅有软引用该对象时, 首次垃圾回收不会回收该对象,如果内存仍不足,再次回收时才会释放对象。即,如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。
- 注意,释放时,释放的是对象a的内存。我们可以设置软引用队列,当引用对象a被回收时,JVM会将软引用对象放入软引用队列中,软引用自身占用的内存需要配合引用队列来释放。
- 典型例子:反射创建对象。
- WeakReference a = new WeakReference(new A());
- 如果仅有弱引用引用该对象时,只要发生垃圾回收,就会释放该对象。
- 注意,释放时,释放的是对象a的内存。我们可以设置弱引用队列,当引用对象a被回收时,JVM会将弱引用对象放入弱引用队列中,弱引用自身占用的内存需要配合引用队列来释放。
- 典型例子:ThreadLocalMap中的Entry对象。
- 弱引用与软引用的区别:只具有弱引用的对象拥有更短暂的生命周期。
- PhantomReference a = new PhantomReference(newA());
- 如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。
- 虚引用必须配合引用队列一起使用,当垃圾回收器准备回收对象a时,如果发现对象a还有虚引用,就会在回收对象a的内存之前,把这个虚引用加入到与之关联的引用队列中。由Reference Handler线程释放其关联的外部资源(Java内存外的内存资源)。
- 虚引用加入到引用队列中后,程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
- 典型例子:Cleaner释放DirectByteBuffer占用的直接内存。
- 虚引用与软引用和弱引用的区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。
- 虚拟机的内存不够使用,开始报警。
- 首先,垃圾回收机制开始执行System.gc(); 回收虚引用和弱引用对象。
- 如果弱引用对象回收完之后,内存还是报警,继续回收软引用对象。
- 如果软引用对象回收完之后,抛出OutOfMemoryError错误,而不会被回收强引用的对象。
引用类型 | 被回收时间 | 用途 | 生存时间 |
---|---|---|---|
强引用 | 从来不会 | 对象的一般状态 | jvm退出时终止 |
软引用 | 内存不足时 | 对象缓存 | 内存不足时终止 |
弱引用 | 垃圾回收时 | 对象缓存 | gc运行之后终止 |
虚引用 | unknow | unknow | unknow |
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)