Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中清除软引用?_Java_Garbage Collection_Soft References - Fatal编程技术网

如何在Java中清除软引用?

如何在Java中清除软引用?,java,garbage-collection,soft-references,Java,Garbage Collection,Soft References,我有一个缓存,它具有对缓存对象的软引用。我试图为使用缓存的类的行为编写一个函数测试,专门测试清除缓存对象时发生的情况 问题是:我似乎无法可靠地清除软引用。仅仅使用一堆内存并不能解决问题:在清除任何软引用之前,我会得到一个OutOfMemory 有没有办法让Java更急切地清理软引用 找到: “尽管所有这些都是可以保证的 软引用将在 抛出OutOfMemoryError,因此 从理论上讲,这不会引起“OOME” 那么,这是否意味着上述场景一定意味着某个类在缓存对象上持有硬引用的某个地方发生内存泄

我有一个缓存,它具有对缓存对象的软引用。我试图为使用缓存的类的行为编写一个函数测试,专门测试清除缓存对象时发生的情况

问题是:我似乎无法可靠地清除软引用。仅仅使用一堆内存并不能解决问题:在清除任何软引用之前,我会得到一个OutOfMemory

有没有办法让Java更急切地清理软引用


找到

“尽管所有这些都是可以保证的 软引用将在 抛出OutOfMemoryError,因此 从理论上讲,这不会引起“OOME”


那么,这是否意味着上述场景一定意味着某个类在缓存对象上持有硬引用的某个地方发生内存泄漏?

垃圾收集和其他引用(如软引用)是不确定的。这确实不可能可靠地执行某些操作,从而在该点上明确清除软引用因此,您的测试可以判断缓存的反应。我建议您通过模拟等方式以更明确的方式模拟引用清除-您的测试将是可复制的和更有价值的,而不仅仅是希望GC清除引用。使用后一种方法是一件非常糟糕的事情,它只会带来额外的问题,而不会帮助您提高缓存及其协作组件的质量。

根据文档和我的经验,我想说是的:您必须在其他地方有参考

我建议使用一个调试器,它可以向您显示对对象的所有引用(例如调试Java6时的Eclipse3.4),并且只检查何时抛出OOM

问题是:我似乎不能 可靠地获取要使用的软引用 清除

这不是SoftReferences所独有的。由于Java中垃圾收集的性质,无法保证任何可垃圾收集的内容都会在任何时间点被收集。即使只需一点代码:

Object temp = new Object();
temp = null;
System.gc();
无法保证在第一行中实例化的对象在此时或事实上在任何时候被垃圾收集。在内存管理语言中,这只是你必须面对的事情之一,你正在放弃对这些事情的声明权。是的,这有时会导致很难确定地测试内存泄漏


也就是说,根据您引用的Javadocs,在抛出OutOfMemoryError之前,SoftReferences应该被清除(事实上,这就是它们的全部要点,也是它们与默认对象引用不同的唯一方式)。因此,听起来似乎存在某种内存泄漏,因为您保留了对所讨论对象的更难的引用


如果您对JVM使用
-XX:+HeapDumpOnOutOfMemoryError
选项,然后将堆转储加载到类似的内容中,您应该能够看到对对象的所有引用,从而查看软引用之外是否有任何引用。或者,您也可以在测试运行时使用探查器实现相同的功能。

如果使用eclipse,则有一个名为的工具可以使堆转储调试更容易。

如果确实需要,可以在SoftReference上调用clear()来清除它

这就是说,如果JVM抛出OutOfMemoryError,并且您的SoftReference尚未清除,那么这意味着您必须在其他地方对该对象进行硬引用。否则将使软引用合同无效。否则,永远不能保证清除了软引用:只要内存仍然可用,JVM就不需要清除任何软引用。另一方面,它可以在下次执行GC循环时清除它们,即使它不需要这样做

也可以考虑查看弱引用,因为VM在清除它们时往往更具攻击性。从技术上讲,VM从来都不需要清除WeakReference,但是如果对象被认为是死的,那么它应该在下次执行GC循环时清除它们。如果您正在尝试测试清除缓存时发生的情况,那么使用WeakReferences可以帮助您更快地删除条目


另外,请记住,这两个都依赖于执行GC循环的JVM。不幸的是,没有办法保证这些事情会发生。即使您调用System.gc(),垃圾收集器也可能会认为它做得很好,而选择什么也不做。

在典型的JVM实现(SUN)中,您需要多次触发完整的gc以清除软引用。这是因为软引用需要GC做更多的工作,例如,因为一种机制允许您在回收对象时得到通知


IMHO在应用服务器中使用大量SOF引用是不好的,因为开发人员无法控制它们何时发布

还有以下JVM参数用于调整软引用的处理方式:

-XX:SoftRefLRUPolicyMSPerMB=<value> -XX:SoftRefLRUPolicyMSPerMB=
其中“value”是每Mb可用内存中软引用将保留的毫秒数。默认值为1s/Mb,因此,如果一个对象只能软访问,那么如果只有1Mb的堆空间可用,它将持续1s。

如果您有一个缓存,它是一个软引用的映射,并且您希望清除它们,那么您只需清除()映射,它们将被清除(包括它们的引用)

缓存的对象是否有终结器?终结器将创建对对象的新强引用,因此,即使清除了软引用,在以后的GC循环之前,内存也不会被回收。

您可以使用此命令在测试中强制清除所有软引用。

但是,在OOM时间清除引用是一种定义行为,这正是他希望通过