如果主引用指向null

时间:2018-03-23 12:49:08

标签: java

我正在阅读WeakReferenceSoftReference

找到以下内容:

的WeakReference:

Counter counter = new Counter(); // strong reference - line 1
WeakReference<Counter> weakCounter = new WeakReference<Counter>(counter); //weak reference
counter = null; // now Counter object is eligible for garbage collection

软参考:

Counter prime = new Counter(); // prime holds a strong reference - line 2
SoftReference<Counter> soft = new SoftReference<Counter>(prime) ; //soft reference variable has SoftReference to Counter Object created at line 2
prime = null; // now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory

在这里,无论如何,我将 null 分配给强引用计数器 prime ,它们有资格进行垃圾回收并将被垃圾回收当下一个GC循环运行时。

WeakReference / SoftReference如何影响/协助垃圾收集?

更新

在以下程序中:

public class WeakReferenceSample {
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        WeakReference<HelloWorld> helloWorldReference = new WeakReference<>(helloWorld);
        helloWorld = null;
        System.out.println(helloWorld);
        System.out.println(helloWorldReference.get());
        System.gc();
        System.out.println(helloWorldReference.get());
    }
}

即使将helloWorld引用更改为null,我的第一个System.out.println(helloWorldReference.get());也会打印对象值,而不是null。在System.gc()之后,第二次打印为null。由于helloWorld引用和helloWorldReference引用都指向同一个HelloWorld对象,因此内部如何工作。

示例输出:

null
HelloWorld@2503dbd3
null

证明:如果我没有将null分配给helloWorld引用,那么helloWorld引用和helloWorldReference引用都指向同一个HelloWorld对象

HelloWorld@2503dbd3
HelloWorld@2503dbd3
HelloWorld@2503dbd3

对内部如何运作感到困惑?之前我曾想过克隆对象然后弱引用它,但是从输出中看,它看起来不像。

2 个答案:

答案 0 :(得分:2)

长话短说

没有任何对象具有强引用,因此对象符合垃圾回收的条件。但是不同的引用类型将决定垃圾收集器如何优先处理对象&#39;垃圾收集。

垃圾收集周期中发生的事情的实际细节可能因不同参数而异。 其中一些参数如下:

  • JRE / VM版本
  • 选择实际垃圾收集算法
  • 系统中的可用内存
  • 系统资源

原则上,垃圾收集器试图快速有效,以免影响长期和短期运行的性能,同时确保有足够的可用内存。

因此在垃圾收集期间,垃圾收集器将尝试通过垃圾收集一些对象来释放一些内存。 垃圾收集器最终将确定它将释放多少内存以及为了执行垃圾收集哪些对象。垃圾收集器不一定在每次运行时垃圾收集所有符合条件的对象。

所以我们可以说有资格进行垃圾收集的对象将被垃圾收集到不同的优先级。因此垃圾收集优先级如下:

  1. 未引用的对象具有最高的垃圾回收优先级。
  2. 弱引用对象是下一个更有资格的垃圾回收对象。
  3. 软引用对象是下一个更有资格的垃圾回收对象。
  4. 基于此优先级,具有弱引用的对象可能比软引用对象更急切地收集垃圾。但是,每个对象何时被垃圾收集的决定和责任仅由垃圾收集器进行。

    这个定义讲的是优先级(渴望)而不是精确的规则,所以人们可以期望观察到: 从长远来看(如果在许多不同的JRE和不同情况下观察到),弱引用对象往往会在Soft Referenced对象之前被垃圾收集。

    &#34;软引用与弱引用完全相同,只是它不太愿意丢弃它引用的对象。&#34;引用这个答案在这里; Soft vs Weak reference Java还包括Phantom引用,这是一个相关的概念。 Phantom References

    在问题更新后更新:

    在您的第一个示例中:

    null这是预期的,因为它是helloWorld变量中的强引用,已明确设置为null。

    HelloWorld@2503dbd3 helloWorldReference变量中的弱引用尚未被垃圾收集,因此它仍然存在。但是,由于这是对象的唯一引用,因此它有资格进行垃圾回收。如果您多次运行此示例,则可能会打印为null。如果你运行另一个消耗太多内存的线程,你可以看到它。

    null helloWorldReference变量中的弱引用已被垃圾收集。也可能是这个对象不为null,具体取决于运行的垃圾收集器。其中垃圾收集器可以依赖于VM和启动之前给出VM的参数。另请参见System.gc的javadoc。

      

    调用gc方法建议认为Java虚拟机需要花费大量资源来回收未使用的对象,以使其当前占用的内存可用于快速重用。当控制从方法调用返回时,Java虚拟机已经做了尽力而为来从所有丢弃的对象中回收空间。

    注意粗体字。他们暗示这个方法并不总是有相同的结果。调用此方法是对VM的建议,该建议将尽最大努力。

    在您的第二个示例中:

    HelloWorld@2503dbd3存在helloWorld变量中的强引用

    HelloWorld@2503dbd3 helloWorldReference变量中的弱引用尚未被垃圾收集,因为已经存在对此对象的强引用。该对象不符合垃圾回收的条件。

    HelloWorld@2503dbd3 helloWorldReference变量中的弱引用检索对象,因为它尚未被垃圾回收。由于已经存在对该对象的强引用,因此该对象永远不会被垃圾收集。

答案 1 :(得分:1)

WeakReferenceSoftReference s不“协助”垃圾收集器,但它们提供了关于是否应该尽可能保留引用的提示。如果对象的唯一引用是弱或软,则GC可以收集对象。但是,除非JVM需要内存,否则具有SoftReference的对象通常不会被垃圾回收。它们适用于缓存之类的东西。