- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
看起来 Dalvik 的垃圾收集器不尊重 SoftReferences 并尽快删除它们,就像 WeakReferences 一样。我还不是 100% 确定,但尽管事实上仍有大约 3MB 的可用内存,但在我在 LogCat 中看到“GC freed bla-bla-bla bytes”后,我的 SoftReferences 被清除了。
此外,我还看到了 Mark Murphy 的评论 here :
Except that it doesn't work on Android, at least in the 1.5 timeframe. I have no idea if the GC SoftReference bugs have been fixed. SoftReferences get GC'd too soon with this bug.
这是真的吗?是否不尊重 SoftReferences?
如何解决这个问题?
最佳答案
在没有收到答复后,我决定自己研究。我做了一个简单的测试来针对 SoftReferences 执行 GC。
public class TestSoftReference extends TestCase {
public void testSoftRefsAgainstGc_1() { testGcWithSoftRefs(1); }
public void testSoftRefsAgainstGc_2() { testGcWithSoftRefs(2); }
public void testSoftRefsAgainstGc_3() { testGcWithSoftRefs(3); }
public void testSoftRefsAgainstGc_4() { testGcWithSoftRefs(4); }
public void testSoftRefsAgainstGc_5() { testGcWithSoftRefs(5); }
public void testSoftRefsAgainstGc_6() { testGcWithSoftRefs(6); }
public void testSoftRefsAgainstGc_7() { testGcWithSoftRefs(7); }
private static final int SR_COUNT = 1000;
private void testGcWithSoftRefs(final int gc_count) {
/* "Integer(i)" is a referrent. It is important to have it referenced
* only from the SoftReference and from nothing else. */
final ArrayList<SoftReference<Integer>> list = new ArrayList<SoftReference<Integer>>(SR_COUNT);
for (int i = 0; i < SR_COUNT; ++i) {
list.add(new SoftReference<Integer>(new Integer(i)));
}
/* Test */
for (int i = 0; i < gc_count; ++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;
}
}
assertEquals(0, dead);
}
}
我的想法是,我每次运行相同的代码都会增加对 SoftReferences 的压力(通过运行更多的 GC 遍数)。
结果非常有趣:除了一次以外,所有运行都顺利通过!
On Android 1.5 device:testSoftRefsAgainstGc_1() FAILED! AssertionFailedError: expected:0 but was:499testSoftRefsAgainstGc_2() passedtestSoftRefsAgainstGc_3() passedtestSoftRefsAgainstGc_4() passedtestSoftRefsAgainstGc_5() passedtestSoftRefsAgainstGc_6() passedtestSoftRefsAgainstGc_7() passedOn Android 1.6 device:testSoftRefsAgainstGc_1() passedtestSoftRefsAgainstGc_2() FAILED! AssertionFailedError: expected:0 but was:499testSoftRefsAgainstGc_3() passedtestSoftRefsAgainstGc_4() passedtestSoftRefsAgainstGc_5() passedtestSoftRefsAgainstGc_6() passedtestSoftRefsAgainstGc_7() passedOn Android 2.2 device:All pass.
这些测试结果是稳定的。我试过很多次,每次都是一样的。所以我相信这确实是垃圾收集器中的一个错误。
因此,我们从中学到了什么......在您的代码中使用 SoftReferences 对于 Android 1.5-1.6 设备毫无意义。对于这些设备,您将不会获得您期望的行为。但是,我没有尝试 2.1。
关于Android:GC 不尊重 SoftReferences?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4014033/
我的 Android 应用程序中有一个位图缓存,其中通过 SoftReference 引用位图。然而,位图被清空得太早了。缓存中最多可以有 20 个位图,如果我加载更多,GC 开始清空 SoftRef
Map> cache = new ConcurrentHashMap>(); 我已经 map 声明了一个类似于上面的 map ,我将其用作缓存。 问题是我要在将项目添加到缓存后立即对缓存执行所有操作,
我有一个创建一系列位图的应用程序。我将这些位图保存在 SoftReferences 中,以避免内存不足。我希望堆大小在开始收集我的 SoftReferences 之前增长到最大 16MB。然而,Sof
JDK 7 文档中有关于 SoftReference 的内容。 : "All soft references to softly-reachable objects are guaranteed to
我正在为我的 Android 应用程序实现缓存机制。 我使用 SoftReference,就像我发现的许多示例一样。问题是,当我在 ListView 中向上或向下滚动时,大部分 图像已经被清除。我可以
我正在为缓存实现测试 SoftReference,我发现了一个奇怪的行为: 我有一个 setName(String name) 方法,它通过 SoftReference 设置 Graph 对象的名称:
我正在使用一个搜索库,它建议将搜索句柄对象保持打开状态,因为这有利于查询缓存。随着时间的推移,我观察到缓存趋于膨胀(几百兆并不断增长)并且 OOM 开始出现。没有办法强制执行此缓存的限制,也没有计划它
看起来 Dalvik 的垃圾收集器不尊重 SoftReferences 并尽快删除它们,就像 WeakReferences 一样。我还不是 100% 确定,但尽管事实上仍有大约 3MB 的可用内存,但
我的应用程序出现了 OutOfMemoryError。当我阅读一些教程时,我开始知道,我可以通过使用 Softreference/Weakreference 来解决这个问题。但是我不知道如何使用Sof
我有一些代码使用了 SoftReference 子类的许多实例。我想测试它在所有/只有一些/没有这些引用被暂存以在 ReferenceQueue 中清除的情况下是否正常工作。对于“无”的情况,这很简单
请解释一下弱引用的用途。我通常确实了解 Java 概念,但这一个给我带来了麻烦。 我确实理解弱引用是什么,但它们的用法和性质在我的脑海中有点模糊。我无法想象一个正确的场景,其中使用弱引用成为必要。 我
编辑 到目前为止,大多数答案都集中在我错误地扩展 map 这一事实上。我已在示例代码中更正了此问题,但类型问题仍然存在,问题仍然存在。 我试图在 Scala 中实现 SoftHashMap,但遇到了类
我在这个 link 上找到了文档描述如下: 弱引用对于映射很有用,一旦它们不再被引用(从外部),应该自动删除它们的条目。 SoftReference 和 WeakReference 之间的区别在于决定
创建这么多Strong Reference会出现OOM错误是因为GC不会收集Strong Reference,但是如果没有额外的内存,GC会收集Weak Reference。所以我的问题是:我在设置
我在处理软引用和弱引用时遇到了问题。代码有一个可以切换的标志软引用和弱引用之间的所有逻辑。虽然引用很弱,但似乎为了工作正常,使用软引用我一直得到 OutOfMemoryError。这种情况发生在 Ma
使用 SoftReference 获取任何代码要进行全面测试,必须想出某种方法来测试“是的,它已被取消”的情况。人们可能或多或少地通过使用“for-test”代码路径强制引用为空来模拟这一点,但这不会
我实现了一个自定义适配器来创建一个显示与位置相关的信息的对话框(对话框的每个条目都包含一个图像、一个显示地址的文本字段和一个显示城市和国家/地区的文本字段。)在适配器的 getView (...) 方
我正在使用一个内部数据库连接池来缓存PreparedStatements。当连接返回到池中时,缓存的Statement并没有关闭。这些会在 mySQL 驱动程序中创建 OutOfMemoryExcep
我之前得出的结论是,如果您需要一个具有基于值(等于)的相等性的 SoftReference,那么设计就会很糟糕,但内部人员除外。这是继 Google Collections 和 Guava 之后,不包
我有一个包含 100 张不同图像的 ListView 。我的缓存如下所示, public class ImageCache { HashMap> myCache; .... .
我是一名优秀的程序员,十分优秀!