0

我的应用程序运行在HotSpot jvm 1.8.0_45上,打包好的8GB堆。应用程序尝试为新对象分配内存失败,并发生堆空间OOM错误。我查看了堆转储,发现大部分空间都被charCCufferCaches的T4CConnection实例占用。这个缓存为char数组保存了SoftReferences。我很惊讶SoftReferences在OOM之前没有发布。我再次检查是否有一个这个数组的硬引用,但没有找到一个。OOM错误和怪异的SoftReferences

为什么我的应用程序通过SoftReferences持有3GB字符数组时存在堆空间OOM? 为什么这个SoftReferences在应用程序需要新内存时不能发布? T4CConnection对象的

部分表示charBufferCache:用于字符数组

part of T4CConnection object showing charBufferCache

传入的引用在T4CConnection charBufferCache holded者:

incoming references for char array holded at T4CConnection charBufferCache

+0

什么时候被转储捕获?这可能是由于堆栈上的某些东西使数组保持活动状态,并且由于异常导致堆栈解开后,转储中并未反映该数组。而且,OOM的具体类型也很重要,例如,即使释放软引用后分配请求可能已满足,也可能发生超出一个的开销。使用+ HeapDumpOnOutOfMemoryError JVM选项创建了 – the8472

+0

转储。我认为这个选项产生的快照应该包含OOM错误出现时的所有对象和引用。快照中是否有任何参考文献缺失的机会?另外,我的应用程序没有通过大帧消耗内存 - 它不会一次尝试分配2GB对象。 – nukie

+0

是的,我认为这个选项确实包含了栈根。但OOME的确切类型仍然可能会有所作为。 – the8472

回答

1

理想的软的引用都应该投掷前被清除OOM。我怀疑存在一些程序内存泄漏..

你可能想看看这里 - How to cause soft references to be cleared in Java?

尝试-XX:SoftRefLRUPolicyMSPerMB=<value>参数限制软引用的大小,并检查是否有帮助。这可能会提供下一步的方向。

+0

谢谢@Anand Vaidya!我会尝试这个选项。 – nukie

-1

只有清除对象时,才会清除SoftReference或WeakReference。它不会阻止收集对象,但如果该对象在某处具有强引用,它将在GC之后保留。

例如

Double d = new Double(123456); 
WeakReference<Double> ref = new WeakReference<>(d); 
System.gc(); 
System.out.println(ref.get() + " == " + d); // both not null. 
+0

谢谢你,@Peter Lawrey!我明白,如果应用程序拥有强大的引用,那么弱/弱魔法将不起作用。我已经在我的堆转储中搜索每个可疑SoftReferenece对象的传入引用。我没有发现任何参考软件引用容器旁边的char数组...这是我的问题的主要观点:我有活的软对象的引用,没有强引用这个数组... – nukie