从Java 8迁移至Java 11后XSLT转换出现ClassGenException问题求助
Java 8迁移至Java 11后XSLT转换异常排查
问题背景
系统从Java 8迁移到Java 11后,XSLT响应转换功能出现异常,该功能在Java 8环境下可正常运行。XSLT与XML文件体积较大,相关代码及错误栈如下:
相关代码
public static void main(String[] args) { try { String data = readFileAsString("Sample.xml"); String dataxsl = readFileAsString("Test.xsl"); transform(data, dataxsl); } catch (Exception e) { e.printStackTrace(); } } public static String readFileAsString(String fileName) throws Exception { String data = ""; data = new String(Files.readAllBytes(Paths.get(fileName))); return data; } public static String transform(String dataXML, String inputXSL) throws TransformerConfigurationException, TransformerException { Source xslt = new StreamSource(new File(inputXSL)); Source text = new StreamSource(new File(dataXML)); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(xslt); StringWriter out = new StringWriter(); transformer.transform(text, new StreamResult(out)); return out.toString(); }
错误栈信息
com.sun.org.apache.bcel.internal.generic.ClassGenException: Not targeting 459415: nop0, but null at java.xml/com.sun.org.apache.bcel.internal.generic.BranchInstruction.updateTarget(BranchInstruction.java:217) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator.outline(MethodGenerator.java:1721) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator.outlineChunks(MethodGenerator.java:1168) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator.getGeneratedMethods(MethodGenerator.java:1882) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator.addMethod(ClassGenerator.java:137) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.Mode.compileNamedTemplate(Mode.java:536) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.Mode.compileTemplates(Mode.java:545) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.Mode.compileApplyTemplates(Mode.java:804) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet.compileModes(Stylesheet.java:622) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet.translate(Stylesheet.java:735) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC.compile(XSLTC.java:503) at java.xml/com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC.compile(XSLTC.java:570) at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:1018) at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:817)
异常成因分析
代码逻辑错误:
transform方法接收的是XML和XSLT的字符串内容,但代码错误地将这些字符串当作文件名传入StreamSource,而非直接使用字符串内容。这个问题在Java 8中可能未触发明显异常,但Java 11的文件处理或XSLT实现更严格,间接加剧了后续的字节码生成问题。XSLTC字节码生成兼容问题:Java 11中默认的
TransformerFactory是Xalan的XSLTC实现,它依赖BCEL库生成字节码处理XSLT。当XSLT文件体积大、逻辑复杂时,生成的方法字节码长度可能超出内部处理限制,或者分支指令的目标地址处理出现异常,从而抛出ClassGenException。此外,Java 8到Java 11的模块化变更,导致BCEL的内部调用逻辑调整,进一步触发了该兼容问题。
解决方向
- 修正代码逻辑:将字符串内容直接通过
StringReader传入StreamSource,替换原有的File方式:
public static String transform(String dataXML, String inputXSL) throws TransformerConfigurationException, TransformerException { Source xslt = new StreamSource(new StringReader(inputXSL)); Source text = new StreamSource(new StringReader(dataXML)); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(xslt); StringWriter out = new StringWriter(); transformer.transform(text, new StreamResult(out)); return out.toString(); }
- 切换到Xalan解释器模式:避免使用XSLTC的字节码编译,指定传统的解释器实现:
- 代码中设置:
TransformerFactory factory = TransformerFactory.newInstance("org.apache.xalan.processor.TransformerFactoryImpl", null); - 或添加JVM参数:
-Djavax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl
- 代码中设置:
- 升级Xalan版本:替换JDK自带的Xalan为最新独立版本,独立版本对Java 11的兼容性更好,能解决部分字节码生成的兼容问题。
内容的提问来源于stack exchange,提问作者Mahajan
相关产品推荐
相关产品推荐

