我有一个在JVM中运行的两个单独的缓存(一个由第三方库控制),每个缓存都使用软引用.我希望JVM在由库控制的缓存之前清除我的受控缓存.SoftReference javadoc指出:
在虚拟机抛出OutOfMemoryError之前,保证已清除对软可访问对象的所有软引用.否则,不会对清除软引用的时间或清除对不同对象的一组此类引用的顺序施加约束.但是,鼓励虚拟机实现偏向清除最近创建或最近使用的软引用.
该类的直接实例可用于实现简单的缓存; 此类或派生的子类也可用于更大的数据结构,以实现更复杂的高速缓存.只要软引用的引用是强可达的,即实际上是在使用中,软引用就不会被清除.因此,复杂的高速缓存可以例如通过保持对这些条目的强烈指示来防止其最近使用的条目被丢弃,留下剩余的条目由垃圾收集器决定丢弃.
常见的JVM实现(尤其是HotSpot)如何在实践中处理SoftReferences?他们是否"反对清除最近创建或最近使用的软参考",这是由规范所鼓励的?
Java中的软引用的用例是什么?当JVM内存不足以释放足够的资源以便在关闭JVM之前转储关键信息时,垃圾收集非关键项是否有用?
它们被称为软引用它们是软的并且在"处于压力之下"时断开,即:JVM已经耗尽内存.我理解弱引用和幻像引用,但实际上并不需要这些引用.
这是我的用例.我们正在尝试缩小应用程序中潜在的内存泄漏,我们正在使用内存分析工具对堆进行快照,以便我们可以查找对象实例和引用.(如果它有帮助,我们正在使用YourKit.)
该应用程序广泛使用动态和CGLIB代理,最终在WeakHashMaps中存储大量类和类加载器的引用.
在我们的测试用例运行之后,我们期望对对象X及其类加载器的所有硬引用都消失了,但是由于测试用例中涉及很多代理,我们还有许多弱/软引用.(我只能找到WeakHashMap引用,但是YourKit将弱引用和软引用都包含在摘要中的一个行项中,所以我不能确定我在某处没有错过软引用.)
即使在从JVM请求完整GC之后也是如此.(在服务器模式下使用sun 1.6.0_23 JDK.)
这看起来好像JVM承认有这些对象只弱/软引用,但我不能强迫它GC这些东西是100%肯定.(所以,我想要的是,它完全从堆中消失,其permgen的类加载器使用也会消失.)
任何人都知道配置和/或强制JVM处理仅软/弱引用的对象的方法吗?
java garbage-collection reference weak-references soft-references
它接收Dalvik的垃圾收集器不尊重SoftReferences并尽快删除它们,就像WeakReferences一样.我还不是100%肯定,但是在我看到LogCat中的"GC释放bla-bla-bla字节"之后,我的SoftReferences仍然被释放了大约3MB的可用内存.
另外,我看到马克·墨菲评论这里:
除非它在Android上不起作用,至少在1.5时间范围内.我不知道GC SoftReference错误是否已修复.SoftReferences很快就会遇到这个bug.
这是真的吗?SoftReferences不受尊重吗?
如何解决这个问题?
我正在为我的Android应用程序实现缓存机制.
我用过SoftReference,就像我发现的许多例子一样.问题是,当我向上或向下滚动时ListView,大部分图像已被清除.我可以在LogCat中看到每次应用程序加载新图像时我的应用程序都是垃圾回收.这意味着大部分不可见的图像ListView都消失了.
因此,每次我回滚到较早的位置(之前我真的下载过图像)我必须再次下载图像 - 它们不会被 缓存.
我也研究过这个话题.根据Mark Murphy在本文中的说法,似乎存在(或者是?)一个bug SoftReference.一些其他结果表明相同的事情(或相同的结果); SoftReference太早被清除了.
有没有可行的解决方案?
在其他语言(例如Java)中,对象引用可以是Strong,Weak,Soft或Phantom(http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html).
在Python中,默认情况下引用为Strong,而WeakRef模块允许弱引用.
是否可以在Python中使用"软引用"?
在我的特定情况下,我有一个对象的缓存,这些对象的创建非常耗时.有时可能没有对缓存对象的引用,但是如果我不需要(例如,如果内存很多),我不想抛弃缓存的对象.
我正在使用一个搜索库,建议保持搜索句柄对象打开,这样可以使查询缓存受益.随着时间的推移,我发现缓存容易变得臃肿(几百兆并且不断增长),并且OOM开始启动.没有办法强制执行此缓存的限制,也没有计划它可以使用多少内存.所以我增加了Xmx限制,但这只是问题的临时解决方案.
最后,我想使这个对象所指的java.lang.ref.SoftReference.因此,如果系统在可用内存上运行不足,它将让对象运行并根据需要创建一个新对象.这会在新开始后降低一些速度,但这比击中OOM要好得多.
我看到的关于SoftReferences的唯一问题是没有干净的方式让他们的指示物最终确定.在我的情况下,在销毁搜索句柄之前我需要关闭它,否则系统可能会用完文件描述符.显然,我可以将这个句柄包装到另一个对象中,在其上写一个终结器(或挂钩到ReferenceQueue/PhantomReference)然后松开.但是,嘿,这个星球上的每篇文章都建议不要使用终结器,特别是 - 针对释放文件句柄的终结器(例如Effective Java ed.II,第27页).
所以我有些困惑.我应该小心地忽略所有这些建议并继续.否则,还有其他可行的替代方案吗?提前致谢.
编辑#1:根据Tom Hawtin的建议测试了一些代码后添加了下面的文字.对我来说,似乎任何一个建议都没有用,或者我错过了一些东西.这是代码:
class Bloat { // just a heap filler really
private double a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
private final int ii;
public Bloat(final int ii) {
this.ii = ii;
}
}
// as recommended by Tom Hawtin
class MyReference<T> extends SoftReference<T> {
private final T hardRef;
MyReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.hardRef = referent;
}
}
//...meanwhile, somewhere in the neighbouring galaxy...
{
ReferenceQueue<Bloat> …Run Code Online (Sandbox Code Playgroud) 我阅读了很多文章,但我不明白 - 在实践中我需要在哪里使用Weak和Phantom参考?软错误引用 - 正如我所理解的那样,是缓存的不错选择.但弱和幻影,我不知道何时使用.请提供我们需要使用它们的实际任务的示例.
JDK 7文档对此有一个说法SoftReference:
" 在虚拟机抛出OutOfMemoryError之前,保证可以清除对软可访问对象的所有软引用."
然而,在我的测试程序中,我看到的OutOfMemoryError一致(除了"陌生人行为"一节):
// RefObjectTest.java
import java.util.*;
import java.lang.ref.*;
public class RefObjectTest {
public static void main(String[] args) {
ArrayList<byte[]> leaks = new ArrayList<>();
byte[] obj = new byte[10 * 1024 * 1024];
SoftReference<byte[]> ref = new SoftReference<>(obj);
// WeakReference is supposed to be eagerly GC'ed, but I see no
// difference in terms of program behavior: still get OOME.
//
// WeakReference<byte[]> ref = new WeakReference<>(obj);
obj = null; …Run Code Online (Sandbox Code Playgroud) java garbage-collection weak-references out-of-memory soft-references