Java 为什么可以';JAXB在ApacheFelix中运行时是否找到我的JAXB.index?
它就在那里,在它应该索引的包中。尽管如此,当我打电话的时候Java 为什么可以';JAXB在ApacheFelix中运行时是否找到我的JAXB.index?,java,jaxb,osgi,apache-felix,Java,Jaxb,Osgi,Apache Felix,它就在那里,在它应该索引的包中。尽管如此,当我打电话的时候 JAXBContext jc = JAXBContext.newInstance("my.package.name"); 我有一个例外说 “my.package.name”不包含ObjectFactory.class或jaxb.index 尽管它确实包含了这两个方面 什么是有效的,但不是我想要的,是 JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.c
JAXBContext jc = JAXBContext.newInstance("my.package.name");
我有一个例外说
“my.package.name”不包含ObjectFactory.class或jaxb.index
尽管它确实包含了这两个方面
什么是有效的,但不是我想要的,是
JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);
这个来自其他人的问题出现在相当多的邮件列表和论坛上,但似乎没有得到答案
我在OpenJDK 6上运行这个,所以我得到了源代码包并将我的调试器放入库中。它首先查找jaxb.properties,然后查找系统属性,如果找不到,它会尝试使用com.sun.internal.xml.bind.v2.ContextFactory创建默认上下文。在那里,会抛出异常(在ContextFactor.createContext(String ClassLoader,Map)
中),但我看不到发生了什么,因为源代码不在这里
预计到达时间:
从ContentFactory的源代码来看,我发现这可能是一段无法按预期工作的代码:
/**
* Look for jaxb.index file in the specified package and load it's contents
*
* @param pkg package name to search in
* @param classLoader ClassLoader to search in
* @return a List of Class objects to load, null if there weren't any
* @throws IOException if there is an error reading the index file
* @throws JAXBException if there are any errors in the index file
*/
private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
final String resource = pkg.replace('.', '/') + "/jaxb.index";
final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);
if (resourceAsStream == null) {
return null;
}
/**
*在指定的包中查找jaxb.index文件并加载其内容
*
*@param pkg要搜索的包名
*@param classLoader要搜索的类加载器
*@返回要加载的类对象列表,如果没有则为null
*如果读取索引文件时出错,@将引发IOException
*如果索引文件中有任何错误,@jaxbeexception
*/
私有静态列表loadIndexedClass(字符串pkg,类加载器类加载器)抛出IOException,JAXBEException{
最终字符串资源=pkg.replace('.','/')+“/jaxb.index”;
final InputStream resourceAsStream=classLoader.getResourceAsStream(资源);
if(resourceAsStream==null){
返回null;
}
从我的经验来看,我猜这与正在运行的OSGi容器的类加载机制有关。不幸的是,我在这里仍然有点不了解。编辑2: 我曾经在我的应用程序中遇到过类似的奇怪类加载问题。如果我将其作为普通应用程序运行,一切正常,但当我将其作为Windows服务调用时,它开始失败,并出现ClassNotFoundExceptions。分析表明,线程的类加载程序以某种方式为空。我通过设置SystemClassLoade解决了问题螺纹上的r:
// ...
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
thread.start();
// ...
但不知道您的容器是否允许进行此类更改。好的,这需要进行一些挖掘,但答案并不令人惊讶,甚至没有那么复杂: JAXB找不到JAXB.index,因为默认情况下,
newInstance(String)
使用当前线程的类加载器(由thread.getContextClassLoader()
返回)。这在Felix内部不起作用,因为OSGi捆绑包和框架的线程有单独的类加载器。
解决方案是从某处获得一个合适的类加载器,并使用newInstance(String,ClassLoader)
。我从包含jaxb.index
的包中的一个类中获得了一个合适的类加载器,出于灵活性原因,一个明智的选择可能是ObjectFactory
:
ClassLoader cl = my.package.name.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("my.package.name", cl);
也许您还可以找到
包
实例正在使用的类加载器,但我不知道如何找到,而且上面的解决方案对我来说似乎是安全的。我在处理的项目中遇到了类似的问题。阅读后,我意识到JAXBContext无法找到包含jaxb.index的包
我会尽量把这件事说清楚
我们有
Bundle A
-- com.a
A.java
aMethod()
{
B.bMethod("com.c.C");
}
MANIFEST.MF
Import-Package: com.b, com.c
Bundle B
-- com.b
B.java
bmethod(String className)
{
Class clazz = Class.forName(className);
}
Export-Package: com.b
Bundle C
-- com.c
C.java
c()
{
System.out.println("hello i am C");
}
Export-Package: com.c
与JAXB相关的类是JAXBContext,方法是newInstance()
如果您熟悉OSGi包限制,那么现在必须非常清楚,包B没有导入包com.c,即类c对于类B不可见,因此它无法实例化c
解决方案是将类加载器传递给b方法。此类加载器应来自导入com.c的捆绑包。在这种情况下,我们可以传递a.class.getClassLoader(),因为捆绑包a导入com.c
希望这是有帮助的。我刚刚遇到了这个问题。对我来说,解决方案是使用IBM的JRE而不是Oracle的。似乎JAXB实现在这一点上更为OSGI友好。对于同一个问题,我通过手动将包放入导入来解决它。如果您在项目中使用maven,那么只需使用图书馆:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-osgi</artifactId>
<version>2.2.7</version>
</dependency>
com.sun.xml.bind
jaxb osgi
2.2.7
它是为Glasfish服务器创建的,但也与Tomcat一起使用(选中)。
有了这个库,您可以轻松地将JAXB与OSGI捆绑包一起使用。我成功地解决了这个问题,将包含
ObjectFactory
的生成类包添加到捆绑包定义的
部分,再加上org.jvnet.jaxb2\u commons.
我的解决方案是:
JAXBContext context=JAXBContext.newInstance(newclass[]{“my.package.name”})
或
JAXBContext context=JAXBContext.newInstance(newclass[]{Class.getName()})
或
完整的解决方案:
public static <T> T deserializeFile(Class<T> _class, String _xml) {
try {
JAXBContext context = JAXBContext.newInstance(new Class[]{_class});
Unmarshaller um = context.createUnmarshaller();
File file = new File(_xml);
Object obj = um.unmarshal(file);
return _class.cast(obj);
} catch (JAXBException exc) {
return null;
}
}
publicstatict反序列化文件(Class\u Class,String\uxml){
试一试{
JAXBContext context=JAXBContext.newInstance(新类[]{u Class});
Unmarshaller um=context.createUnmarshaller();
File File=新文件(_xml);
Object obj=um.unmarshal(文件);
返回类铸件(obj);
}捕获(JAXBEException exc){
返回null;
}
}
100%有效可能还有另一种情况会导致此问题 当您安装并启动一个包,该包导出包含jaxb.i
<dependency>
<groupId>com.myCompany</groupId>
<artifactId>my-module-name</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>