UnmarshallerImpl finalize() 方法导致内存泄漏

UnmarshallerImpl finalize() method leads to memory leak

我在我的多线程 Spring 应用程序中使用 webServiceTemplate。 有我的 jaxb 依赖项:

compile('javax.xml.bind:jaxb-api:2.3.0')
compile('org.glassfish.jaxb:jaxb-runtime:2.3.0')

我的应用程序发出了很多 esb 请求以及我如何注意到每个 request/response (marshalSendAndReceive) jaxb 创建了一个 UnmarshallerImpl 的实例,它实现了 finalize() 方法和这对我来说是个问题,因为创建对象的速度比终结器线程处理该对象的速度快,因此会导致内存泄漏。我想知道为什么 glassfish 实现在 UnmarshallerImpl 中仍然有 finalize(),这确实给我带来了问题。是否有任何替代版本的 glassfish jaxb 实现或类似库?如果您提供任何有用的信息,我将不胜感激。

更新: 我也尝试了 jaxb:jaxb-runtime 的 3.0.2 版 - 问题仍然存在

finalize() 方法目前已弃用,因为它没有按预期工作。你必须使用像 System.gc() 这样的方法来完成 类 否则它不会工作。

讨论:

我认为从长远来看,你最好的选择是切换到使用 XML 流式处理实现来处理你的请求。

短期内...

  • 如您所述,JAXB 参考实现在最新版本中仍使用 finalize()
  • 我认为没有办法增加 GC 终结器线程的数量。 (这可能是件好事....)
  • 此问答列出了一些替代的 JAXB 实现:
  • 由于它是开源的,您可以为您当前使用的 UnmarshallerImpl 修改 finalize() 实现。

finalize() 方法的标准实现如下所示:

@Override
@SuppressWarnings("FinalizeDeclaration")
protected void finalize() throws Throwable {
    try {
        ClassFactory.cleanCache();
    } finally {
        super.finalize();
    }
}

考虑一下......你 可能 不用清理 ClassFactory 缓存 每次 UnmarshallerImpl 实例被垃圾回收。也许这可以设置一个“全局”标志来告诉异步缓存清理器有工作要做。

当然,从长远来看,使用修改后的库会产生维护开销,因此建议尝试让上游项目接受您的更改。

更新

我应该早点查看 cleanCache,但它所做的似乎只是删除缓存在 thread-local 中的地图。这应该便宜,不应该成为争论的焦点。此外,这意味着异步执行此操作(即在不同的线程上!)不会有效。 (这也意味着下面建议的 Cleaner 方法也不起作用。)

另一种选择是根本不调用 cleanCache,但这给我们带来了通过本地线程潜在的内存泄漏!!

无论哪种方式,我(现在!)都对这种 finalize() 方法是一个瓶颈感到困惑。您确定问题不是由其他问题引起的吗?


I'm wondering why do glassfish implementation still has finalize() in UnmarshallerImpl, it really creates problems for me.

答案显而易见。他们还没有抽出时间1 修复它。


1 - 反问:1) 您为支持 GlassFish 实施支付了多少钱? 2) 有东西叫做"open source bounties"。您是否尝试过提供一个解决此问题的方法?