紧急和错误的类加载器(从私有类加载器中创建单例)

问题描述 投票:0回答:1

我有一个Java类,该类由第三方应用程序实例化为扩展。也就是说,根据第三方软件设计,像我们这样的客户将Java类注册到他们的应用程序,他们的应用程序将在适当的时间和地点安装它以执行自定义逻辑。

我们的自定义Java类需要封送和取消封送XML,为此它使用JAXB。因此,它需要一个JAXB上下文。

我在每次调用时都天真地调用JAXBContext.newInstance(MyClass.class),但不是很快发现这是内存泄漏的众所周知的秘诀。通常的做法是使一个(或最多只有几个)JAXB上下文在整个应用程序中共享。

很好,除了调用我的类的第三方应用程序之外,每个调用都是在对该调用私有的新ClassLoader实例上进行的。

因此,即使我将JAXBContext放在static字段或static HashMap<>中,它对于调用仍然是私有的!

问题

我如何在从私有ClassLoader实例实例化的类中创建要在JVM之间共享的单例?

我正在考虑两种可能的思路,但是我想就如何使它们中的任何一种或任何人使用的完全不同的方法提出建议。

我有三个想法:

  1. 在JVM类中的某个地方可以写一个对象。例如,如果System.setProperty可以写Object的实例,而不仅仅是String,则想法是创建JAXB上下文并将其放在属性中,因为可以确定System已经被实例化并自定义类加载器实例将继承它。但是System.setProperty不会采用Object值,因此我不知道执行此操作的实用方法。

  2. 以某种方式强制将类加载到我可以通过JAXB上下文存储的父类或根类加载器上。我不知道该怎么做。

  3. 使用ThreadLocal来存储JAXBContexts。我不认为每个调用都是一个全新的线程(它们可能会从线程池中重复使用),因此这可能是限制我的上下文的方式。但是如何创建ThreadLocal变量,以便其在实例之间共享?似乎这给我带来了同样的问题。

非常感谢您的帮助。由于项目的截止日期,我需要尽快对此做出答复。我无法立即为新问题设置赏金,但是当SO允许时,我会很乐意在可接受的答案上发送额外的代表。

java jaxb singleton classloader
1个回答
0
投票

听起来您的代码在第3方应用程序中被沙箱化。因此,使用staticThreadLocal将无济于事,因为它们仅存在于相同的classloader中,并且如果classloader发生了更改,则上下文将丢失。

最接近的解决方案是将您的上下文注入到应用程序代码中。这不是最好的主意,因为它可能会受到外界的影响并产生意想不到的后果。请注意,这意味着您在classloader中创建的值将保留在应用程序中,因此创建的classloader将永远不会被垃圾回收。还有JAXB jar来源的问题。我假设是从您的代码而不是第三方。因此,每次将jar加载到不同的类加载器中,以便从那里共享对象可能会出现问题,并需要一些代理。

老实说,会有很多无法预料的结果。

最好的想法是请第三者为您提供一些API来启用它。

继续之前,让我们看看其他选项:

  • 是否有使用JAXB的替代品?不会出现相同的内存泄漏问题的东西。
  • 内存泄漏严重吗?如果在第三方应用程序提供API之前出现暂时的内存泄漏,该怎么办。
  • 如果您真的想尝试

    注入

该对象,我很乐意提供帮助。但是,从经验来看,这类事情是混乱的。
© www.soinside.com 2019 - 2024. All rights reserved.