我已经阅读了有关该主题的这篇文章,但是我不太了解。描述概念时,请给我一些建议以及示例。
我已经阅读了有关该主题的这篇文章,但是我不太了解。描述概念时,请给我一些建议以及示例。
Answers:
Java提供了两种不同类型/类型的引用对象:Strong和weak。弱引用对象可以进一步分为soft和phantom。
让我们一点一点地走。
强参考对象
StringBuilder builder = new StringBuilder();
这是引用对象的默认类型/类,如果没有特别指定,则为:builder
是强引用对象。这种引用使所引用的对象不符合GC的条件。也就是说,每当一个对象被一系列强引用对象引用时,就无法对其进行垃圾回收。
弱参考对象
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
弱引用对象不是引用对象的默认类型/类,要使用它们,应像上面的示例一样明确指定它们。这种参考使参考对象有资格使用GC。也就是说,如果StringBuilder
内存中对象唯一可访问的引用实际上是弱引用,则允许GC垃圾回收StringBuilder
对象。如果只有弱引用对象可以访问内存中的对象,则该对象将自动具有GC资格。
弱点水平
可以列举两种不同的弱点级别:“ 软”和“ 幻像”。
一个柔软的参考对象基本上是一个弱引用对象保留在内存多一点:通常情况下,它抵抗GC循环,直到没有可用的内存和存在的风险OutOfMemoryError
(在这种情况下,它可以被删除)。
另一方面,幻影引用对象仅在确切地知道何时已将对象有效地从内存中删除时才有用:通常,它们用于修复怪异的finalize()复兴/复活行为,因为它们实际上并不返回对象本身,而是返回对象本身。仅有助于保持他们的记忆力。
弱引用对象是实现缓存模块的理想选择。实际上,只要强引用链无法再访问对象/值,就可以通过允许GC清理内存区域来实现某种自动收回。一个示例是WeakHashMap保留弱键。
参考不足:
简而言之,弱引用是强度不足以迫使对象保留在内存中的引用。弱引用使您可以利用垃圾收集器的能力来确定您的可达性,因此您不必自己做。
软参考:
软引用与弱引用完全一样,不同之处在于软引用不急于丢弃它所引用的对象。只有弱可达性的对象(对它最强的引用是WeakReferences)将在下一个垃圾回收周期中被丢弃,但是柔弱可达性的对象通常会停留一段时间。
幻影参考:
幻像引用与SoftReference或WeakReference完全不同。它对它的对象的控制是如此的脆弱,以至于您甚至无法检索该对象-它的get()方法始终返回null。此类引用的唯一用途是跟踪何时将其排队到ReferenceQueue中,因为此时您知道指向的对象已死。
该文本摘自:https : //weblogs.java.net/blog/2006/05/04/understanding-weak-references
SoftReference
和之间的简单区别WeakReference
由Android Developer提供。
a SoftReference
和a 之间的差异WeakReference
是决定清除和排队引用的时间点:
SoftReference
应尽快清除A 并使其入队,以防VM内存不足的危险。
WeakReference
一旦已知弱引用,A 可能会被清除并入队。
您使用的三个术语主要与Object收集垃圾的资格有关。
弱引用 ::它的引用强度不足以迫使对象保留在内存中。它是垃圾收集器的一时冲动,以收集该对象进行垃圾收集。 您不能强迫该GC不收集它。
软参考 ::与软参考大致相同。但是可以说,它比垃圾回收中的弱引用更牢固地容纳了对象。
如果垃圾收集器在第一个生命周期本身中收集了弱引用,它将在下一个垃圾收集周期中收集软引用。
强参考 ::与上述两种参考相反。他们不太喜欢收集垃圾(大多数情况下从不收集垃圾)。
您可以参考以下链接以获取更多信息:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
此文章可以超有助于了解强,软,弱,虚引用。
为了给您一个总结,
如果您对某个对象有很强的引用,则该对象将永远无法由GC(垃圾收集器)收集/回收。
如果您的参考文献薄弱对象(而没有强引用),则该对象将在下一个GC周期中由GC回收。
如果您仅具有对对象的软引用(没有强引用),则仅当JVM内存不足时,GC才会回收该对象。
我们创建对象的幻像引用,以跟踪该对象何时入队ReferenceQueue
。一旦知道可以执行精细的终结处理。(这将使您免于意外地复现该对象,因为幻影引用不会给您提供引用对象)。我建议你阅读此文章以获得深入详细地介绍这一点。
所以你可以说,强大的参考具有最终的力量(GC永远无法收集)
软引用比弱引用更强大(因为软引用可以逃避GC周期,直到JVM内存不足)
弱引用甚至没有软引用强大(因为它们无法逃脱任何GC周期,如果对象没有其他强引用,则将被回收)。
餐厅类比
现在,如果您是一个强大的客户(类似于强大的参考),那么即使有新客户进来餐厅或发生的事情,您也永远不会离开桌子(堆上的内存区域)。服务员无权告诉您(甚至要求您)离开餐厅。
如果您是一位软顾客(类似于软顾客),那么如果有新顾客进来,餐厅的服务员将不会要求您离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,服务员只会在有新客户进场并且没有其他可供该新客户使用的桌子时才要求您离开桌子)
如果您是弱顾客(类似于弱顾客),那么服务员可以(在任何时间)要求您离开餐厅:P
4度参考- Strong, Weak, Soft, Phantom
强-是一种引用,使引用的对象不符合GC的条件。构建器类。例如-StringBuilder
弱-是可以用于GC的参考。
软-是一种引用,其对象可以使用GC,直到有可用的内存为止。最适合图像缓存。它将保持它们直到有可用的内存。
幻影-是一种引用,其对象直接可以用于GC。仅用于了解何时从内存中删除对象。
用途:
允许您确定何时从内存中完全删除对象。
当
finalize()
方法重载时,两个类的符合GC要求的对象可能无法及时发生GC。因此,幻影引用使他们有资格获得GC资格finalize()
具有,这就是即使大部分堆都是垃圾时仍会出现OutOfMemoryErrors的原因。
弱引用是实现高速缓存模块的理想选择。
这些是我们每天编写的常规对象引用:
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传递给构造函数以获取弱引用,则垃圾收集器会在完成弱化或GC之前将弱引用附加到ReferenceQueue。您可以定期处理此队列并处理无效引用。
SoftReference就像WeakReference,但是不太可能被垃圾回收。垃圾回收器可根据内存需求酌情清除软引用。虚拟机保证在抛出OutOfMemoryError之前,将清除对所有可软访问对象的软引用。
幻象引用是所有引用类型中最弱的,对它们调用get将始终返回null。在完成对象之后,但在回收分配的内存之前,对对象进行幻像引用。与在完成对象之前将其排队的弱引用或很少使用GC的幻像引用相反。
那么它们有什么用呢?构造幻像引用时,必须始终传递ReferenceQueue。这表明您可以使用幻像引用来查看对象何时进行了GC处理。
嘿,因此,如果弱引用在被认为已完成但尚未进行GC时入队,则可以在终结器块中为该对象创建一个新的强引用,并防止该对象被GC处理。是的,可以,但是您可能不应该这样做。为了检查这种情况,除非每个对象仅通过幻像引用可访问,否则GC周期将至少发生两次。这就是为什么即使内存中包含大量垃圾也可能耗尽堆的原因。幻像引用可以防止这种情况。
您可以在我的文章Java中的引用类型(强,软,弱,幻影)上阅读更多内容。