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

2019-05-10 12:36发布

什么之间的区别java.lang.ref.WeakReferencejava.lang.ref.SoftReference

Answer 1:

从认识弱引用 ,由伊桑·尼古拉斯:

弱引用

弱引用 ,简单地说,是不是强大到足以迫使对象保留在内存中的参考。 弱引用允许你利用垃圾收集器的,以确定您的可达性的能力,所以你不必自己做。 您创建一个弱引用是这样的:

 WeakReference weakWidget = new WeakReference(widget); 

然后在代码的其他地方,你可以使用weakWidget.get()获取实际Widget对象。 当然,弱引用是没有强大到足以防止垃圾收集,所以你会发现(如果有到窗口小部件不强引用)是weakWidget.get()突然开始返回null

...

软引用

软参考酷似弱引用,不同之处在于它是更少急于扔掉其所引用的对象。 这仅仅是弱可及的对象(它最强的引用WeakReferences )将在下次垃圾收集周期被丢弃,而是一个对象,它是软可到达一般会坚持一段时间了。

SoftReferences要求任何行为不同于WeakReferences ,但在实践中轻轻地可达对象一般保留,只要内存供应充足。 这使得他们一个很好的基础,为高速缓存,如上面所描述的,因为你可以让有关双方如何到达的对象(强烈可达的对象将永远不会被从缓存中删除)垃圾收集担心图像缓存,以及如何不好它需要他们消耗的内存。

和彼得·凯斯勒加入评论:

太阳JRE并从在WeakReferences区别对待SoftReferences。 我们试图举行反对由一个SoftReference的引用,如果没有可用的内存压力。 一个细节:为“-client”和“-server” JRE的政策是不同的:在-client JRE试图保持你的足迹小由宁愿以清除SoftReferences而不是扩展堆,而-server JRE试图保持你的性能通过宁愿扩大堆(如果可能的话),而不是明确的SoftReferences高。 一个尺寸不适合所有。



Answer 2:

弱引用急切地收集。 如果GC发现一个对象是弱可到达(到达只有通过弱引用),它会立即清除到该对象的弱引用。 因此,他们是很好的保持一个参考的对象,你的程序也不断(强引用)“相关信息” somewere,如对一类,使缓存反射信息,或为对象的包装等什么没有任何意义,以保持它关联的对象之后是GC-ED。 当弱引用被清除,它引用队列被排队,你的代码投票的地方,并且它摒弃了相关的对象也。 也就是说,你把一个对象的额外信息,但并不需要的信息,一旦对象是指消失。 事实上,在某些情况下你甚至可以子类的WeakReference和保持有关在了WeakReference子类的领域对象相关联的额外信息。 另一种典型用法的WeakReference的是连同地图保持典型实例。

在另一方面SoftReferences是良好的外部缓存,重新创​​建的资源为GC通常延误清除它们。 这是保证,虽然之前的OutOfMemoryError抛出所有SoftReferences将被清除,所以他们在理论上不会引起OOME [*]。

典型的使用情况实例是保持的从文件中的内容的解析形式。 你会实施一套系统,你会加载一个文件,分析它,并保持一个SoftReference的解析出的代表性的根对象。 您需要的文件下一次,你会尝试通过SoftReference的捡回来。 如果你能找回它,你不惜自己一负载/分析,如果GC在此期间清除了它,你重新加载它。 这样,您使用的性能优化空闲内存,但不冒险的OOME。

现在的[*]。 保持一个SoftReference的本身不能引起OOME。 如果在另一方面,你错误地使用SoftReference的一个任务WeakReference的是为了使用(即,你跟上不知何故强烈引用的对象相关信息,并丢弃它时,参考对象被清除),你可以运行到OOME为你的代码,轮询的ReferenceQueue并丢弃相关的对象可能会发生不及时运行。

因此,决定取决于使用 - 如果你缓存是构建昂贵,但是从其他数据仍然可重构信息,请使用软引用 - 如果你保持一个参考一些数据的规范化实例,或者你想得的对象的引用,而不“拥有”这(从而防止它被GC'd),使用弱参考。



Answer 3:

在Java中 ; 为了从最强到最弱,主要有:强,软,弱和幻影

很强的参考是一个正常的参考保护从收集通过GC称为对象。 即决不垃圾收集。

软引用是符合回收的垃圾收集器,但可能不会被收集到需要它的内存中,直到。 即垃圾收集之前OutOfMemoryError

弱引用是不被GC保护引用的对象从集合的引用。 即垃圾收集时没有强烈的或软裁判。

虚引用是它已经敲定后,一个对象的引用phantomly引用,但其分配的内存已经被回收之前。

资源

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

  • 当国王 ,GC不能杀了他。
  • 当国王是的,GC攻击他,但国王统治的王国与保护,直到资源可用。
  • 当国王 ,GC攻击他,但统治的王国,不用保护。
  • 当国王是幻影 ,GC已经杀了他,但国王通过他的灵魂是可用的。


Answer 4:

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

原理: weak reference有关垃圾收集。 通常情况下,有对象的一个或多个reference将没有资格进行垃圾回收。
当它上面的原理是不适用weak reference 。 如果一个对象只有与其他对象的弱引用,那么它准备进行垃圾回收。

让我们来看看下面的例子:我们有一个Map使用对象,其中关键是参考对象。

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是一个地方的条目( key-to-value mappings ,当它不再是可以从检索它们)将被删除Map

让我给上面的例子一样用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());
    }
}

输出:拍摄20 calls to System.gc()以导致aMap size的: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");
    }
}

软引用。

Soft Reference稍强的是弱引用。 软引用允许垃圾回收,但回避了一个垃圾收集器只能清除它,如果没有其他的选择。

