Java:强/软/弱/幻象参考之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9809074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: difference between strong/soft/weak/phantom reference
提问by
I have read this articleabout the topic, but I don't really understand it. Please give me some advice along with examples when describing the concepts.
我已经阅读了有关该主题的这篇文章,但我并没有真正理解它。在描述概念时,请给我一些建议和例子。
回答by Sabya
The three terms that you have used are mostly related to Object's eligibility to get Garbage collected .
您使用的三个术语主要与 Object 获得垃圾收集的资格有关。
Weak Reference:: Its a reference that is not strong enough to force the object to remain in memory . Its the garbage collector's whimsto collect that object for garbage collection. You can't force that GC not to collect it.
弱引用:: 它的引用强度不足以强制对象保留在内存中。它是垃圾收集器的一时兴起来收集该对象以进行垃圾收集。 你不能强迫 GC 不收集它。
Soft Reference:: Its more or less same like the weak reference . But you can say that it holds the object a bit more strongly than the weak reference from garbage collection.
Soft Reference:: 它或多或少与弱引用相同。但是你可以说它比垃圾收集的弱引用更强烈地持有对象。
If the Garbage collectors collect the weak reference in the first life cycle itself, it will collect the soft reference in the next cycle of Garbage collection.
如果垃圾收集器本身在第一个生命周期收集弱引用,它将在下一个垃圾收集周期收集软引用。
Strong Reference:: Its just opposite to the above two kind of references . They are less like to get garbage collected (Mostly they are never collected.)
强引用:与上面两种引用正好相反。他们不太喜欢收集垃圾(大多数情况下他们从不收集。)
You can refer to the following link for more info :
您可以参考以下链接了解更多信息:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
回答by Muhammad Nabeel Arif
The simple difference between SoftReference
and WeakReference
is provided by Android Developer.
SoftReference
和之间的简单区别WeakReference
由Android Developer提供。
The difference between a SoftReference
and a WeakReference
is the point of time at which the decision is made to clear and enqueue the reference:
aSoftReference
和 a之间的区别WeakReference
是决定清除和排队引用的时间点:
A
SoftReference
should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.A
WeakReference
may be cleared and enqueued as soon as is known to be weakly-referenced.
A
SoftReference
应该尽可能晚地清除和入队,也就是说,以防 VM 面临内存不足的危险。阿
WeakReference
可以被清除并尽快已知是弱引用的排队。
回答by Punith Raj
Weak Reference :
弱参考:
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself.
简而言之,弱引用是一种引用强度不足以强制对象保留在内存中的引用。弱引用允许您利用垃圾收集器的能力来确定您的可达性,因此您不必自己做。
Soft Reference :
软参考:
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
软引用与弱引用完全一样,只是它不太急于丢弃它所引用的对象。一个只有弱可达的对象(对它的最强引用是 WeakReferences)将在下一个垃圾收集周期被丢弃,但一个软可达的对象通常会停留一段时间。
Phantom Reference :
幻影参考:
A phantom reference is quite different than either SoftReference or WeakReference. Its grip on its object is so tenuous that you can't even retrieve the object -- its get() method always returns null. The only use for such a reference is keeping track of when it gets enqueued into a ReferenceQueue, as at that point you know the object to which it pointed is dead.
幻像引用与 SoftReference 或 WeakReference 完全不同。它对其对象的控制是如此脆弱,以至于您甚至无法检索该对象——它的 get() 方法总是返回 null。此类引用的唯一用途是跟踪它何时进入 ReferenceQueue,因为此时您知道它指向的对象已死亡。
This text was extracted from: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
本文摘自:https: //weblogs.java.net/blog/2006/05/04/understanding-weak-references
回答by Paolo Maresca
Java provides two different types/classes of Reference Objects: strongand weak. Weak Reference Objects can be further divided into softand phantom.
Java 提供了两种不同类型/类的引用对象:强和弱。弱引用的对象可以被进一步划分成软和幻象。
- Strong
- Weak
- soft
- phantom
- 强的
- 虚弱的
- 柔软的
- 幻影
Let's go point by point.
让我们逐点进行。
Strong Reference Object
强引用对象
StringBuilder builder = new StringBuilder();
This is the default type/class of Reference Object, if not differently specified: builder
is a strong Reference Object. This kind of reference makes the referenced object not eligible for GC. That is, whenever an object is referenced by a chain of strong Reference Objects, it cannot be garbage collected.
这是引用对象的默认类型/类,如果没有不同地指定:builder
是强引用对象。这种引用使得被引用的对象不符合 GC 的条件。也就是说,每当一个对象被一个强引用对象链引用时,它就不能被垃圾回收。
Weak Reference Object
弱引用对象
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Weak Reference Objects are not the default type/class of Reference Object and to be used they should be explicitly specified like in the above example. This kind of reference makes the reference object eligible for GC. That is, in case the only reference reachable for the StringBuilder
object in memory is, actually, the weak reference, then the GC is allowed to garbage collect the StringBuilder
object. When an object in memory is reachable only by Weak Reference Objects, it becomes automatically eligible for GC.
弱引用对象不是引用对象的默认类型/类,要使用它们应该像上面的例子一样明确指定。这种引用使引用对象有资格进行 GC。也就是说,如果StringBuilder
内存中对象的唯一可访问引用实际上是弱引用,则允许 GC 对StringBuilder
对象进行垃圾回收。当内存中的对象只能通过弱引用对象访问时,它会自动符合 GC 的条件。
Levels of Weakness
弱点
Two different levels of weakness can be enlisted: softand phantom.
两个不同层次的弱点才能登记:柔软和幻象。
A softReference Object is basically a weak Reference Object that remains in memory a bit more: normally, it resists GC cycle until no memory is available and there is risk of OutOfMemoryError
(in that case, it can be removed).
一个柔软的参考对象基本上是一个弱引用对象保留在内存多一点:通常情况下,它抵抗GC循环,直到没有可用的内存和存在的风险OutOfMemoryError
(在这种情况下,它可以被删除)。
On the other hand, a phantomReference Object is useful only to know exactly when an object has been effectively removed from memory: normally they are used to fix weird finalize() revival/resurrection behavior, since they actually do not return the object itself but only help in keeping track of their memory presence.
另一方面,幻影引用对象仅用于准确知道对象何时从内存中有效删除:通常它们用于修复奇怪的 finalize() revival/resurrection 行为,因为它们实际上不返回对象本身而是只有助于跟踪他们的记忆存在。
Weak Reference Objects are ideal to implement cache modules. In fact, a sort of automatic eviction can be implemented by allowing the GC to clean up memory areas whenever objects/values are no longer reachable by strong references chain. An example is the WeakHashMapretaining weak keys.
弱引用对象是实现缓存模块的理想选择。事实上,当强引用链不再能够访问对象/值时,可以通过允许 GC 清理内存区域来实现一种自动驱逐。一个例子是WeakHashMap保留弱键。
回答by Preetham R U
4 degrees of reference - Strong, Weak, Soft, Phantom
4 度参考 - Strong, Weak, Soft, Phantom
Strong - is a kind of reference, which makes the referenced object not eligible for GC. builder classes. eg - StringBuilder
Weak - is a reference which is eligible for GC.
Soft - is a kind of reference whose object is eligible for GC until memory is avaiable. Best for image cache. It will hold them till the memory is available.
Phantom - is a kind of reference whose object is directly eligible for GC. Used only to know when an object is removed from memory.
强 - 是一种引用,它使得被引用的对象不符合 GC 的条件。建设者类。例如 - StringBuilder
弱 - 是符合 GC 条件的参考。
软 - 是一种引用,其对象在内存可用之前有资格进行 GC。最适合图像缓存。它将保留它们直到内存可用。
Phantom - 是一种引用,其对象直接符合 GC 条件。仅用于知道何时从内存中删除对象。
uses:
用途:
Allows you to identify when an object is exactly removed from memory.
when
finalize()
method is overloaded, then GC might not happen in timely fashion for GC eligible objects of the two classes. So phantom reference makes them eligible for GC beforefinalize()
, is why you can get OutOfMemoryErrorseven when most of the heap is garbage.
允许您确定对象何时从内存中完全删除。
当
finalize()
方法重载时,对于两个类的符合 GC 条件的对象,GC 可能不会及时发生。因此,幻像引用使它们有资格在 GC 之前进行finalize()
,这就是为什么即使大多数堆是垃圾,您也会得到OutOfMemoryErrors 的原因。
Weak references are ideal to implement the cache modules.
弱引用是实现缓存模块的理想选择。
回答by Naresh Joshi
Strong References
强引用
These are your regular object references which we code daily:
这些是我们每天编码的常规对象引用:
Employee emp = new Employee();
The variable “emp” holds a strong reference to an Employee object and objects that are reachable through any chain of strong references are not eligible for garbage collection. Usually, this is what you want but not always. Now suppose we are fetching lots of employees from database in a collection or map, and we need to do a lot of processing on them regularly, So in order keep performance we will keep them in the cache.
变量“emp”持有对 Employee 对象的强引用,并且可以通过任何强引用链访问的对象不符合垃圾收集条件。通常,这是您想要的,但并非总是如此。现在假设我们要从数据库中的集合或地图中获取大量员工,并且我们需要定期对他们进行大量处理,因此为了保持性能,我们会将它们保存在缓存中。
As far as this is good but now we need different data and we don't need those Employee objects and these are not referenced from anywhere except the cache. Which is causing a memory leak because these objects are not in use but still not eligible for the garbage collection and we cannot remove those objects from cache because we don't have reference to them? So here either we need to empty the entire cache manually which is tedious or we could use other kind references e.g. Weak References.
就这点而言是好的,但现在我们需要不同的数据,我们不需要那些 Employee 对象,而且除了缓存之外,它们不会从任何地方引用。哪个会导致内存泄漏,因为这些对象未被使用但仍然不符合垃圾收集条件,并且我们无法从缓存中删除这些对象,因为我们没有对它们的引用?所以这里要么我们需要手动清空整个缓存,这很乏味,要么我们可以使用其他类型的引用,例如弱引用。
Weak References
弱引用
A weak reference does not pin an object into memory and will be GC'd in next GC cycle if not referenced from other references. We can use WeakReference class which is provided by Java to create above kind of caches, which will not store objects which are not referenced from somewhere else.
弱引用不会将对象固定到内存中,如果没有被其他引用引用,则将在下一个 GC 周期中进行 GC。我们可以使用 Java 提供的 WeakReference 类来创建上述类型的缓存,这些缓存不会存储未从其他地方引用的对象。
WeakReference<Cache> cache = new WeakReference<Cache>(data);
To access data you need to call cache.get(). This call to get may return null if the weak reference was garbage collected: you must check the returned value to avoid NPEs. Java provides collections that use weak references e.g., the WeakHashMap class stores keys (not values) as weak references. If the key is GC'd then the value will automatically be removed from the map too.
要访问数据,您需要调用 cache.get()。如果弱引用被垃圾收集,则对 get 的调用可能返回 null:您必须检查返回的值以避免 NPE。Java 提供了使用弱引用的集合,例如, WeakHashMap 类将键(而不是值)存储为弱引用。如果键是 GC 的,那么该值也将自动从地图中删除。
Since weak references are objects too we need a way to clean them up (they're no longer useful when the object they were referencing has been GC'd). If you pass a ReferenceQueue into the constructor for a weak reference then the garbage collector will append that weak reference to the ReferenceQueue before they're finalized or GC'd. You can periodically process this queue and deal with dead references.
由于弱引用也是对象,我们需要一种方法来清理它们(当它们引用的对象已被 GC 处理时,它们不再有用)。如果您将 ReferenceQueue 传递给弱引用的构造函数,那么垃圾收集器将在最终确定或 GC 之前将该弱引用附加到 ReferenceQueue。您可以定期处理此队列并处理死引用。
Soft References
软引用
A SoftReference is like a WeakReference but it is less likely to be garbage collected. Soft references are cleared at the discretion of the garbage collector in response to memory demand. The virtual machine guarantees that all soft references to softly reachable objects will have been cleared before it would ever throw an OutOfMemoryError.
SoftReference 类似于 WeakReference,但它不太可能被垃圾收集。软引用由垃圾收集器根据内存需求自行决定清除。虚拟机保证在抛出 OutOfMemoryError 之前,对软可访问对象的所有软引用都已被清除。
Phantom References
幻影参考
Phantom references are the weakest of all reference types, calling get on them will always return null. An object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed, As opposed to weak references which are enqueued before they're finalized or GC'd Phantom references are rarely used.
幻像引用是所有引用类型中最弱的,对它们调用 get 将始终返回 null。一个对象在它被终结之后被虚引用,但在其分配的内存被回收之前,与弱引用相反,弱引用在它们被终结或 GC 的虚引用很少使用之前排队。
So how are they useful? When you construct a phantom reference you must always pass in a ReferenceQueue. This indicates that you can use a phantom reference to see when your object is GC'd.
那么它们有什么用呢?当您构造一个幻像引用时,您必须始终传入一个 ReferenceQueue。这表明您可以使用幻像引用来查看您的对象何时被 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.
嘿,所以如果弱引用在被认为是 finalize 但尚未被 GC 时被排队,我们可以在终结器块中创建一个对对象的新强引用,并防止对象被 GC 处理。是的,你可以,但你可能不应该这样做。为了检查这种情况,每个对象的 GC 循环将至少发生两次,除非该对象只能通过幻像引用访问。这就是为什么即使您的内存包含大量垃圾,您也可能会耗尽堆。幻像引用可以防止这种情况。
You can read more on my article Types of References in Java(Strong, Soft, Weak, Phantom).
您可以在我的文章Java 中的引用类型(强、软、弱、幻影)中阅读更多内容。
回答by Lavish Kothari
This articlecan be super helpful to understand strong, soft, weak and phantom references.
这篇文章对于理解强引用、软引用、弱引用和幻像引用非常有帮助。
To give you a summary,
给你一个总结,
If you have a strong referenceto an object, then the object can never be collected/reclaimed by GC (Garbage Collector).
如果您对某个对象有一个强引用,则该对象永远不会被 GC(垃圾收集器)收集/回收。
If you only have weak referencesto an object (with no strong references), then the object will be reclaimed by GC in the very next GC cycle.
如果您只有对对象的弱引用(没有强引用),那么该对象将在下一个 GC 循环中被 GC 回收。
If you only have soft referencesto an object (with no strong references), then the object will be reclaimed by GC only when JVM runs out of memory.
如果您只有一个对象的软引用(没有强引用),那么只有当 JVM 内存不足时,GC 才会回收该对象。
We create phantom referencesto an object to keep track of when the object gets enqueued into the ReferenceQueue
. Once you know that you can perform fine-grained finalization. (This would save you from accidentally resurrecting the object as phantom-reference don't give you the referrant). I'd suggest you reading thisarticle to get in-depth detail about this.
我们创建对对象的幻像引用,以跟踪对象何时进入ReferenceQueue
. 一旦你知道你可以执行细粒度的终结。(这可以避免您意外地复活对象,因为幻像引用不会给您提供引用者)。我建议你阅读这篇文章以深入了解这方面的细节。
So you can say that, strong references have ultimate power(can never be collected by GC)
所以你可以说,强引用拥有终极力量(永远不会被GC收集)
Soft references are powerfulthan weak references (as they can escape GC cycle until JVM runs out of memory)
软引用比弱引用更强大(因为它们可以逃避 GC 循环,直到 JVM 耗尽内存)
Weak references are even less powerfulthan soft references (as they cannot excape any GC cycle and will be reclaimed if object have no other strong reference).
弱引用甚至不如软引用强大(因为它们不能超越任何 GC 循环,并且如果对象没有其他强引用将被回收)。
Restaurant Analogy
餐厅类比
- Waiter - GC
- You - Object in heap
- Restaurant area/space - Heap space
- New Customer - New object that wants table in restaurant
- 服务员 - GC
- 你 - 堆中的对象
- 餐厅区/空间 - 堆空间
- 新客户 - 想要在餐厅用餐的新对象
Now if you are a strong customer(analogous to strong reference), then even if a new customer comes in the restaurant or what so ever happnes, you will never leave your table (the memory area on heap). The waiter has no right to tell you (or even request you) to leave the restaurant.
现在,如果你是一个强大的客户(类似于强引用),那么即使有新客户来到餐厅或发生了什么事情,你也永远不会离开你的桌子(堆上的内存区域)。服务员无权告诉您(甚至要求您)离开餐厅。
If you are a soft customer(analogous to soft reference), then if a new customer comes in the restaurant, the waiter will not ask you to leave the table unless there is no other empty table left to accomodate the new customer. (In other words the waiter will ask you to leave the table only if a new customer steps in and there is no other table left for this new customer)
如果您是软顾客(类似于软参考),那么如果餐厅有新顾客进来,除非没有其他空桌子可以容纳新顾客,否则服务员不会要求您离开餐桌。(换句话说,只有当有新顾客进来并且没有其他桌子留给这位新顾客时,服务员才会要求你离开桌子)
If you are a weak customer(analogous to weak reference), then waiter, at his will, can (at any point of time) ask you to leave the restaurant :P
如果您是弱顾客(类似于弱参考),那么服务员可以(在任何时间点)随意要求您离开餐厅:P