CXF 2.7.16: ClassFormatError: JVMCFRE114 field name is invalid; jaxws_asm

CXF 2.7.16: ClassFormatError: JVMCFRE114 field name is invalid; jaxws_asm

我们将 CXF 从 v2.2.6 升级到 v2.7.16。当我们在 Linux 机器上启动 IBM WebSphere Application Server v7.0.0.33 时,报错 jaxws_asm/RetrieveRssFeedResponse:

Caused by: java.lang.ClassFormatError: JVMCFRE114 field name is invalid; class=com/abc/mobile/service/rss/jaxws_asm/RetrieveRssFeedResponse, offset=0
    at java.lang.ClassLoader.defineClassImpl(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:287)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:224)
    at org.apache.cxf.common.util.ASMHelper$TypeHelperClassLoader.defineClass(ASMHelper.java:367)
    at org.apache.cxf.common.util.ASMHelper.loadClass(ASMHelper.java:316)
    at org.apache.cxf.jaxws.WrapperClassGenerator.createWrapperClass(WrapperClassGenerator.java:229)

这是我们目前的理解:

跟踪日志显示“jaxws.RetrieveRssFeedResponse”正在加载:

[1/5/16 11:39:04:447 EST] 00000014 CompoundClass >  loadClass com.abc.mobile.service.rss.jaxws.RetrieveRssFeedResponse this=com.ibm.ws.classloader.CompoundClassLoader@736d736d[PL][war:US-EAR/US.war] Entry
[1/5/16 11:39:04:447 EST] 00000014 CompoundClass >  loadClass com.abc.mobile.service.rss.jaxws.RetrieveRssFeedResponse this=com.ibm.ws.classloader.CompoundClassLoader@70207020[app:US-EAR] Entry
[1/5/16 11:39:04:448 EST] 00000014 CompoundClass <  loadClass com.abc.mobile.service.rss.jaxws.RetrieveRssFeedResponse failed Exit
[1/5/16 11:39:04:448 EST] 00000014 CompoundClass <  loadClass com.abc.mobile.service.rss.jaxws.RetrieveRssFeedResponse failed Exit

我还没有找到为什么上面的class加载跟踪日志会加载“jaxws.RetrieveRssFeedResponse”。如果有人可以分享有关如何解决此 ClassFormatError.

的任何线索,我们将不胜感激

非常感谢您的帮助。该问题已通过从 @WebResult 注释中删除“[]”得到解决。也就是说,原来我们的应用代码有:

    @WebMethod(operationName = "retrieveRssFeed")
    @WebResult(name = "RssChannelDTO[]")

改成:

错误解决
    @WebMethod(operationName = "retrieveRssFeed")
    @WebResult(name = "RssChannelDTO")

我们所做的是:

  • 修改CXF/2.7.16/ASMHelper.javadefineClass()方法打印动态生成的classes。一共打印了302 classes

            System.out.println("***********ASMHelper.TypeHelperClassLoader.defineClass(): " + name.replace('/', '.'));
            try {
                java.io.FileOutputStream fos = new java.io.FileOutputStream(name.replace('/', '.') + ".class");
                fos.write(bytes);
                fos.close();
            } catch (java.io.IOException ioe) {
                ioe.printStackTrace();
            }
    
  • 在所有生成的 302 个 class 中,只有 RetrieveRssFeedResponse.class 字段名称中有“[]”

            @XmlElement(name="RssChannelDTO[]")
            private RssChannelDTO[] RssChannelDTO[];
    
  • 修改CXF/2.7.16/ASMHelper.java增加main方法(因为内部classTypeHelperClassLoader的构造函数是私有的)调用loader.defineClass( ) 方法

  • 运行main方法后,报错:

            Exception in thread "main" java.lang.ClassFormatError: Illegal field name "RssChannelDTO[]" in class RetrieveRssFeedResponse
                at java.lang.ClassLoader.defineClass1(Native Method)
                at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
                at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
                at org.apache.cxf.common.util.ASMHelper$TypeHelperClassLoader.defineClass(ASMHelper.java:377)
                at org.apache.cxf.common.util.ASMHelper.main(ASMHelper.java:513)
    
  • 然后我们修改了我们的应用程序代码以从@WebResult 注释中删除“[]”。生成的 RetrieveRssFeedResponse.class 有:

            @XmlElement(name="RssChannelDTO")
            private RssChannelDTO[] RssChannelDTO;
    

现在错误消失了,我们的 WebSphere Application Server v7.0 可以正常启动了。

关于IBM class加载跟踪日志只显示"jaxws.RetrieveRssFeedResponse",我估计情况是:

  • IBM 日志记录语句在记录期间可能会忽略“_”及其后的任何内容
  • 但是 IBM class loader 仍然可以加载 "jaxws_asm.RetrieveRssFeedResponse"

无论如何,这只是我的猜测,我没有检查任何 IBM 源代码。