我读过这篇关于Java中不同类型引用(强、软、弱、幻影)的文章,但我不是很理解。
这些引用类型之间的区别是什么,什么时候使用每种类型?
我读过这篇关于Java中不同类型引用(强、软、弱、幻影)的文章,但我不是很理解。
这些引用类型之间的区别是什么,什么时候使用每种类型?
当前回答
这篇文章对于理解强引用、软引用、弱引用和幻影引用非常有帮助。
总结一下,
如果你对一个对象有强引用,那么这个对象永远不能被GC(垃圾回收器)收集/回收。
如果对一个对象只有弱引用(没有强引用),那么该对象将在下一个GC循环中被GC回收。
如果对对象只有软引用(没有强引用),那么只有当JVM内存耗尽时,GC才会回收该对象。
我们创建对对象的虚引用来跟踪对象何时进入ReferenceQueue队列。一旦您知道可以执行细粒度终结。(这将避免意外地复活对象,因为phantom-reference不给你referrant)。我建议您阅读这篇文章来深入了解这方面的细节。
所以你可以说,强引用具有强大的功能(GC永远不会收集)。
软引用比弱引用更强大(因为它们可以逃避GC循环,直到JVM耗尽内存)
弱引用甚至不如软引用强大(因为它们无法逃脱任何GC循环,如果对象没有其他强引用,则会被回收)。
餐厅的类比
服务员- GC 堆中的对象 餐厅区域/空间-堆空间 新客户-在餐厅想要桌子的新对象
现在,如果您是一个强客户(类似于强引用),那么即使餐厅里来了一个新客户或发生了其他事情,您也不会离开您的表(堆上的内存区域)。服务员没有权利告诉你(甚至要求你)离开餐厅。
如果你是一个软顾客(类似于软参考),那么如果餐厅来了一个新顾客,服务员不会让你离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,只有当一个新顾客进来,并且没有其他的桌子给这个新顾客时,服务员才会叫你离开桌子)
如果你是一个弱顾客(类似于弱参考),那么服务员可以根据他的意愿(在任何时候)要求你离开餐厅:P
其他回答
您使用的这三个术语主要与Object获得垃圾收集的资格有关。
弱引用:它是一个不够强的引用,不足以迫使对象保留在内存中。为了垃圾回收而收集该对象是垃圾收集器的心血来潮。 你不能强迫GC不收集它。
软引用:它或多或少类似于弱引用。但是您可以说,它比垃圾收集中的弱引用更强地保存对象。
如果垃圾收集器在第一个生命周期中收集弱引用,它将在下一个垃圾收集周期中收集软引用。
强参考:它正好与上面两种参考相反。 他们不太喜欢被垃圾收集(大多数情况下他们从未被收集过)。
你可以参考下面的链接了解更多信息:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
软参考和弱参考之间的简单区别是由Android开发者提供的。
软引用和弱引用之间的区别是决定清除引用并将其排队的时间点:
一个SoftReference应该被清除并尽可能晚地进入队列, 即防止虚拟机存在内存不足的危险。 WeakReference可以在已知的情况下被清除并加入队列 weakly-referenced。
强引用
这些是我们每天编写的常规对象引用:
Employee emp = new Employee();
变量“emp”保存着对Employee对象的强引用,通过任何强引用链可访问的对象都不符合垃圾收集的条件。 通常,这是你想要的,但并不总是如此。现在假设我们在一个集合或映射中从数据库中获取大量的员工,我们需要定期对他们进行大量的处理,所以为了保持性能,我们将他们保存在缓存中。
到目前为止,这很好,但现在我们需要不同的数据,我们不需要那些Employee对象,这些不从任何地方引用,除了缓存。这导致了内存泄漏,因为这些对象没有被使用,但仍然不符合垃圾收集的条件,我们不能从缓存中删除这些对象,因为我们没有对它们的引用? 所以在这里,我们要么需要手动清空整个缓存,这很乏味,要么我们可以使用其他类型的引用,例如弱引用。
弱引用
弱引用不会将对象固定到内存中,如果没有从其他引用引用,则会在下一个GC循环中进行GC。我们可以使用Java提供的WeakReference类来创建上述类型的缓存,它不会存储没有从其他地方引用的对象。
WeakReference<Cache> cache = new WeakReference<Cache>(data);
要访问数据,需要调用cache.get()。如果弱引用被垃圾回收,这个get调用可能返回null:你必须检查返回值以避免npe。 Java提供了使用弱引用的集合,例如WeakHashMap类将键(而不是值)存储为弱引用。如果键被GC化了,那么该值也会自动从映射中删除。
由于弱引用也是对象,我们需要一种方法来清理它们(当它们引用的对象已经被GC化时,它们就不再有用了)。如果您将ReferenceQueue传递给弱引用的构造函数,那么垃圾收集器将在ReferenceQueue最终确定或GC - d之前将该弱引用附加到ReferenceQueue。您可以定期处理这个队列并处理死引用。
软引用
软引用类似于弱引用,但它不太可能被垃圾收集。垃圾收集器根据内存需求自行清除软引用。虚拟机保证在抛出OutOfMemoryError错误之前,对软可达对象的所有软引用都将被清除。
幽灵的引用
幻影引用是所有引用类型中最弱的,对它们调用get总是返回null。一个对象在它被终结后,但在它分配的内存被回收之前被幻影引用,与弱引用相反,弱引用在它们被终结之前被排队,或者很少使用幽灵引用。
那么它们有什么用处呢?当你构造一个虚引用时,你必须传递一个referencqueuue。这表明您可以使用幻影引用来查看对象何时被GC。
Hey, so if weak references are enqueued when they’re considered finalize but not yet GC’d we could create a new strong reference to the object in the finalizer block and prevent the object being GC’d. Yep, you can but you probably shouldn’t do this. To check for this case the GC cycle will happen at least twice for each object unless that object is reachable only by a phantom reference. This is why you can run out of heap even when your memory contains plenty of garbage. Phantom references can prevent this.
你可以阅读我的文章《Java中的引用类型(强,软,弱,幻影)》。
这篇文章对于理解强引用、软引用、弱引用和幻影引用非常有帮助。
总结一下,
如果你对一个对象有强引用,那么这个对象永远不能被GC(垃圾回收器)收集/回收。
如果对一个对象只有弱引用(没有强引用),那么该对象将在下一个GC循环中被GC回收。
如果对对象只有软引用(没有强引用),那么只有当JVM内存耗尽时,GC才会回收该对象。
我们创建对对象的虚引用来跟踪对象何时进入ReferenceQueue队列。一旦您知道可以执行细粒度终结。(这将避免意外地复活对象,因为phantom-reference不给你referrant)。我建议您阅读这篇文章来深入了解这方面的细节。
所以你可以说,强引用具有强大的功能(GC永远不会收集)。
软引用比弱引用更强大(因为它们可以逃避GC循环,直到JVM耗尽内存)
弱引用甚至不如软引用强大(因为它们无法逃脱任何GC循环,如果对象没有其他强引用,则会被回收)。
餐厅的类比
服务员- GC 堆中的对象 餐厅区域/空间-堆空间 新客户-在餐厅想要桌子的新对象
现在,如果您是一个强客户(类似于强引用),那么即使餐厅里来了一个新客户或发生了其他事情,您也不会离开您的表(堆上的内存区域)。服务员没有权利告诉你(甚至要求你)离开餐厅。
如果你是一个软顾客(类似于软参考),那么如果餐厅来了一个新顾客,服务员不会让你离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,只有当一个新顾客进来,并且没有其他的桌子给这个新顾客时,服务员才会叫你离开桌子)
如果你是一个弱顾客(类似于弱参考),那么服务员可以根据他的意愿(在任何时候)要求你离开餐厅:P
4个参照度-强,弱,软,幻影
强-是一种引用,它使被引用的对象不 有资格获得GC。构建器类。StringBuilder Weak -是一个符合GC条件的引用。 Soft -是一种引用,其对象在内存可用之前都有资格进行GC。最适合图像缓存。它将保存它们,直到内存可用为止。 幻影——是一种引用,其对象直接适合GC。仅用于了解对象何时从内存中删除。
用途:
允许您识别对象何时从内存中完全删除。 当finalize()方法重载时,对于两个类中符合GC条件的对象可能不会及时进行GC。因此,幻影引用使它们有资格在finalize()之前进行GC,这就是为什么即使堆的大部分是垃圾,您也可以获得OutOfMemoryErrors。
弱引用是实现缓存模块的理想方法。