java - 重用 DOM 模板时 Saxon 不是线程安全的

标签 java saxon

我正在尝试使用 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.transformTemplates 类,这是在线程安全中重用样式表的官方方法方式并避免为每个转换创建和解析它们的开销。

  1. 使用 TransformerFactory.newTemplates(Source) 为模板源创建缓存存储 Templates 而不是 DOM 文档。
  2. 对缓存的 Templates 对象调用 Templates.newTransformer() 以获取用于单个转换的 Transformer。

这甚至应该比您当前的解决方案更快。

<小时/>

编辑:

NPE 似乎源自 Xerces 中的一行:

fNodeListCache.fChildIndex = i;

在我看来,这是一个强有力的线索,表明对 DOM 的多线程访问导致了错误,而不是 Saxon。不知道为什么默认的 TransformerFactory 在这种情况下仍然存在。

关于java - 重用 DOM 模板时 Saxon 不是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32121659/

相关文章:

java - 比较存储在字节数组中的 double 的最有效方法?

java - 使用 AdMob 旋转时 Android 应用程序崩溃

xml - "Content is not allowed in prolog"错误但在 XML 声明之前什么也没有

xslt - 一个关于 XSLT 的初学者问题

java - XSLT 在 Saxon 中生成带有未声明的 namespace 前缀的输出。错误 XTSE1430 : Namespace prefix exsl is undeclared

java - Kubernetes SharedInformer 用法和定义

java - 如何将字符串作为代码运行?

java - Gson:序列化 java.nio.Path 导致 StackOverflowError

xquery - 调用 XQuery 更新函数会导致错误 如果任何子表达式正在更新,则所有子表达式都必须更新

java - 如何使用 XML 转换器以 Java 对象作为参数?