将大对象分配给null就足够了吗?我读到,如果有软引用,GC 不会释放对象。
简短的回答是肯定的。将一个大对象(所有强引用)分配给 null 就足够了——如果这样做,垃圾收集器将不再认为该对象是“强可达的”。
在您的情况下,软引用不会成为问题,因为它可以保证在OutOfMemoryError
抛出 an 之前软可访问的对象将被垃圾收集。它们很可能会阻止垃圾收集器立即收集对象(如果不这样做,它们的行为将与弱引用完全相同)。但是这种内存使用将是“临时的”,因为如果需要它来满足分配请求,它将被释放。
我应该深入清除对象、清除所有列表、将 null 分配给属性等吗?
那可能是个坏主意。如果字段值只被外部大对象引用,那么在大对象被回收时,它们也会被垃圾回收。如果它们不是,那么引用它们的代码的其他部分将不会很高兴看到您正在从他们正在使用的列表中删除成员!
在最好的情况下,这不会做任何事情,在最坏的情况下,这会破坏你的程序。不要让这种诱惑分散您的注意力,而不是解决您的对象是否是强可达性的唯一实际问题。
JaxB(我使用的是 Java6,所以 JaxB 是内置的)和软引用呢?JaxB 比旧的 JibX 编组器快,但我不知道它在内存使用方面是否更糟。
我对这些库的相对时间和空间性能并不是特别熟悉。但总的来说,对核心库采取非常强烈的“在被证明有罪之前是无辜的”态度是安全的。如果存在内存泄漏错误,它现在可能已经被发现、报告和修复(除非你正在做一些非常小众的事情)。
如果有内存泄漏,我有 99.9% 的把握是你自己的代码有问题。
我应该用 WeakReference 或类似的东西来包装大型复杂的 JaxB 类吗?
这听起来像是您可能会在问题上抛出 GC“修复”,而没有考虑实际需要什么。
如果应该弱引用JaxB 类,那么无论如何这是一个好主意(它应该已经存在)。但如果不应该,那么绝对不要这样做。弱引用更多的是整体语义的问题,不应该是你为了避免内存问题而专门引入的东西。
如果外部代码需要对对象的引用,那么它就需要引用——没有什么魔法可以让实例被垃圾收集但仍然可用。如果它不需要引用(超出某个点),那么它根本不需要引用 - 最好只是取消标准 [strong] 引用,或者让它超出范围。弱引用是一种特殊情况,通常在您无法完全控制对象不再相关的点时使用。这可能不是这里的情况。
.hprof 文件证明所有发票的所有客户数据都保留在内存中。
这表明它们确实被引用的时间超过了必要的时间。
好消息是 hprof 文件将包含引用它们的确切内容的详细信息。查看您期望已被 GC 处理的发票实例,并查看引用它并阻止它被 GC 处理的内容。然后查看有问题的类,看看您希望如何释放该引用,以及为什么在这种情况下没有释放。
所有良好的性能/内存调整都基于测量。进行堆转储并检查实例和对它们的引用是您的衡量标准。这样做并根据结果采取行动,而不是试图将东西包装在 WeakReferences 中,希望它可能会有所帮助。