我正在尝试使用 Saxon HE 作为内置 JAXP 实现的替代品,但我遇到了各种线程问题。
出于性能原因,我将模板缓存为 DOM 文档,并像这样跨线程重用它们
TransformerFactory factory = TransformerFactory.newInstance();
Document template = getFromCache(...);
Transformer transformer = factory.newTransformer(new DOMSource(template));
transformer.transform(new DOMSource(document), streamResult);
我知道 DOM 不能保证线程安全,但 JAXP XSLT 实现工作正常,而 Saxon 完全崩溃。怎么会这样?
有没有办法让它工作但保持缓存以提高性能?
撒克逊语中的异常发生在不同的地方,但最常见的是:
java.lang.NullPointerException: null
at com.sun.org.apache.xerces.internal.dom.ParentNode.nodeListItem(ParentNode.java:786) ~[na:1.7.0_71]
at com.sun.org.apache.xerces.internal.dom.ParentNode.item(ParentNode.java:800) ~[na:1.7.0_71]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:154) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.outputElement(DOMSender.java:243) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:162) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.outputElement(DOMSender.java:243) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:162) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.outputElement(DOMSender.java:243) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:162) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.outputElement(DOMSender.java:243) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:162) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.outputElement(DOMSender.java:243) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.walkNode(DOMSender.java:162) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMSender.send(DOMSender.java:92) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.dom.DOMObjectModel.sendSource(DOMObjectModel.java:250) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.event.Sender.send(Sender.java:221) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.style.StylesheetModule.loadStylesheetModule(StylesheetModule.java:128) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.style.Compilation.compilePackage(Compilation.java:131) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.style.Compilation.compileSingletonPackage(Compilation.java:94) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.s9api.XsltCompiler.compile(XsltCompiler.java:543) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.jaxp.SaxonTransformerFactory.newTemplates(SaxonTransformerFactory.java:152) ~[Saxon-HE-9.6.0-7.jar:na]
at net.sf.saxon.jaxp.SaxonTransformerFactory.newTransformer(SaxonTransformerFactory.java:108) ~[Saxon-HE-9.6.0-7.jar:na]
最佳答案
不知道是什么原因导致您描述的错误,但 javax.xml.transform
有 Templates
类,这是在线程安全中重用样式表的官方方法方式并避免为每个转换创建和解析它们的开销。
- 使用
TransformerFactory.newTemplates(Source)
为模板源创建缓存存储Templates
而不是 DOM 文档。 - 对缓存的 Templates 对象调用
Templates.newTransformer()
以获取用于单个转换的 Transformer。
这甚至应该比您当前的解决方案更快。
<小时/>编辑:
NPE 似乎源自 Xerces 中的一行:
fNodeListCache.fChildIndex = i;
在我看来,这是一个强有力的线索,表明对 DOM 的多线程访问导致了错误,而不是 Saxon。不知道为什么默认的 TransformerFactory 在这种情况下仍然存在。
关于java - 重用 DOM 模板时 Saxon 不是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32121659/