`
in355hz
  • 浏览: 230298 次
社区版块
存档分类
最新评论

有关 SoftReference 的一些事实

    博客分类:
  • Java
阅读更多
Java 的 SoftReference 有很多年都没有被人惦记了。在 Javadoc 里, 它的描述是这样:
 
”虚拟机在抛出 OutOfMemoryError 之前会保证所有的软引用对象已被清除。此外,没有任何约束保证软引用将在某个特定的时间点被清除,或者确定一组不同的软引用对象被清除的顺序。不过,虚拟机的具体实现会倾向于不清除最近创建或最近使用过的软引用。“
 
这个类可以直接被用来实现简单的缓存,这个类或派生的子类也可用于较大的数据结构,来实现更加复杂的缓存。只要软引用可以到达该对象,就是说,该对象实际上是在使用,软引用就不会被清除。这样能够实现一个复杂的缓存,例如,使用强引用来关联最近使用的项目以防止对象被清除,而剩下的项目(使用软引用)抛给垃圾收集器去自由衡量。“
 
这里告诉我们什么?
1. 在你看到 OutOfMemoryError 前,Java 虚拟机一定会回收 SoftReference 对象;
2. Java 不保证 SoftReference 对象何时被清除,相关的机制是 JVM 实现相关的;
3. Java 提供 SoftReference 的期望是更好的实现缓存。
 
恩,看起来 很好很强大。JVM 会负责保留最近最新使用过的软引用,简直完美。但是,喂喂,有没有人在实际项目里用过 SoftReference 以及仔细观察过它的清除? 
 
结果告诉我,现实是骨感的:
1. 如果你的进程所占的内存不是满到要抛 OutOfMemoryError 的程度,JVM 根本不清理 SoftReference 占用的内存。
2. 软引用对象占用了一大堆内存,更糟糕的是它们都会进入 Old-Gen。这样你的进程会频繁触发 Full GC,但即使这样,JVM 也不一定会清理 SoftReference 占用的内存。
3. 因为 Old-Gen 现在是满负荷工作,你会发现一次 FullGC 的时间变得异常的长。
 
简直太坑爹了,那 JVM 什么时候才清理 SoftReference 呢? 
 
这里的正确答案是 ”这是 JVM 的自由,凡人无法干涉“。恩,尽管凡人无法干涉 JVM,但是可以使点小手段欺骗:
try { 
    Object[] ignored = new Object[(int) Runtime.getRuntime().maxMemory()];
} catch (Throwable e) {
    // Ignore OME
}
 (来源:http://stackoverflow.com/questions/3785713/how-to-make-the-java-system-release-soft-references
 
上面这段代码可以让 JVM 立即回收 SoftReference,很猛很暴力。
 
那么,常见的 JVM,例如 HotSpot 是怎么回收 SoftReference 的呢? 谢天谢地,已经有人给出了研究结果:
 
直接翻译一下结论,是这样的:
 
”发生 GC 的时候,是否清理 SoftReference 取决于两个因素:
1. 引用的时间戳;
2. 有多少可用内存。
 
计算公式非常简单,首先定义:
free_heap    - 堆里的空闲内存数量,单位是 MB
interval       - 上一次 GC 时间与与引用记录的时间戳之间的时间间隔
ms_per_mb - 是一个毫秒数常量,表示每 MB 空闲堆中保留的 SoftReference 数量。
 
判定公式是:
interval <= free_heap * ms_per_mb
 
其中 ms_per_mb 是一个可以设置的 JVM 参数:-XX:SoftRefLRUPolicyMSPerMB,结合公式很容易看明白,这个参数决定 FullGC 保留的 SoftReference 数量,参数值越大,GC 后保留的软引用对象就越多。
 
有些博客在推荐 JVM 参数时,建议 -XX:SoftRefLRUPolicyMSPerMB 配置成 0 ,这样可以避免在 GC 后保留 SoftReference。是否这样就可以完全避免软引用回收的问题?我想只有 JVM 知道了。
 
这里也揭示了 JVM 回收 SoftReference 的算法,注意它并不是真正淘汰最久最少访问的对象,而是根据内存余量,淘汰最近未访问的对象。相比真正的 LRU 淘汰算法,这显得比较粗放。
 
上面这些事实背后,我的结论是,使用 SoftReference 前需要谨慎考虑:
1. 你的应用的确需要把这些对象保留在 JVM 中,如果内存够用就永不清理吗?
2. 这些软引用对象会不会过分占用内存,导致你的应用内存压力增加,频繁 Full GC?
3. 除了 SoftReference, 你有没有更好管理这些对象的机制?
 
最后,决定使用 SoftReference 的同学,请三思~
0
2
分享到:
评论

相关推荐

    SoftReference、WeakReference和PhantomRefrence分析和比较

    SoftReference、WeakReference和PhantomReference分析和比较 在 Java 中,引用类型分为强引用、软引用、弱引用和虚引用四种。强引用是我们最常用的引用类型,而软引用、弱引用和虚引用则是 Java 为我们提供的三种...

    软引用SoftReference1

    软引用SoftReference1

    StrongReference,SoftReference, WeakReference的使用实例

    StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421

    软引用SoftReference缓存图片及异步加载

    本篇文章将深入探讨如何使用Java中的软引用(SoftReference)来缓存图片,并结合异步加载策略来实现高效的图片加载机制。 一、软引用(SoftReference)的概念与作用 软引用是Java内存管理中的一种特性,它是一种弱...

    Android基于SoftReference缓存图片的方法

    本篇文章将详细探讨如何基于`SoftReference`来缓存图片,以及其原理和实践技巧。 首先,我们需要理解`SoftReference`的概念。在Java中,`SoftReference`是一种特殊的引用类型,它持有对对象的弱化引用。当系统内存...

    Java引用总结--StrongReference、SoftReference、WeakReference、PhantomRef

    Java从1.2版本开始引入了四种引用,分别是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。这四种引用的级别由高到低依次为:强引用 &gt; 软引用 &gt; 弱引用...

    软应用示例

    本篇将详细讲解如何利用软引用(SoftReference)来解决Android OOM问题,并探讨其工作原理以及在实际应用中的注意事项。 **软引用(SoftReference)的概念** 软引用是Java内存模型中的一种特殊引用类型,它介于强...

    ListView异步加载网络图片

    当系统需要释放内存时,SoftReference持有的Bitmap会优先被清理,但只要Bitmap还被其他强引用(如ImageView)持有,就不会被回收。 具体步骤如下: 1. 创建一个图片加载器类,实现异步加载功能。这个类通常包含一...

    深入探讨 java.lang.ref 包1

    Java.lang.ref 包是 Java 类库中的一个重要组成部分,它包含了与垃圾回收机制密切相关的引用类。这些引用类的设计允许开发者在特定条件下控制对象的生命周期,尤其是在处理缓存、大型数据结构或者避免内存泄漏时显得...

    Android实现ListView异步加载图片

    本文将详细介绍 Android 中实现 ListView 异步加载图片的方法,并对相关的技术概念进行解释。 1. 异步加载图片的必要性 在 Android 应用程序中,加载图片是一个耗时的操作,特别是在 ListView 中。如果不使用异步...

    基于软引用实现的缓存,当内存不够使会自动释放缓存内容,以避免OOM

    具体实现上,可以使用Java的`java.lang.ref.SoftReference`类来创建软引用。通常,我们会创建一个软引用对象,将实际的缓存数据作为参数传入,然后将软引用对象放入一个映射结构(如HashMap)中。当需要访问缓存时,...

    android中软引用的使用测试

    所以开始做应用的时候并没有考虑这些,所以后来痛苦了好久,现在和大家分享一些关于让你的程序稳定程度加一成保障的做法,那就是在程序中SoftReference的使用,可能大家并没有确切的去做过这个软引用的实际使用与不...

    Java中的软引用弱引用和虚引用.docx

    这个问题往往与如何有效地管理内存资源有关,特别是在处理大量图片等大内存消耗的任务时更为明显。本文将深入探讨Java中三种特殊的引用类型——软引用(Soft Reference)、弱引用(Weak Reference)以及虚引用(Phantom ...

    JVM 77道面试题和答案.docx

    4. **WeakReference与SoftReference**:两者都与内存管理和GC有关。WeakReference的对象一旦没有强引用,就会立即被GC回收。SoftReference则稍微“软”一些,只有在系统内存不足时才会被回收。 5. **-XX:+...

    Android内存管理

    SoftReference是Java语言中的一种弱引用类型,它比普通的强引用更弱一些,但比WeakReference强一些。在Android中,SoftReference通常用于处理图像缓存等问题,可以帮助开发者更好地管理内存。 - **用途**: ...

    Android使用缓存机制实现文件下载及异步请求图片加三级缓存

    在下载文件或者在线浏览文件时,或者为了保证文件下载的正确性,需要使用缓存机制,常使用SoftReference来实现。 SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程...

    一些android开发技巧

    使用WeakReference和SoftReference管理对象生命周期,及时释放不再使用的资源。 5. **数据持久化**:SQLite数据库适用于存储结构化的数据,而SharedPreferences适合保存用户偏好设置。对于大量非结构化数据,可考虑...

Global site tag (gtag.js) - Google Analytics