我已经阅读了关于Java中不同类型引用(强、软、弱、虚)的这篇文章,但我并不是很理解。
这些引用类型有什么区别,每种类型应该在什么情况下使用?
我已经阅读了关于Java中不同类型引用(强、软、弱、虚)的这篇文章,但我并不是很理解。
这些引用类型有什么区别,每种类型应该在什么情况下使用?
Java提供了两种不同类型/类的引用对象: 强引用和弱引用。弱引用又可以进一步分为软引用和虚引用。
我们来逐点讨论。
强引用对象
StringBuilder builder = new StringBuilder();
如果没有特别指定,builder
是强引用对象的默认类型/类。这种类型的引用会使所引用的对象不能被垃圾回收。也就是说,当一个对象被一系列强引用对象所引用时,它就不能被垃圾回收。
弱引用对象
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
弱引用对象不是引用对象的默认类型或类,需要像上面的示例一样显式指定才能使用。这种引用使引用对象有资格进行GC。也就是说,如果内存中字符串构建器对象的唯一可访问引用是弱引用,则GC可以清除该字符串构建器对象。当内存中的对象仅由弱引用对象引用时,它将自动有资格进行GC。
弱度级别
可以列举两个不同的弱度级别:软引用和幽灵引用。
软引用对象基本上是略微强的弱引用对象:通常,它会抵抗GC周期,直到没有可用内存并且存在OutOfMemoryError
风险(在这种情况下,它可以被删除)。
另一方面,幽灵引用对象只有在确切地知道对象已经从内存中有效删除时才有用:通常它们用于修复奇怪的finalize()复活行为,因为它们实际上不返回对象本身,只是帮助跟踪它们的内存存在。
弱引用对象非常适合实现缓存模块。事实上,可以通过允许GC在强引用链不再引用对象/值时清除内存区域来实现某种自动清除。一个例子是保留弱键的WeakHashMap。
strongRef --> weakRef --> objA
。现在,由于objA
具有从strongRef
间接引用,它是否会被垃圾回收? - samshers弱引用(Weak Reference):
简单地说,弱引用是一种不足以强制对象保留在内存中的引用。使用弱引用可以利用垃圾回收器自身检测可达性的能力,从而无需手动进行检测。
软引用(Soft Reference):
软引用与弱引用几乎相同,只是它不太愿意立即丢弃所引用的对象。只有当一个对象只有弱引用时,它将在下一次垃圾回收周期中被丢弃,但若一个对象具有软引用,则通常会在一段时间内保留。
幽灵引用(Phantom Reference):
幽灵引用与软引用或弱引用截然不同。它对其对象的控制是如此微弱,以至于甚至无法检索到该对象,其 get() 方法总是返回 null。这种引用的唯一用途是跟踪何时将其加入到引用队列中,因为此时您知道其指向的对象已经死亡。
本文摘自:https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
strongRef --> weakRef --> objA
。现在,由于objA
具有从strongRef
间接引用,它是否会被垃圾回收? - samshers这篇文章可以帮助理解强引用、软引用、弱引用和虚引用。
简单概括一下:
如果你有一个强引用指向一个对象,那么这个对象永远不会被垃圾回收器(GC)回收。
如果你只有弱引用指向一个对象(没有强引用),那么这个对象将在下一个GC周期中被回收。
如果你只有软引用指向一个对象(没有强引用),那么这个对象只有在JVM内存耗尽时才会被GC回收。
我们创建虚引用指向一个对象,以跟踪对象何时进入ReferenceQueue
。一旦知道了这一点,就可以执行精细的最终化操作。(这可以避免因虚引用不提供引用对象而意外地使对象恢复)。建议阅读这篇文章,了解更深入的细节。
因此,可以说强引用具有绝对的控制力(永远不会被GC回收)
软引用比弱引用更有优势(因为它们可以在JVM内存耗尽之前逃避GC周期)
弱引用比软引用更不强大(因为它们不能逃避任何GC周期,如果对象没有其他强引用,则会被回收)。
餐厅类比
现在,如果你是强顾客(类比于强引用),那么即使有新客户进来或者发生什么事情,你也永远不会离开你的桌子(堆上的内存区域)。服务员无权要求您离开餐厅。
如果您是软顾客(类比于软引用),那么如果有新客户进来,服务员只有在没有其他空桌子可容纳新客户时才会让您离开桌子。(换句话说,如果新客户进来并且没有其他桌子留给这位新客户,服务员才会让您离开桌子)
如果您是弱顾客(类比于弱引用),那么服务员可以随时(任何时间)要求您离开餐厅 :P
SoftReference
和 WeakReference
的简单区别由Android开发者文档提供。一个 SoftReference
和一个 WeakReference
的区别在于决定清除和排队引用的时间点:
SoftReference
应该尽可能晚地被清除和排队,即在VM面临内存耗尽危险时。
WeakReference
可以在已知弱引用时立即被清除和排队。
您提到的三个术语主要与对象是否有资格进行垃圾回收相关。
弱引用 :: 它是一种不足以强制对象保留在内存中的引用。垃圾回收器会决定是否将该对象收集为垃圾。 您无法阻止GC对其进行回收。
软引用 :: 它与弱引用差不多。但可以说它比弱引用更强地持有对象以避免被垃圾回收。
如果垃圾收集器在第一次生命周期中收集了弱引用,那么它将在下一次垃圾回收周期中收集软引用。
强引用 :: 它与上述两种引用相反。 它们不太可能被垃圾回收(大多数情况下永远不会被回收)。
您可以参考以下链接获取更多信息:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
这些是我们日常编码使用的常规对象引用:
Employee emp = new Employee();
变量“emp”持有一个Employee 对象的强引用,通过任何一条强引用链可访问到的对象都不符合垃圾回收条件。通常情况下这是我们期望的,但并非总是如此。现在假设我们需要从集合或映射中获取大量从数据库中检索的员工,并且需要定期对它们进行大量处理,为了保持性能,我们将把它们放在缓存中。
这样做是好的,但现在我们需要不同的数据,并且我们不需要那些Employee对象,除了缓存以外没有地方引用它们。由于这些对象没有使用但仍未满足垃圾回收条件,会导致内存泄漏,但我们无法将这些对象从缓存中删除,因为没有对它们的引用。
因此,我们要么手动清空整个缓存(比较繁琐),要么使用其他类型的引用,例如Weak References。WeakReference<Cache> cache = new WeakReference<Cache>(data);
要访问数据,您需要调用cache.get()。如果弱引用被垃圾回收,则此调用可能返回null:必须检查返回的值以避免NPE。4个引用级别 - 强引用、弱引用、软引用、虚引用
强引用 - 一种使被引用对象不符合垃圾回收的引用,例如StringBuilder。
弱引用 - 可以被垃圾回收的引用。
软引用 - 一种在内存可用时对象可以被垃圾回收的引用。最适合图像缓存。它们将保持对象直到内存可用。
虚引用 - 一种直接可被垃圾回收的引用。仅用于了解何时从内存中删除对象。
应用:
允许您确定对象何时完全从内存中删除。
当
finalize()
方法被重载时,GC可能无法按时回收两个类的GC适用对象。因此,虚引用使它们在finalize()
之前就变得可回收,这就是为什么即使大部分堆都是垃圾时也会出现OutOfMemoryErrors。
弱引用非常适合实现缓存模块。