Java WeakReference GC已完成,尚未完成?

时间:2020-05-11 08:18:52

标签: java weak-references

我认为WeakReference引用对象将在调用System.gc()之后完成,但是我错了。

这里有两个测试用例,唯一的区别是WeakReference构造函数,第一个是新对象,而第二个使用引用,它们具有不同的性能,我不知道为什么...

弱引用对象,不会阻止其引用对象 进行定型,定型,然后回收。参考文献最弱 通常用于实现规范化的映射。

假设垃圾收集器在某个时间点确定 一个物体是弱的 可达的。到那时,它将原子清除所有弱引用。 该对象以及对其他任何弱可达对象的所有弱引用 通过一连串的强壮而柔软的物体可以从该物体到达 参考。同时它将声明所有以前的 弱可到达对象将被终结。同时或在某个时候 稍后它将排队那些新近清除的弱引用 在参考队列中注册。

package com.zeng.javaReference;

import org.junit.Test;

import java.lang.ref.WeakReference;

/**
 * @author zeng
 * @version 1.0.0
 * @date 2020-05-11
 */
public class WeakReferenceTest {

    @Test
    public void weakRefRemoved() {
        WeakReference<Apple> weakReference = new WeakReference<>(new Apple("green-apple"));

        System.gc();

        if (weakReference.get() == null) {
            System.out.println("GC remove weakReference!");
        } else {
            System.out.println("weakReference still alive");
        }
    }

    @Test
    public void weakRefNotRemoved() {
        Apple apple = new Apple("green-apple");
        WeakReference<Apple> weakReference = new WeakReference<>(apple);

        System.gc();

        if (weakReference.get() == null) {
            System.out.println("GC remove weakReference!");
        } else {
            System.out.println("weakReference still alive");
        }
    }

    public static class Apple {

        private String name;

        public Apple(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("Apple: " + name + " finalized。");
        }

        @Override
        public String toString() {
            return "Apple{" +
                    "name='" + name + '\'' +
                    '}' + ", hashCode:" + this.hashCode();
        }
    }

}

2 个答案:

答案 0 :(得分:0)

Unable to connect to Chrome debug port: 51656 FormatException: Unexpected character (at character 1) <html> ^ #0 throwToolExit (package:flutter_tools/src/base/common.dart:14:3) #1 ChromeLauncher._connect (package:flutter_tools/src/web/chrome.dart:251:9) <asynchronous suspension> #2 ChromeLauncher.launch (package:flutter_tools/src/web/chrome.dart:183:12) <asynchronous suspension> #3 ChromeDevice.startApp (package:flutter_tools/src/web/web_device.dart:142:46) #4 _ResidentWebRunner.run.<anonymous closure> (package:flutter_tools/src/build_runner/resident_web_runner.dart:443:29) #5 _rootRunUnary (dart:async/zone.dart:1192:38) #6 _CustomZone.runUnary (dart:async/zone.dart:1085:19) #7 _FutureListener.handleValue (dart:async/future_impl.dart:141:18) #8 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45) #9 Future._propagateToListeners (dart:async/future_impl.dart:711:32) #10 Future._completeWithValue (dart:async/future_impl.dart:526:5) #11 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15) #12 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13) #13 _ResidentWebRunner._updateDevFS (package:flutter_tools/src/build_runner/resident_web_runner.dart) #14 _rootRunUnary (dart:async/zone.dart:1192:38) #15 _CustomZone.runUnary (dart:async/zone.dart:1085:19) #16 _FutureListener.handleValue (dart:async/future_impl.dart:141:18) #17 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45) #18 Future._propagateToListeners (dart:async/future_impl.dart:711:32) #19 Future._completeWithValue (dart:async/future_impl.dart:526:5) #20 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15) #21 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13) #22 WebDevFS.update (package:flutter_tools/src/build_runner/devfs_web.dart) #23 _rootRunUnary (dart:async/zone.dart:1192:38) #24 _CustomZone.runUnary (dart:async/zone.dart:1085:19) #25 _FutureListener.handleValue (dart:async/future_impl.dart:141:18) #26 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45) #27 Future._propagateToListeners (dart:async/future_impl.dart:711:32) #28 Future._completeWithValue (dart:async/future_impl.dart:526:5) #29 Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:556:7) #30 _rootRun (dart:async/zone.dart:1184:13) #31 _CustomZone.run (dart:async/zone.dart:1077:19) #32 _CustomZone.runGuarded (dart:async/zone.dart:979:7) #33 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1019:23) #34 _microtaskLoop (dart:async/schedule_microtask.dart:43:21) #35 _startMicrotaskLoop (dart:async/schedule_microtask.dart:52:5) #36 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13) #37 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:169:5) 可能会也可能不会触发垃圾回收。

通过手动调用它,您只是在向JVM提供提示,但是天气会尊重它,这完全取决于Java运行时。 JVM是非常复杂的系统,不允许直接访问资源。

关于文档中的System.gc()

弱引用是指所引用的引用不足以使 要保留在内存中的对象。因此,弱引用可以让 垃圾收集器确定对象的可及性以及是否 有问题的对象应该保留在内存中。

再次决定收集物体的天气完全取决于收集器。

答案 1 :(得分:0)

这确实很有趣。

假设您使用的GC收集器在调用System.gc()时实际上起到了某些作用,例如G1,并且您没有禁用通过-XX:+DisableExplicitGC对GC的显式调用,则有一个解释这,以某种方式。

weakRefNotRemoved在理论上应与weakRefRemoved相同。这与scopereachability有关,有关此here的更多详细信息。

问题在于,在weakRefNotRemoved中,apple引用 之后,任何人都没有使用调用System.gc(),因此在那时可以到达因此,从理论上讲,GC可以回收它,但是无论出于何种原因它都不会回收。我只能假定只有在存在实际内存压力时才触发此特殊路径。

为证明这一点,我们可以将代码稍作更改为:

 public static void weakRefNotRemoved() {
    Apple apple = new Apple("green-apple");
    WeakReference<Apple> weakReference = new WeakReference<>(apple);

    // explicitly set to null
    apple = null;
    System.gc();

    if (weakReference.get() == null) {
        System.out.println("GC remove weakReference!");
    } else {
        System.out.println("weakReference still alive");
    }
}

现在,GC确实会清理它。通常,如果您试图证明一个观点,则最好在while循环中调用该观点,因为无法保证该循环将“抓住” that reference。同样是因为清除发生在asynchronous fashion中。像这样:

 public static void weakRefNotRemoved() {
    Apple apple = new Apple("green-apple");
    WeakReference<Apple> weakReference = new WeakReference<>(apple);

    apple = null;
    while (weakReference.get() != null) {
        System.out.println("weakReference still alive");
        System.gc();
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    }

    System.out.println("GC remove weakReference!");

}

获得这样的输出是完全合法的,例如:

weakReference still alive  // zero or more of these messages
GC remove weakReference!