WeakReference和SoftReference之间有什么不同

时间:2014-02-17 13:22:32

标签: android dalvik

我在link上找到了该文档 它描述如下:

弱引用对于映射有用,一旦它们不再被引用(从外部),它们的条目应自动删除。 SoftReference和WeakReference之间的区别在于决定清除和排列引用的时间点: 应尽可能早地清除和排队SoftReference,即,如果VM存在内存不足的危险。 一旦知道弱引用,就可以清除WeakReference并将其排队。

但是当我查看Dalvikvm的源代码时,在dvmCollectGarbageInternal(Heap.cpp L446 Android 4.4)函数中找到了一些东西。它似乎有两个参考 同时清除。

 /*
 * All strongly-reachable objects have now been marked.  Process
 * weakly-reachable objects discovered while tracing.
 */
dvmHeapProcessReferences(&gcHeap->softReferences,
                         spec->doPreserve == false,
                         &gcHeap->weakReferences,
                         &gcHeap->finalizerReferences,
                         &gcHeap->phantomReferences);

我错过了什么吗?

=============================================== =================================

在@ fadden的帮助下,我找到了保留代码

if (!marked && ((++counter) & 1))

dalvikvm保留每个GC程序的半软件参考,并且我复制某人的测试代码测试

final ArrayList> list = new ArrayList>(                 SR_COUNT);         for(int i = 0; i< SR_COUNT; ++ i){             list.add(new SoftReference(new Integer(i)));         }

    /* Test */
    for (int i = 0; i < 3; ++i) {
        System.gc();

        try {
            Thread.sleep(200);
        } catch (final InterruptedException e) {
        }
    }

    /* Check */
    int dead = 0;
    for (final SoftReference<Integer> ref : list) {
        if (ref.get() == null) {
            ++dead;
        }
        Log.d(TAG, "dead: " + dead);
    }

来自logcat的所有日志都是我的想法。

2 个答案:

答案 0 :(得分:2)

FWIW,Java中弱/软/幻像引用的最佳描述见 Java编程语言(“垃圾收集和内存”)的第17章。

软引用保留没有强制性政策。允许VM在GC期间丢弃所有或不丢弃,或者介于两者之间。唯一的要求是在抛出OOM之前,VM应该丢弃所有可轻松访问的对象。

您可以在MarkSweep.cppdvmHeapProcessReferences()中继续使用Dalvik的逻辑。请特别注意对preserveSomeSoftReferences()的调用,该调用根据引用“颜色”保留一些但不保留其他内容。您可以在wikipedia GC article上阅读有关颜色的更多信息。

答案 1 :(得分:0)

来自理解弱参考,作者:Ethan Nicholas: https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

弱引用

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

WeakReference weakWidget = new WeakReference(widget);

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

...

软参考

软引用与弱引用完全相同,只是它不太愿意丢弃它引用的对象。一个只能弱访问的对象(对它的最强引用是WeakReferences)将在下一个垃圾收集周期被丢弃,但是一个可以轻松到达的对象通常会暂停一段时间。

SoftReferences的行为与WeakReferences不同,但实际上只要内存供应充足,就可以保留软可访问对象。这使得它们成为缓存的良好基础,例如上面描述的图像缓存,因为您可以让垃圾收集器担心对象的可达性(永远不会从缓存中移除强可达对象)以及它有多糟糕需要他们消耗的记忆。

Peter Kessler在评论中补充道:

Sun JRE确实以不同于WeakReferences的方式处理SoftReferences。如果可用内存没有压力,我们会尝试保持SoftReference引用的对象。一个细节:“-client”和“-server”JRE的策略是不同的:-client JRE试图通过清除SoftReferences而不是扩展堆来保持您的足迹小,而-server JRE尝试保留您的通过优先扩展堆(如果可能)而不是清除SoftReferences来提高性能。一种尺寸并不适合所有人。