垃圾收集器并不积极收集软可及的对象,它与弱可及的人做的方式 - 而不是只当它真正“需要”内存收集软可及的对象。 软引用是说给垃圾收集器的一种方式,“只要内存不太紧张,我想保持这个对象周围。但是如果内存变得非常紧张,继续前进,收集它,我会处理接着就,随即。” 垃圾收集器需要清除所有的软引用才可以抛出OutOfMemoryError



Answer 5:

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

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



Answer 6:

SoftReference是专为高速缓存。 当它被发现, WeakReference引用否则无法访问对象,那么它将会立即清除。 SoftReference可以保持原样。 通常有涉及的可用内存上次用于确定它是否应该被清除的量和时间的一些算法。 目前太阳算法是明确的参考,如果它没有被尽可能多秒作为有空闲的内存兆字节的Java堆(可配置,对最大可能堆服务器HotSpot的检查,通过设置-Xmx )。 SoftReference年代以前将被清除OutOfMemoryError被抛出,除非另有到达。



Answer 7:

唯一真正的区别

每商务部 ,松在WeakReferences 必须通过运行GC被清除。

每商务部 ,OOM抛出之前宽松SoftReferences 必须被清除。

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

SoftReferences是有用的。 内存敏感的缓存使用SoftReferences,在WeakReferences没有。


唯一的正确使用的WeakReference的是观察GC运行。 您可以通过创建一个新的WeakReference,其对象立即超出范围做到这一点,然后尝试让空出的weak_ref.get() 当它的null ,你要知道这个时间之间,GC的跑了。

至于不正确使用的WeakReference的,名单是无止境的:

  • 一个糟糕的黑客来实现优先级2 SoftReference的,这样你就不必写了一个, 如预期,因为高速缓存会在每次 GC运行清除,即使有空余的内存这是行不通的。 见https://stackoverflow.com/a/3243242/632951为phails。 (另外,如果你需要超过2级高速缓存优先级?你最好还是得需要一个真正的图书馆。)

  • 一个糟糕的黑客将数据与现有的类的对象联系起来, 但是当你的GC决定创建你在WeakReferences后休息一下它创建了一个内存泄漏(OutOfMemoryError错误)。 此外,它超越丑:一个更好的办法是使用元组。

  • 一个糟糕的黑客将数据与现有的类的对象,其中类具有神经,使自己无子类化,并在其中你需要调用现有的功能代码相关联。 在这种情况下,适当的解决方案是编辑类并使其子类化,或者编辑功能,并使其采取的界面,而不是类,或使用另一种功能。



Answer 8:

此文章可以超有助于了解强,软,弱,虚引用。


为了给你一个总结,

如果你只需要一个对象(没有强引用) 弱引用 ,那么对象将被GC在第二天GC循环回收。

如果你只需要一个对象(没有强引用) 软引用 ,那么对象将被GC只有当JVM运行的内存回收。


所以,你可以说,强引用有最终的权力 (不能被GC回收)

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

弱引用比软引用甚至不那么强大的 (因为他们不能excape任何GC周期,并且将被回收,如果对象没有其他有力的参考)。


餐厅比喻

  • 服务员 - GC
  • 你 - 对象在堆
  • 餐厅面积/空间 - 堆空间
  • 新客户 - 新的对象,希望在餐桌

现在,如果你是一个强大的客户 (类似于强引用),那么即使新顾客来餐厅或什么那么happnes,你将永远不会离开你的表(上堆内存区)。 服务员有没有权利告诉你(或者甚至要求你)离开餐厅。

如果你是一个软客户 (类似于软引用),那么如果一个新的客户进来的餐厅,服务员不会问你离开牌桌,除非没有其他空表留下来适应新的客户。 (换句话说,服务员会问你离开仅当有一个新客户的步骤没有留下其他表为这个新的客户表)

如果你是一个弱的客户 (类似于弱引用),然后服务员,在他的意志,可以(在任何时间点),请你离开餐厅:P



Answer 9:

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

  1. LY 可及对象- GC 不会收集( 回收占用内存 )这类对象。 这些是通过根节点或另一强可对象 (通过局部变量,类变量,实例变量等IE) 可到达
  2. LY 可及对象- GC 可能试图收集这种依赖于内存争的对象。 这些经由一个或多个软参考对象是从根到达
  3. LY 可及对象- GC 必须收集这类对象。 这些经由一个或多个弱引用的对象是从根到达
  4. 复活,能够对象- GC已经在收集这些对象的过程。 但是, 他们可能会回到状态中的一种-强/中/弱一些终结执行
  5. 幻影 LY可及对象- GC 已经在收集这些对象的过程中,已确定不能复活,能够通过任何终结(如果它声明finalize()方法本身,那么它的终结将一直运行)。 这些经由一个或多个幻像参考对象是从根到达
  6. 不可达的对象-一个对象既不强烈,温柔地,弱,也不是幻象可达,而不是resurrectable。 这些对象是准备回收

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



Answer 10:

每个人都应该知道,当它只有弱引用(S)弱引用的对象将只得到收集。 如果有这么多的一个有力的参考,它不会不管有多少弱引用收集。



Answer 11:

WeakReference的 :那些只有弱引用的对象在每个GC周期(轻微或全部)收集。

SoftReference的 :当只软引用收集对象取决于:

  1. -XX:SoftRefLRUPolicyMSPerMB = N标志(默认值是1000,又名1秒)

  2. 在堆中的空闲内存量。

    例:

    • 堆具有的自由空间(全GC之后)10MB;
    • -XX:SoftRefLRUPolicyMSPerMB = 1000

    然后,如果当它被最后存取时间是大于10秒,这仅由SoftReference的引用的对象将被收集。



文章来源: What's the difference between SoftReference and WeakReference in Java?