什么';Java中SoftReference和WeakReference的区别是什么?

什么';Java中SoftReference和WeakReference的区别是什么?,java,reference,weak-references,soft-references,Java,Reference,Weak References,Soft References,和之间有什么区别?弱参考文献被急切地收集起来。如果GC发现一个对象是 弱可达(仅通过弱引用可达),它将清除 立即对该对象的弱引用。就其本身而言,它们是有益的 保留对程序也为其保留的对象的引用 (强烈引用)“关联信息”有些是缓存的 关于类或对象包装器等的反射信息。 在关联对象之后保留任何没有意义的内容 with是GC-ed。当弱引用被清除时,它将以 代码在某处轮询的引用队列,它将丢弃 以及关联的对象。也就是说,您保留了有关 对象,但一旦该对象引用,就不需要该信息 他走了。实际上,在某些情况下,您甚

和之间有什么区别?

弱参考文献被急切地收集起来。如果GC发现一个对象是 弱可达(仅通过弱引用可达),它将清除 立即对该对象的弱引用。就其本身而言,它们是有益的 保留对程序也为其保留的对象的引用 (强烈引用)“关联信息”有些是缓存的 关于类或对象包装器等的反射信息。 在关联对象之后保留任何没有意义的内容 with是GC-ed。当弱引用被清除时,它将以 代码在某处轮询的引用队列,它将丢弃 以及关联的对象。也就是说,您保留了有关 对象,但一旦该对象引用,就不需要该信息 他走了。实际上,在某些情况下,您甚至可以将 WeakReference并保留与对象相关的额外信息 在WeakReference子类的字段中。另一个典型用法是 WeakReference与映射一起用于保存规范实例

另一方面,软引用有利于缓存外部的可重新创建的资源 因为GC通常会延迟清除它们。尽管如此,这一切都是可以保证的 SoftReferences将在抛出OutOfMemoryError之前清除,因此 理论上不会导致OOME[*]

典型的用例示例是将内容的解析形式保留在 文件您将实现一个系统,在该系统中加载文件、解析文件并保持 对已解析表示的根对象的软引用。下次 如果您需要该文件,请尝试通过SoftReference检索它。如果 您可以检索它,为自己节省另一个加载/解析,如果GC 同时清除它,你重新加载它。那样的话,你就可以免费使用了 内存用于性能优化,但不要冒OOME的风险

现在来看[*]。保存软引用本身不会导致OOME。如果 另一方面,您错误地将SoftReference用于任务,这意味着WeakReference 要使用(即,您以某种方式保留与对象关联的信息) 强引用,并在引用对象 清除),您可以将OOME作为轮询引用队列的代码运行 和丢弃关联的对象可能不会及时运行 时尚

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

SoftReference
是为缓存设计的。当发现
WeakReference
引用了无法访问的对象时,它将立即被清除<代码>软参考可以保持原样。通常,有一些算法与空闲内存量和上次用于确定是否应清除内存的时间有关。当前的Sun算法是,如果在Java堆上有兆字节的可用内存(可配置,服务器热点根据
-Xmx
设置的最大可能堆进行检查),则清除引用<代码>软引用s将在抛出
OutOfMemoryError
之前被清除,除非可以访问。

来自,作者:Ethan Nicholas:

弱引用

简单地说,弱引用是 引用的强度不足以 强制对象保留在内存中。 弱引用允许您利用 垃圾收集器执行以下操作的能力: 为您确定可达性,以便 不必自己动手。你 创建一个弱引用,如下所示:

WeakReference weakWidget = new WeakReference(widget);
然后 在代码的其他地方可以使用
weakWidget.get()
获取实际的
小部件
对象。当然是弱者 引用不够强,无法 防止垃圾收集,以便 发现(如果没有强大的 对小部件的引用)
weakWidget.get()
突然启动 返回
null

软引用

软引用与 弱引用,只是它的引用较少 迫不及待地想把东西扔掉 它所指的。一个物体 仅弱可达(最强 对它的引用是
WeakReferences
) 将在下一次垃圾处理时丢弃 收集周期,但对象 是软可及的,通常 呆一会儿

SoftReferences
不需要 行为举止有什么不同
WeakReferences
,但在实际操作中 可达对象通常是 只要内存在,就会被保留 供应充足。这使他们成为一个 高速缓存的良好基础 如上所述的图像缓存, 既然你可以让垃圾 收藏家们担心这两个问题 可到达的对象是(强 永远不会删除可访问对象 (从缓存中)以及它需要的程度 他们正在消耗的内存

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

Sun JRE对待软引用的方式与处理软引用的方式不同。如果可用内存没有压力,我们尝试保留SoftReference引用的对象。一个细节:“-client”和“-server”JRE的策略是不同的:“-client”JRE试图通过清除软引用而不是扩展堆来保持较小的占用空间,“-server”JRE试图通过扩展堆(如果可能)而不是清除软引用来保持较高的性能。一个尺码不适合所有人


软引用和弱引用之间唯一的真正区别
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());

    }
}
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());
    }
}
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");
    }
}