可以在两次后续调用WeakReference.get()之间对对象进行垃圾回收吗?

时间:2017-04-07 16:36:53

标签: java android garbage-collection weak-references

我有时会在某些库API中看到这种代码,而只是在某人的代码中:

class SomeClass {

    private WeakReference<SomeObject> objectWeakReference; // initialized elsewhere

    public boolean isObjectAttached() {
        return objectWeakReference.get() != null;
    }

    public SomeObject getObject() {
        return objectWeakReference.get();
    }

}

public void checkAndGetWeakReference() {
    SomeClass someClass = new SomeClass();
    if (someClass.isObjectAttached()) {
        someClass.getObject().doSomethingDirectlyOnReturnedObject(); // can the returned reference be null here ?
    }
}

我总是担心如果在蓝色的月亮中有一次NullPointerException,假设此时没有对底层对象的强引用。

我真的不知道垃圾收集器何时可以开始从内存中删除对象,以及它如何与基本线程流相关联。

如果有人能够阐明这一特定主题和/或提供有关该主题的一些信息,那就太好了。

P.S。我个人只会参考一次并将其分配给强有力的参考。问题的关键是得到一些证据证明上面的代码是错误的。

4 个答案:

答案 0 :(得分:3)

WeakReference(以及SoftReference)的重点在于,在任何时,引用的对象可能是gc,并且不存在对该对象的强引用。

由于isObjectAttached()返回时不存在强引用,因此可以在实际执行getObject()之前对其进行垃圾回收。对于这个用例,整个idom是错误的。

唯一安全的方法是首先获取引用(例如,获取本地变量),然后然后将其检查为null。在这种情况下,对象不能被垃圾收集,因为局部变量 是强引用。

答案 1 :(得分:0)

根据java doc。你不应该依赖垃圾收集器。它不知道什么时候会被执行。虽然您正在尝试显式System.gc()

它始终是JVM垃圾收集器的最低优先级。当JVM空闲或程序即将耗尽时,它可以执行GC。

在其他情况下,您的程序将退出。它将在从JVM内存中刷出之前进行垃圾回收。

请参阅javadoc以获取GC的详细说明。

http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

答案 2 :(得分:0)

我想在所有答案中添加一些内容。

当您调用以下方法时,您的对象可以为null:

public SomeObject getObject() {
        return objectWeakReference.get();
    }

关于此对象的垃圾收集。 如果您执行以下操作:

public static void main(String args[]) {
     SomeClass oSomeClass = new SomeClass();

     // this one is strong reference "obj"
     // this object can be null. Best practice is to null check before you use it.
    // Or i will suggest to call isObjectAttached() method before you use it
     Object obj = oSomeClass.getObject(); 
}

当你做obj = null;在上述声明之后的代码中的某处。

此对象内存可用于垃圾回收。只要JVM感觉清理内存。是的,它可以收集这个对象。

关于你要问的代码证明。

public boolean isObjectAttached() {
        return objectWeakReference.get() != null;
    }

此方法用于检查此对象是否存在于内存中,或者它是否具有有效的参考。

如果返回true,则永远不会得到nullpointer异常。

但如果您不使用此方法,我建议您在使用对象之前始终使用空检查。

希望我的方向正确,并在我的回答中有所作为。请相应回复。

我们都在这里学习;-) 享受Java,OOP概念。

答案 3 :(得分:-3)

垃圾收集器内部有其启发式来收集软/弱/幻像引用。它不会在后续GC调用中收集这些对象。它跟踪这些对象,直到达到启发式的阈值,GC不允许收集这些引用。