SoftReference 过早收集垃圾

发布于 2024-11-02 14:55:34 字数 674 浏览 3 评论 0原文

我正在为我的 Android 应用程序实现缓存机制。

我使用 SoftReference,就像我发现的许多示例一样。问题是,当我在 ListView 中向上或向下滚动时,大部分图像已经被清除。我可以在 LogCat 中看到,每次应用程序加载新图像时,我的应用程序都会被垃圾收集。这意味着 ListView 中的大部分不可见图像都消失了。

因此,每次我向后滚动到较早的位置(我之前确实下载过图像的位置),我都必须再次下载图像 - 它们没有缓存< /em>.

我也研究过这个话题。 根据本文中的 Mark Murphy 的说法,SoftReference 似乎存在(或曾经?)一个错误。其他一些结果表明同样的事情(或相同的结果); SoftReference 被清除得太早了。

有可行的解决方案吗?

I'm on my way with implementing a caching mechanism for my Android application.

I use SoftReference, like many examples I've found. The problem is, when I scroll up or down in my ListView, the most of the images are already cleared. I can see in LogCat that my application is garbage collected everytime the application loads new images. That means that the most of the non-visible images in the ListView are gone.

So, everytime I scroll back to an earlier position (where I really downloaded images before) I have to download the images once again - they're not cached.

I've also researched this topic. According to Mark Murphy in this article, it seems that there is (or was?) a bug with the SoftReference. Some other results indicates the same thing (or the same result); SoftReferences are getting cleared too early.

Is there any working solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一人独醉 2024-11-09 14:55:34

SoftReference 是穷人的缓存。 JVM 可以使这些引用保持更长时间,但不是必须的。一旦不再存在硬引用,JVM 就会对软引用对象进行垃圾回收。您所遇到的 JVM 的行为是正确的,因为 JVM 不必将此类对象保留更长时间。当然,大多数 JVM 都会在某种程度上尝试使软引用对象保持活动状态。

因此,软引用是一种危险的缓存。如果您确实想确保缓存行为,则需要一个真正的缓存。就像 LRU 缓存。特别是如果您的缓存对性能至关重要,则应该使用适当的缓存。

SoftReference are the poor mans Cache. The JVM can hold those reference alive longer, but doesn't have to. As soon as there's no hard reference anymore, the JVM can garbage collect a the soft-referenced Object. The behavior of the JVM you're experiencing is correct, since the JVM doesn't have to hold such object longer around. Of course most JVMs try to keep the soft reference object alive to some degree.

Therefore SoftReferences are kind of a dangerous cache. If you really want to ensure a caching-behavior, you need a real cache. Like a LRU-cache. Especially if you're caching is performance-critical, you should use a proper cache.

痴骨ら 2024-11-09 14:55:34

来自 Android 培训网站:

http://developer.android.com/training/displaying-bitmaps/cache -位图.html

过去,流行的内存缓存实现是软引用
或 WeakReference 位图缓存,但不建议这样做。
从 Android 2.3(API Level 9)开始,垃圾收集器更多
积极收集软/弱引用,这使得它们
相当无效。另外,在Android 3.0(API Level 11)之前,
位图的支持数据存储在本机内存中,而不是存储在本机内存中
以可预测的方式发布,可能会引起应用程序
短暂超出其内存限制并崩溃。

链接中的更多信息。

我们应该使用 LruCache 代替。

From Android Training site:

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

In the past, a popular memory cache implementation was a SoftReference
or WeakReference bitmap cache, however this is not recommended.
Starting from Android 2.3 (API Level 9) the garbage collector is more
aggressive with collecting soft/weak references which makes them
fairly ineffective. In addition, prior to Android 3.0 (API Level 11),
the backing data of a bitmap was stored in native memory which is not
released in a predictable manner, potentially causing an application
to briefly exceed its memory limits and crash.

More information in link.

We shoud use LruCache instead.

贪了杯 2024-11-09 14:55:34

将每个图像缓存在持久存储中,而不仅仅是内存中。

Cache each image on persistent storage instead of just in memory.

情绪 2024-11-09 14:55:34

Gamlor 的答案在您的情况下是正确的。不过,有关其他信息,请参阅 GC 常见问题解答,问题32.

Java HotSpot Server VM 使用最大可能的堆大小(由 -Xmx 选项设置)来计算剩余的可用空间。

Java HotSpot 客户端 VM 使用当前堆大小来计算可用空间。

这意味着服务器 VM 的总体趋势是增加堆而不是刷新软引用,因此 -Xmx 对软引用何时进行垃圾收集具有重大影响。

Gamlor's answer is correct in your situtation. However, for additional information, see the GC FAQ, question 32.

The Java HotSpot Server VM uses the maximum possible heap size (as set by the -Xmx option) to calculate free space remaining.

The Java HotSpot Client VM uses the current heap size to calculate the free space.

This means that the general tendency is for the Server VM to grow the heap rather than flush soft references, and -Xmx therefore has a significant effect on when soft references are garbage collected.

滿滿的愛 2024-11-09 14:55:34

Jvm遵循这个简单的等式来确定是否应该清除软引用:

interval <= free_heap * ms_per_mb

间隔是上次GC周期时间戳和软引用的上次访问时间戳之间的持续时间。
空闲堆是当时可用的堆空间。
ms_per_mb 是分配给堆中每个可用 MB 的毫秒数。 (恒定默认值 1000 毫秒)

如果以上方程为假,则参考值被清除。

因此,即使您有大量可用内存,如果您的软引用在足够长的时间内没有被访问,它们也会被清除。

-XX:SoftRefLRUPolicyMSPerMB= jvm arg 可用于调整 ms_per_mb 常量。

Jvm follows this simple equation to determine if a soft reference should get cleared:

interval <= free_heap * ms_per_mb

interval is duration between last gc cycle timestamp and the last access timestamp of soft reference.
free heap is heap space available at that moment.
ms_per_mb is milliseconds allocated to every MB available in heap. (Constant default 1000 ms)

If above equation is false, reference gets cleared.

So, even if you have a lot of free memory, if your soft references have not been accessed for an ample amount of time, they will get cleared.

-XX:SoftRefLRUPolicyMSPerMB= jvm arg can be used to tweak ms_per_mb constant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文