Java 我可以先占类路径吗?

Java 我可以先占类路径吗?,java,classpath,Java,Classpath,我有一个图书馆,是一个商业产品的临时扩展。该产品已有几年历史,使用Sun的JAXB-2.0库 我的库使用JAXB,我有一个非常奇怪的错误 我发现这是由旧库中的一个bug引起的。我可以先占加载的类以强制扩展使用该类的“正确”版本吗 编辑:随着我的加入,我正在打包JAXB-2.2.5(它在我的插件的类路径上被引用),但我怀疑现有的JVM已经加载了该类的2.0版本,这引起了我的心痛 每个Java类都由类加载器加载。一旦类被加载,就不可能从类加载器中卸载该类。摆脱类的唯一可能性是释放对该类装入器已装入的

我有一个图书馆,是一个商业产品的临时扩展。该产品已有几年历史,使用Sun的JAXB-2.0库

我的库使用JAXB,我有一个非常奇怪的错误

我发现这是由旧库中的一个bug引起的。我可以先占加载的类以强制扩展使用该类的“正确”版本吗


编辑:随着我的加入,我正在打包JAXB-2.2.5(它在我的插件的类路径上被引用),但我怀疑现有的JVM已经加载了该类的2.0版本,这引起了我的心痛

每个Java
类都由
类加载器加载。一旦类被加载,就不可能从类加载器中卸载该类。摆脱类的唯一可能性是释放对该类装入器已装入的类的所有实例的所有引用,以及对类装入器本身的引用

类装入器按层次结构组织。默认情况下,每个类加载器首先要求其父类加载器加载一个类。只有当父类加载器无法加载类时,原始类加载器才会尝试加载。您可以重写此行为以加载JAXB类

但这并不是那么容易:假设您有一个类
MyObject
,它是用类装入器a装入的。如果您用类装入器B装入同一个类,那么
MyObject.class!=这两个类的MyObject.class
。这也会导致
MyObject o=getMyObjectFromOtherClassLoader()
抛出
ClassCastException

Stackoverflow提供。剩下的唯一一件事是在类装入器激活之前,在不装入类的情况下运行应用程序。为此,您可以执行以下操作(未经验证的代码):

此包装器将使用首先考虑库的子类装入器启动类
com.company.Name
的普通应用程序的
publicstaticvoidmain(String[])
方法。确保在显式加载之前不加载
com.company.Main
。(这就是反思性方法。)


你在使用Maven这样的构建工具吗?不能明确排除旧库的依赖项吗?旧的应用程序可能与旧的JAXB存在类似的问题。

您可以使用自定义类加载器隐藏加载的类路径,该加载器不委托给其父级,而是尝试自己加载尽可能多的类。通过这种方式,您至少可以发现这是否是原因。@raphw我对JVM的理解有点深。你能在这一点上展开一点吗?注释字段有点短。请看下面的答案。最终,我用更新的版本替换了原有的库。然而,这是一个黑客,这是“正确的”解决方案;我很高兴你在这里分享了这些信息。
class StartupWrapper {

  public static void main(String[] args) throws Exception {
    Class.forName("com.company.Main", true, 
        new ParentLastURLClassLoader(Arrays.asList(new URL("./new-JAXB.jar"))))
      .getMethod("main", String[].class).invoke(null, args);
  }
}