2

I have a library that is a drop-in extension of a commercial product. That product is several years old and uses Sun's JAXB-2.0 libraries.

My library uses JAXB and I'm having a very bizarre error. What might cause "JAXBElement Does not have a no-arg default constructor"?

I've discovered that this is caused by a bug in the older library. Can I pre-empt the loaded classes to force my extension to use the "right" version of the class?

Edit: Along with my drop-in I'm packing JAXB-2.2.5 (which is referenced on the classpath of my plugin) but I suspect that the existing JVM has already loaded 2.0 versions of the class, causing my heartache.

4

1 回答 1

2

每个 JavaClass都由一个ClassLoader. 一旦加载了一个类,就不可能从类加载器中卸载这个类。摆脱一个类的唯一可能性是放弃对该类加载器已加载的类的所有实例的所有引用以及对类加载器本身的引用

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

但这并不容易:假设您有一个MyObject使用类加载器A加载的类。如果您使用类加载器B加载相同的类,那么MyObject.class != MyObject.class对于这两个类。这也会导致MyObject o = getMyObjectFromOtherClassLoader()抛出ClassCastException.

Stackoverflow 提供了一个类加载器的示例。剩下的唯一事情是在类加载器激活之前运行您的应用程序而不加载类。对此,您可以执行以下操作(未经验证的代码):

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);
  }
}

这个包装器将使用首先考虑您的库的子优先public static void main(String[])类加载器来启动您的普通应用程序的类方法。确保在显式加载之前不加载。(因此是反射方法。)com.company.Namecom.company.Main

你在使用像 Maven 这样的构建工具吗?你不能明确排除旧图书馆的依赖吗?旧应用程序在新 JAXB 中可能会遇到与您的应用程序在旧 JAXB 中类似的问题。

于 2013-10-30T21:58:53.140 回答