线程被阻塞的 JAXB

5
即使每次创建新的“unmarshaller”对象,线程仍然会被阻塞。请帮忙解决。
"http-80-3" daemon prio=10 tid=0x000000004fabe800 nid=0x7147 waiting for monitor entry [0x0000000042401000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:457)
    - waiting to lock <0x00000000c02cce20> (a sun.net.www.protocol.jar.URLJarFile)
    at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:475)
    at java.io.FilterInputStream.read(FilterInputStream.java:66)
    at java.io.DataInputStream.readInt(DataInputStream.java:371)
    at com.sun.xml.internal.bind.v2.bytecode.ClassTailor.tailor(ClassTailor.java:165)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.AccessorInjector.tailor(AccessorInjector.java:108)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:68)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:156)
    at com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:245)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.<init>(SingleElementNodeProperty.java:79)
    at sun.reflect.GeneratedConstructorAccessor21.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:145)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:479)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:305)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
    at sun.reflect.GeneratedMethodAccessor47.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:376)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)

public static <T> T unmarshal(Class<? extends T> type, InputStream in) { try { JAXBContext ctx = JAXBContext.newInstance(type); Unmarshaller unMarshaller = ctx.createUnmarshaller(); return unMarshaller.unmarshal(new StreamSource(in), type).getValue(); } catch (JAXBException ex) { LOGGER.warn("无法解组类型:" + type, ex); throw new IllegalArgumentException("无法解组类型:" + type.getName() + "。", ex); } } - Abhishek Gayakwad
你是每次都在创建 JAXBContext 吗?JAXBContext 是线程安全的,应该只创建一次并重复使用。Unmarshaller 不是线程安全的,每个线程应该创建一个新的。 - bdoughan
感谢Blaise Doughan,我按照您所提到的方法进行了操作,问题在于我们为每种类型创建了一个JAXBContext,在我们的系统中有许多这样的对象。现在我正在维护一个映射(ConcurrentHashMap<Class,JAXBContext> contexts),并使用线程安全代码来存储所有JAXBContexts(每种类型一个)。目前它运行得很好。还有其他更好的建议吗? - Abhishek Gayakwad
2个回答

11

(将我的评论转为答案)

您每次都创建一个JAXBContext吗?JAXBContext是线程安全的,应该只创建一次并重复使用。Unmarshaller不是线程安全的,应该为每个线程创建一个新的。

现在我正在维护一个映射(ConcurrentHashMap contexts),其中包装了线程安全代码,以存储所有JAXBContexts(每个类型一个)。目前它运行良好。是否有其他更好的建议?

这取决于您的应用程序。您也可以在许多类上创建一个JAXBContext

JAXBContext jc = JAXBContext.newInstance(A.class, B.class, C.class, D.class);
或者
JAXBContext jc = JAXBContext.newInstance("com.foo:org.bar");

1
旧的线程,所以不知道你是否能看到这个 Blaise,但是通过为可编组类创建一个 JAXBContext 实例或为多个可编组类创建一个 JAXBContext 是否可以获得任何显著的性能改进。 - CodeClimber
1
@CodeClimber - 每当创建JAXBContext时,都会发生提供程序查找机制。从性能上讲,最好在N个类上创建1个上下文,而不是每个类上创建N个上下文。 - bdoughan
谢谢。附言:“marshable”是一个词吗?还是应该是“marshalable”? - CodeClimber
@CodeClimber 我不确定这两个单词是否存在,但我会说 "可编组的" :)。 - bdoughan

1

在开发多线程Web应用程序时,可靠的性能故障排除JAXB Context的好解决方案是创建一个提供JAXBContext的单例,如下所示:

class JAXBContextServletHelper  extends HttpServlet {
    static final JAXBContext context = initContext();
    private static JAXBContext initContext() {
        return JAXBContext.newInstance(MyClasse1.class,MyClasse2.class);
    }
}

使用 ";" 调用它。
JAXBContext context =   JAXBContextServletHelper. initContext();
Unmarshaller u = context.createUnmarshaller();
        u.unmarshal(...);

如果您想了解更多关于这个问题的细节,请访问java.net上的JAXB教程此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接