Eclipse/OSGI、Java11、JAXB和类加载器
我有两个Java模块,A和B。A提供了一个核心模型,其中包含JAXB注释和帮助器类,用于创建JAXB内容(创建上下文、编组、解组等)。B提供了其他类,这些类通过@xmlanyement(lax=true)包含在模型中,因此必须添加到JAXB上下文中 这在普通Java-B的classloader中运行良好,它可以看到所有相关的类,并可以使用以下内容实例化JAXB上下文:Eclipse/OSGI、Java11、JAXB和类加载器,java,eclipse,jaxb,osgi,classloader,Java,Eclipse,Jaxb,Osgi,Classloader,我有两个Java模块,A和B。A提供了一个核心模型,其中包含JAXB注释和帮助器类,用于创建JAXB内容(创建上下文、编组、解组等)。B提供了其他类,这些类通过@xmlanyement(lax=true)包含在模型中,因此必须添加到JAXB上下文中 这在普通Java-B的classloader中运行良好,它可以看到所有相关的类,并可以使用以下内容实例化JAXB上下文: JAXBContext.newInstance(RootFromA.class, RootFromB.class) 现在我也在
JAXBContext.newInstance(RootFromA.class, RootFromB.class)
现在我也在尝试OSGI(B是Eclipse插件,A是核心库,普通Java命令行模块C也将使用它)。经过多次尝试和错误,我已经设法让A和B通过OSGI包导入来查看JAXB API和实现。问题在于,如上所述调用newInstance似乎使用了JAXB API的类加载器,而不是RootFromA的类加载器,当然也不是RootFromB的类加载器。因此,它甚至无法看到JAXB实现,并抱怨找不到ContextFactory类
我已通过调用不同版本的newInstance解决了此问题:
JAXBContext.newInstance(
RootFromA.class.getPackageName()
+ ":" + RootFromB.class.getPackageName(),
RootFromB.class.getClassLoader())
我不喜欢这样,有两个原因:
我错过什么了吗?有没有“更好”的方法?为什么没有一个newInstance方法来接受一组上下文类和一个类加载器呢?看来我找到了一个解决方案。我的问题是为了两个不同的目的处理类加载器:
Class[] myClasses = getModelClasses(); // gather all model classes, which may have different classloaders
Thread thread = Thread.currentThread();
ClassLoader originalClassLoader = thread.getContextClassLoader();
thread.setContextClassLoader(getClass().getClassLoader()); // my own bundle's classloader
JAXBContext context = JAXBContext.newInstance(myClasses);
thread.setContextClassLoader(originalClassLoader); // reset context classloader
上下文类加载器操作可以包装在一个自动关闭的文件中,这样我就可以简单地将JAXBContext实例化包装在try-with-resources块中。Update:我已经在测试项目中添加了一个扩展插件,上面的第1点确实令人担忧。我可以通过Platform.getBundle().loadClass()从扩展点加载贡献的模型类并实例化它们,但我不能将它们添加到JAXB上下文中,因为它们显然来自不同的类加载器,在创建JAXBContext时,我只能指定一个类加载器和包名。多年来,我一直在纯Java中使用模块化JAXB结构——在Eclipse中肯定有合适的方法来实现这一点吗?