JAXB对象转XML时随机抛出空指针及数组越界异常求助
JAXB转XML随机触发空指针/数组越界异常的解决方案
问题现象
将JAXB对象转换为XML时,随机出现以下非必现异常:
异常1:NullPointerException
Caused by: java.lang.NullPointerException: Cannot invoke "com.sun.org.apache.xml.internal.dtm.ref.ExtendedType.getNodeType()" because "this.m_extendedTypes[ExpandedNameID]" is null at com.sun.org.apache.xml.internal.dtm.ref.ExpandedNameTable.getType(ExpandedNameTable.java:348) ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.getMapping(SAXImpl.java:568) ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter.getMapping(DOMAdapter.java:105) ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter.getExpandedTypeID(DOMAdapter.java:224) ~[?:?] at die.verwandlung.GregorSamsa.applyTemplates() ~[?:?] at die.verwandlung.GregorSamsa.transform() ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:627) ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:782) ~[?:?]
异常2:ArrayIndexOutOfBoundsException(添加-XX:+ShowCodeDetailsInExceptionMessages后获取)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 71 at com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter.getExpandedTypeID(DOMAdapter.java:227) ~[?:?] at die.verwandlung.GregorSamsa.applyTemplates() ~[?:?] at die.verwandlung.GregorSamsa.transform() ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:627) ~[?:?] at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:782) ~[?:?]
环境信息
- Java版本:
openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7) OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)
- Maven依赖:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.1</version> </dependency>
解决方案
1. 修复Transformer实例的线程安全问题
JDK自带的TransformerImpl(Xalan XSLTC实现)非线程安全,多线程环境下复用同一个实例会导致内部状态混乱,触发随机异常。
解决方式:
- 每次转换时重新创建
Transformer实例; - 或用
ThreadLocal为每个线程维护独立的实例,兼顾性能与安全性。
示例代码:
// 错误:复用Transformer实例(多线程不安全) // private static Transformer transformer = TransformerFactory.newInstance().newTransformer(); // 正确:每次转换新建实例 public String jaxbToXml(Object jaxbObject) throws Exception { Transformer transformer = TransformerFactory.newInstance().newTransformer(); // 后续转换逻辑 } // 优化:用ThreadLocal减少实例创建开销 private static ThreadLocal<Transformer> transformerThreadLocal = ThreadLocal.withInitial(() -> { try { return TransformerFactory.newInstance().newTransformer(); } catch (TransformerConfigurationException e) { throw new RuntimeException(e); } }); public String jaxbToXml(Object jaxbObject) throws Exception { Transformer transformer = transformerThreadLocal.get(); // 后续转换逻辑 }
2. 升级JAXB依赖版本
当前使用的JAXB 2.3.1与Java 17存在兼容性隐患,建议升级到Jakarta EE版本的最新依赖:
<dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>4.0.2</version> <scope>runtime</scope> </dependency>
3. 替换XSLT实现库
若上述方法无效,可替换JDK默认的Xalan为Saxon实现:
<dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> <version>12.4</version> </dependency>
创建TransformerFactory时指定Saxon实现类:
TransformerFactory factory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", null); Transformer transformer = factory.newTransformer();
4. 检查JAXB对象的并发访问
确保待转换的JAXB对象未被多线程并发读写,对象内部状态不稳定也会导致转换异常。
内容的提问来源于stack exchange,提问作者Raviteja
相关产品推荐
相关产品推荐

