如何从一个私有的classloader中创建一个单子?

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

我有一个Java类,会被第三方应用程序作为扩展实例化。 也就是说,按照第三方软件的设计,像我们这样的客户将我们的Java类注册到他们的应用程序中,他们的应用程序将在正确的地点和时间安装它来执行自定义逻辑。

我们的自定义Java类需要对XML进行marshal和unmarshal,为此它使用了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变量,使其在所有实例中共享? 这似乎让我遇到了同样的问题。

java jaxb singleton classloader
1个回答
0
投票

听起来你的代码在第三方应用中是被沙盒化的。所以使用 staticThreadLocal 不会有任何帮助,因为它只存在于同一个地方。classloader如果 classloader 被改变了... 那么上下文就会丢失。

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

说实话,可能会有这么多不可预见的结果。

最好的办法是要求第三方为你提供一些API来实现。

在继续之前,我们先看看其他的选择。

  • 是否有一个替代使用 JAXB? 不会出现同样的内存泄漏问题的东西。
  • 是内存泄漏 严重吗?在第三方应用提供API之前,如果出现暂时的内存泄漏怎么办。

如果你真的想尝试 注射 的对象,我很乐意帮忙。但是,根据经验,这种事情很乱。

© www.soinside.com 2019 - 2024. All rights reserved.