Java中的SoftReference和WeakReference有什么区别?

发布于 2024-07-09 05:58:59 字数 354 浏览 10 评论 0原文

java.lang.ref.WeakReferencejava.lang.ref.SoftReference

What's the difference between java.lang.ref.WeakReference and java.lang.ref.SoftReference ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

很酷又爱笑 2024-07-16 05:58:59

来自 了解弱引用,作者:Ethan Nicholas:

弱引用

弱引用,简单地说,是一个
参考不够有力
强制一个对象保留在内存中。
弱引用可以让你利用
垃圾收集器的能力
确定您的可达性,以便您
不必自己做。 你
创建一个弱引用,如下所示:

弱引用weakWidget = new WeakReference(widget); 
  

然后
您可以在代码的其他地方使用
weakWidget.get() 获取实际的
Widget 对象。 当然是弱者
参考不够强
防止垃圾收集,所以你可以
找到(如果没有强
对小部件的引用)
weakWidget.get() 突然启动
返回null

...

软引用

软引用
弱引用,除了它较少
急于扔掉该物体
它指的是哪个。 一个对象是
仅弱可达(最强
对它的引用是WeakReferences
将在下一个垃圾场被丢弃
收集周期,但是一个对象
通常是容易到达的
坚持一段时间。

SoftReferences 不是必需的
行为方式与
WeakReferences,但在实践中很温和
可到达的对象一般是
只要内存在就保留
货源充足。 这使他们成为
缓存的良好基础,例如
正如上面描述的图像缓存,
因为你可以让垃圾
收藏家既担心又如何
对象是可达的(强
可到达的对象将永远被删除
从缓存中)以及它的需求有多迫切
他们消耗的内存。

彼得·凯斯勒在评论中补充道:

Sun JRE 确实以不同于弱引用的方式对待软引用。 如果可用内存没有压力,我们会尝试保留 SoftReference 引用的对象。 一个细节:“-client”和“-server”JRE 的策略是不同的:-client JRE 尝试通过清除软引用而不是扩展堆来保持较小的占用空间,而 -server JRE 则尝试保持较小的占用空间通过扩展堆(如果可能)而不是清除软引用来提高性能。 一种尺寸并不适合所有情况。

From Understanding Weak References, by Ethan Nicholas:

Weak references

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. You
create a weak reference like this:

WeakReference weakWidget = new WeakReference(widget);

and then
elsewhere in the code you can use
weakWidget.get() to get the actual
Widget object. Of course the weak
reference isn't strong enough to
prevent garbage collection, so you may
find (if there are no strong
references to the widget) that
weakWidget.get() suddenly starts
returning null.

...

Soft references

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.

SoftReferences aren't required to
behave any differently than
WeakReferences, but in practice softly
reachable objects are generally
retained as long as memory is in
plentiful supply. This makes them an
excellent foundation for a cache, such
as the image cache described above,
since you can let the garbage
collector worry about both how
reachable the objects are (a strongly
reachable object will never be removed
from the cache) and how badly it needs
the memory they are consuming.

And Peter Kessler added in a comment:

The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.

乖乖公主 2024-07-16 05:58:59

弱引用被急切地收集。 如果GC发现一个对象是
弱可达(只能通过弱引用可达),它将清除
立即对该对象进行弱引用。 因此,它们适合
保留对程序也保留的对象的引用
(强烈引用)“关联信息”有些,例如缓存
有关类或对象的包装器等的反射信息。
任何在关联对象后面保留没有意义的内容
是 GC 编辑的。 当弱引用被清除时,它会被排入队列
您的代码在某处轮询的引用队列,并且它会丢弃
关联的对象也是如此。 也就是说,您保留有关某个的额外信息
对象,但是一旦它引用了对象,就不再需要该信息
消失了。 实际上,在某些情况下你甚至可以子类化
WeakReference 并保留有关对象的关联额外信息
在 WeakReference 子类的字段中。 另一个典型的用法是
WeakReference 与 Map 结合使用来保存规范实例。

另一方面,软引用非常适合缓存外部、可重新创建的资源
因为 GC 通常会延迟清除它们。 但可以保证的是,所有
SoftReferences 将在抛出 OutOfMemoryError 之前被清除,因此它们
理论上不会导致 OOME[*]。

典型的用例示例是保留来自 a 的内容的解析形式
文件。 您将实现一个系统,在其中加载文件、解析它并保留
对已解析表示的根对象的 SoftReference。 下次
如果您需要该文件,您将尝试通过 SoftReference 检索它。 如果
你可以检索它,这样你就可以避免再次加载/解析,并且如果 GC
在此期间清除它,然后重新加载它。 这样,您就可以免费使用
内存用于性能优化,但不要冒 OOME 的风险。

现在来说说[*]。 保留 SoftReference 本身不会导致 OOME。 如果
另一方面,您错误地使用 SoftReference 来执行弱引用的任务
要使用(即,您以某种方式保留与对象关联的信息
强引用,并在引用对象获取时丢弃它
清除),您可以在轮询 ReferenceQueue 的代码中遇到 OOME
并丢弃可能无法及时运行的关联对象
时尚。

所以,决定取决于使用情况
- 如果您正在缓存构建成本高昂的信息,但是
尽管如此,仍可从其他数据重建,请使用软引用
- 如果您保留对某些数据的规范实例的引用,或者
你想要引用一个对象而不“拥有”它(因此
防止它被 GC'd),使用弱引用。

Weak references are collected eagerly. If GC finds that an object is
weakly reachable (reachable only through weak references), it'll clear the
weak references to that object immediately. As such, they're good for
keeping a reference to an object for which your program also keeps
(strongly referenced) "associated information" somewere, like cached
reflection information about a class, or a wrapper for an object, etc.
Anything that makes no sense to keep after the object it is associated
with is GC-ed. When the weak reference gets cleared, it gets enqueued in a
reference queue that your code polls somewhere, and it discards the
associated objects as well. That is, you keep extra information about an
object, but that information is not needed once the object it refers to
goes away. Actually, in certain situations you can even subclass
WeakReference and keep the associated extra information about the object
in the fields of the WeakReference subclass. Another typical use of
WeakReference is in conjunction with Maps for keeping canonical instances.

SoftReferences on the other hand are good for caching external, recreatable resources
as the GC typically delays clearing them. It is guaranteed though that all
SoftReferences will get cleared before OutOfMemoryError is thrown, so they
theoretically can't cause an OOME[*].

Typical use case example is keeping a parsed form of a contents from a
file. You'd implement a system where you'd load a file, parse it, and keep
a SoftReference to the root object of the parsed representation. Next time
you need the file, you'll try to retrieve it through the SoftReference. If
you can retrieve it, you spared yourself another load/parse, and if the GC
cleared it in the meantime, you reload it. That way, you utilize free
memory for performance optimization, but don't risk an OOME.

Now for the [*]. Keeping a SoftReference can't cause an OOME in itself. If
on the other hand you mistakenly use SoftReference for a task a WeakReference is meant
to be used (namely, you keep information associated with an Object somehow
strongly referenced, and discard it when the Reference object gets
cleared), you can run into OOME as your code that polls the ReferenceQueue
and discards the associated objects might happen to not run in a timely
fashion.

So, the decision depends on usage
- if you're caching information that is expensive to construct, but
nonetheless reconstructible from other data, use soft references
- if you're keeping a reference to a canonical instance of some data, or
you want to have a reference to an object without "owning" it (thus
preventing it from being GC'd), use a weak reference.

拿命拼未来 2024-07-16 05:58:59

在Java中; 从最强到最弱的顺序,有:Strong、Soft、Weak 和 Phantom。

强引用是普通引用,可以保护所引用的对象不被 GC 回收。 即从不收集垃圾。

软引用可以被垃圾收集器收集,但在需要其内存之前可能不会被收集。 即在 OutOfMemoryError 之前进行垃圾收集。

弱引用是一种不能保护所引用对象不被 GC 回收的引用。 即当没有强或软引用时垃圾收集。

幻像引用是指在对象完成后、分配的内存被回收之前被幻像引用的对象的引用。

来源

类比: 假设 JVM 是一个王国,Object 是一个国王GC是王国的攻击者,试图杀死国王(对象)。

  • 当King时,GC无法杀死他。
  • 当King时,GC会攻击他,但King会在资源可用之前通过保护统治王国。
  • 当国王时,GC会攻击他,但在没有保护的情况下统治王国。
  • 当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得。

In Java; order from strongest to weakest, there are: Strong, Soft, Weak and Phantom

A Strong reference is a normal reference that protects the referred object from collection by GC. i.e. Never garbage collects.

A Soft reference is eligible for collection by garbage collector, but probably won't be collected until its memory is needed. i.e. garbage collects before OutOfMemoryError.

A Weak reference is a reference that does not protect a referenced object from collection by GC. i.e. garbage collects when no Strong or Soft refs.

A Phantom reference is a reference to an object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed.

Source

Analogy: Assume a JVM is a kingdom, Object is a king of the kingdom, and GC is an attacker of the kingdom who tries to kill the king(object).

  • When King is Strong, GC can not kill him.
  • When King is Soft, GC attacks him but King rule the kingdom with protection until resource are available.
  • When King is Weak, GC attacks him but rule the kingdom without protection.
  • When king is Phantom, GC already killed him but king is available via his soul.
烂人 2024-07-16 05:58:59

弱引用
http://docs.oracle.com/javase/1.5。 0/docs/api/java/lang/ref/WeakReference.html

原理: 弱引用与垃圾回收有关。 通常,具有一个或多个引用的对象不符合垃圾回收的条件。
当是弱引用时,上述原则不适用。 如果一个对象与其他对象只有弱引用,那么它就准备好进行垃圾回收。

让我们看下面的示例:我们有一个带有对象的 Map,其中 Key 是对象的引用。

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

现在,在程序执行期间我们已经设置了emp = null。 持有密钥的 Map 在这里没有任何意义,因为它是 null。 在上述情况下,该对象不会被垃圾回收。

WeakHashMap

WeakHashMap 是一种当不再可能从索引中检索条目(键到值映射)时将被删除的映射。 地图

让我用 WeakHashMap 来展示上面的示例

import java.util.WeakHashMap;

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

输出: 对 System.gc() 进行了 20 次调用,得到 aMap 大小< /code> of : 0.

WeakHashMap 仅具有对键的弱引用,而不是像其他 Map 类那样的强引用。 尽管您使用了 WeakHashMap,但在某些情况下,当值或键被强引用时,您必须小心。 通过将对象包装在 WeakReference 中可以避免这种情况。

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

软引用。

软引用比弱引用稍强。 软引用允许垃圾收集,但只有在没有其他选择的情况下才会请求垃圾收集器清除它。

垃圾收集器不会像处理弱可到达对象那样主动收集软可到达对象,而是仅在确实“需要”内存时收集软可到达对象。 软引用是对垃圾收集器说的一种方式,“只要内存不太紧张,我就想保留这个对象。但是如果内存变得非常紧张,请继续收集它,我会处理接着就,随即。” 垃圾收集器需要清除所有软引用,然后才能抛出 OutOfMemoryError

Weak Reference
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Principle: weak reference is related to garbage collection. Normally, object having one or more reference will not be eligible for garbage collection.
The above principle is not applicable when it is weak reference. If an object has only weak reference with other objects, then its ready for garbage collection.

Let's look at the below example: We have an Map with Objects where Key is reference a object.

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

Now, during the execution of the program we have made emp = null. The Map holding the key makes no sense here as it is null. In the above situation, the object is not garbage collected.

WeakHashMap

WeakHashMap is one where the entries (key-to-value mappings) will be removed when it is no longer possible to retrieve them from the Map.

Let me show the above example same with WeakHashMap

import java.util.WeakHashMap;

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

Output: Took 20 calls to System.gc() to result in aMap size of : 0.

WeakHashMap has only weak references to the keys, not strong references like other Map classes. There are situations which you have to take care when the value or key is strongly referenced though you have used WeakHashMap. This can avoided by wrapping the object in a WeakReference.

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

Soft References.

Soft Reference is slightly stronger that weak reference. Soft reference allows for garbage collection, but begs the garbage collector to clear it only if there is no other option.

The garbage collector does not aggressively collect softly reachable objects the way it does with weakly reachable ones -- instead it only collects softly reachable objects if it really "needs" the memory. Soft references are a way of saying to the garbage collector, "As long as memory isn't too tight, I'd like to keep this object around. But if memory gets really tight, go ahead and collect it and I'll deal with that." The garbage collector is required to clear all soft references before it can throw OutOfMemoryError.

°如果伤别离去 2024-07-16 05:58:59

软引用和弱引用之间唯一真正的区别是

垃圾收集器使用算法来决定是否
回收一个软可达对象,但总是回收一个弱可达对象
可到达的对象。

The only real difference between a soft reference and a weak reference is that

the garbage collector uses algorithms to decide whether or not to
reclaim a softly reachable object, but always reclaims a weakly
reachable object.

我也只是我 2024-07-16 05:58:59

SoftReference 专为缓存而设计。 当发现WeakReference引用了一个原本无法访问的对象时,它将立即被清除。 SoftReference 可以保留原样。 通常有一些与可用内存量和上次使用时间相关的算法来确定是否应该清除它。 当前的 Sun 算法是,如果在 Java 堆上有兆字节的空闲内存(可配置,服务器 HotSpot 检查由 -Xmx)。 SoftReference 将在抛出 OutOfMemoryError 之前被清除,除非可以访问。

SoftReference is designed for caches. When it is found that a WeakReference references an otherwise unreachable object, then it will get cleared immediately. SoftReference may be left as is. Typically there is some algorithm relating to the amount of free memory and the time last used to determine whether it should be cleared. The current Sun algorithm is to clear the reference if it has not been used in as many seconds as there are megabytes of memory free on the Java heap (configurable, server HotSpot checks against maximum possible heap as set by -Xmx). SoftReferences will be cleared before OutOfMemoryError is thrown, unless otherwise reachable.

蓝颜夕 2024-07-16 05:58:59

这篇文章对于理解强、软引用、弱引用和幻像引用。


总结一下,

如果对某个对象只有弱引用(没有强引用),那么该对象将在下一个 GC 周期中被 GC 回收。

如果对某个对象只有软引用(没有强引用),那么只有当 JVM 内存不足时,该对象才会被 GC 回收。


所以你可以说,强引用拥有终极力量(永远不会被GC收集)

软引用比弱引用更强大(因为它们可以逃避GC循环,直到JVM运行内存不足)

弱引用甚至不如软引用强大(因为它们无法避免任何GC周期,并且如果对象没有其他强引用,它们将被回收)。


餐厅类比

  • 服务员 - GC
  • 你 - 堆中的对象
  • 餐厅区域/空间 - 堆空间
  • 新顾客 - 想要餐厅餐桌的新对象

现在,如果您是一个强顾客(类似到强引用),那么即使有新顾客进入餐厅或发生任何事情,您也永远不会离开您的桌子(堆上的内存区域)。 服务员无权告诉你(甚至要求你)离开餐厅。

如果你是一个软顾客(类似于软引用),那么如果有新顾客来到餐厅,服务员不会要求你离开桌子,除非没有其他空桌子可以容纳新客户。 (换句话说,只有当新顾客进来并且没有其他桌子可供该新顾客离开时,服务员才会要求您离开桌子)

如果您是弱顾客(类似于弱引用) ),然后服务员可以(在任何时间)随意要求您离开餐厅:P

This article can be super helpful to understand strong, soft, weak and phantom references.


To give you a summary,

If you only have weak references to an object (with no strong references), then the object will be reclaimed by GC in the very next GC cycle.

If you only have soft references to an object (with no strong references), then the object will be reclaimed by GC only when JVM runs out of memory.


So you can say that, strong references have ultimate power (can never be collected by GC)

Soft references are powerful than weak references (as they can escape GC cycle until JVM runs out of memory)

Weak references are even less powerful than soft references (as they cannot excape any GC cycle and will be reclaimed if object have no other strong reference).


Restaurant Analogy

  • Waiter - GC
  • You - Object in heap
  • Restaurant area/space - Heap space
  • New Customer - New object that wants table in restaurant

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

生生漫 2024-07-16 05:58:59

Java中对象可达性状态的六种类型:

  1. 可达对象 - GC不会收集(回收所占用的内存)这种目的。 这些是通过根节点或另一个强可达对象可达的(即通过局部变量、类变量、实例变量等)
  2. 可达对象 - GC 可能会尝试根据内存争用来收集此类对象。 这些可以通过一个或多个软引用对象从根到达
  3. 可到达对象 - GC必须收集这种对象。 这些
    可以通过一个或多个弱引用对象
  4. 可复活对象从根到达 - GC 已经在收集这些对象了。 但是它们可能会通过执行某些幻像可达对象的终结器返回到其中一种状态 - 强/软/弱
  5. - GC 已经在该过程中收集这些对象并确定不能由任何终结器复活(如果它本身声明了 Finalize() 方法,则其终结器将被运行)。 这些可以通过一个或多个幻像引用对象从根到达。
  6. 无法到达对象 - 对象既不是强、弱、弱也不是幻像可达,并且不可复活。 这些对象已准备好回收

有关更多详细信息:https://www.artima.com/insidejvm /ed2/gc16.html « 崩溃

The six types of object reachability states in Java:

  1. Strongly reachable objects - GC will not collect (reclaim the memory occupied by) this kind of object. These are reachable via a root node or another strongly reachable object (i.e. via local variables, class variables, instance variables, etc.)
  2. Softly reachable objects - GC may attempt to collect this kind of object depending on memory contention. These are reachable from the root via one or more soft reference objects
  3. Weakly reachable objects - GC must collect this kind of object. These
    are reachable from the root via one or more weak reference objects
  4. Resurrect-able objects - GC is already in the process of collecting these objects. But they may go back to one of the states - Strong/Soft/Weak by the execution of some finalizer
  5. Phantomly reachable object - GC is already in the process of collecting these objects and has determined to not be resurrect-able by any finalizer (if it declares a finalize() method itself, then its finalizer will have been run). These are reachable from the root via one or more phantom reference objects
  6. Unreachable object - An object is neither strongly, softly, weakly, nor phantom reachable, and is not resurrectable. These objects are ready for reclamation

For more details: https://www.artima.com/insidejvm/ed2/gc16.html « collapse

离笑几人歌 2024-07-16 05:58:59

唯一真正的区别

根据文档 ,松散的弱引用必须由正在运行的 GC 清除。

根据文档,在 OOM 之前必须清除松散软引用抛出。

这是唯一真正的区别。 其他一切都不属于合同的一部分。 (我假设最新的文档是合同性的。)

软引用很有用。内存敏感的缓存使用软引用,而不是弱引用。


The only proper use of WeakReference is to observe the GC run. You do this by creating a new WeakReference whose object immediately goes out of scope, then try to get null out of weak_ref.get(). When it's null, you learn that between this duration, the GC ran.

至于弱引用的不正确使用,这个列表是无穷无尽的:

  • 一个糟糕的黑客来实现优先级2软引用,这样你就不必编写一个,它无法按预期工作,因为即使有空闲内存,每次 GC 运行时都会清除缓存。 请参阅 https://stackoverflow.com/a/3243242/632951 了解 phails。 (此外,如果您需要 2 级以上的缓存优先级怎么办?您仍然需要一个真正的库。)

  • 将数据与现有类的对象关联起来的糟糕黑客,但是< /strong> 当你的 GC 在创建弱引用后决定休息一下时,它会产生内存泄漏(OutOfMemoryError)。 此外,它非常丑陋:更好的方法是使用元组。

  • 将数据与现有类的对象关联起来的糟糕黑客,其中该类有勇气使自己不可子类化,并在您需要调用的现有函数代码中使用。 在这种情况下,正确的解决方案是编辑类并使其可子类化,或者编辑函数并使其采用接口而不是类,或者使用替代函数。

The Only Real Difference

Per the doc, loose WeakReferences must be cleared by a running GC.

Per the doc, loose SoftReferences must be cleared before OOM is thrown.

That's the only real difference. Everything else is not part of the contract. (I'll assume the latest docs are contractual.)

SoftReferences are useful. Memory-sensitive caches use SoftReferences, not WeakReferences.


The only proper use of WeakReference is to observe the GC run. You do this by creating a new WeakReference whose object immediately goes out of scope, then try to get null out of weak_ref.get(). When it's null, you learn that between this duration, the GC ran.

As for incorrect use of WeakReference, the list is endless:

  • a lousy hack to implement priority-2 softreference such that you don't have to write one, yet it doesn't work as expected because the cache would be cleared on every GC run, even when there is spare memory. See https://stackoverflow.com/a/3243242/632951 for phails. (Besides, what if you need more than 2 levels of cache priority? You'd still gotta need a real library for it.)

  • a lousy hack to associate data with an object of an existing class, yet it creates a memory leak (OutOfMemoryError) when your GC decides to take a break after your weakreferences are created. Besides, it's beyond ugly: A better approach is to use tuples.

  • a lousy hack to associate data with an object of an existing class, where the class has the nerve to make itself non-subclassable, and is used in an existing function code which you need to call. In such a case, the proper solution is to either edit the class and make it subclassable, or edit the function and make it take an interface instead of a class, or use an alternative function.

稍尽春風 2024-07-16 05:58:59

为了给出实际内存使用情况,我做了一个关于强、软、弱和弱的实验。 通过将重对象保留到程序结束,在重负载下使用重对象进行幻像引用。 然后监控堆的使用情况& GC 行为。 这些指标可能会因具体情况而异,但肯定能提供高层次的理解。 以下是调查结果。

堆和 重负载下的 GC 行为

  • 强/硬引用 - 随着程序继续,JVM 无法收集保留的强引用对象。 最终出现“java.lang.OutOfMemoryError: Java heap space”
  • 软引用 - 随着程序继续,堆使用量不断增长,但在接近最大堆时发生了 OLD gen GC。 GC 在启动程序后开始的时间稍晚一些。
  • 弱引用 - 当程序启动时,对象开始完成并完成。 几乎立即被收集。 大多数对象是在年轻代垃圾收集中收集的。
  • 幻像引用 - 与弱引用类似,幻像引用的对象也开始最终确定和确定。 垃圾立即收集。 没有老年代GC和GC。 所有对象都在年轻代垃圾收集本身中被收集。

您可以更深入地了解 此实验的图表、统计数据、观察结果

To give an in-action memory usage aspect, I did an experiment with Strong, Soft, Weak & Phantom references under heavy load with heavy objects by retaining them till end of program. Then monitored heap usage & GC behavior. These metrics may vary case by case basis but surely gives high level understanding. Below are findings.

Heap & GC Behavior under heavy load

  • Strong/Hard Reference - As program continued, JVM couldn't collect retained strong referenced object. Eventually ended up in "java.lang.OutOfMemoryError: Java heap space"
  • Soft Reference - As program continued, heap usage kept growing, but OLD gen GC happened hen it was nearing max heap. GC started bit later in time after starting program.
  • Weak Reference - As program started, objects started finalizing & getting collected almost immediately. Mostly objects got collected in young generation garbage collection.
  • Phantom Reference - Similar to weak reference, phantom referenced objects also started getting finalized & garbage collected immediately. There were no old generation GC & all objects were getting collected in young generation garbage collection itself.

You can get more in depth graphs, stats, observations for this experiment here.

远山浅 2024-07-16 05:58:59

人们应该意识到,弱引用对象只有在只有弱引用时才会被收集。 如果它只有一个强引用,那么无论它有多少个弱引用,它都不会被收集。

One should be aware that a weakly referenced object will only get collected when it has ONLY weak reference(s). If it has so much as one strong reference, it does not get collected no matter how many weak references it has.

ぃ弥猫深巷。 2024-07-16 05:58:59

WeakReference:仅弱引用的对象在每个 GC 周期(次要或完整)时被收集。

SoftReference:仅软引用的对象何时被收集取决于:

  1. -XX:SoftRefLRUPolicyMSPerMB=N 标志(默认值为 1000,即 1 秒)

  2. 堆中的可用内存量。

    示例:

    • 堆有 10MB 的可用空间(完整 GC 后);
    • -XX:SoftRefLRUPolicyMSPerMB=1000

    如果最后一次访问该对象的时间超过 10 秒,则仅由 SoftReference 引用的对象将被收集。

WeakReference: objects that are only weakly referenced are collected at every GC cycle (minor or full).

SoftReference: when objects that are only softly referenced are collected depends on:

  1. -XX:SoftRefLRUPolicyMSPerMB=N flag (default value is 1000, aka 1 second)

  2. Amount of free memory in the heap.

    Example:

    • heap has 10MB of free space (after full GC);
    • -XX:SoftRefLRUPolicyMSPerMB=1000

    Then object which is referenced only by SoftReference will be collected if last time when it was accessed is greater then 10 seconds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文