Search code examples
javaweb-servicesjaxbwebspherecxf

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


We upgrade CXF from v2.2.6 to v2.7.16. When we start IBM WebSphere Application Server v7.0.0.33 in Linux machine, error is reported for 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)

Here is our current understanding:

  • This error does not occur in local Windows machine WAS7.0.0.11
  • Class jaxws_asm.RetrieveRssFeedResponse does not exist at compile time. Instead, it's generated by CXF at runtime.
  • Our application code has Java package: com/abc/mobile/service/rss
  • Class WrapperClassGenerator in org.apache.cxf/cxf-bundle.jar/2.7.16 appends Java package “jaxws_asm” at line 160:

    String pkg = new StringBuilder().append(getPackageName(method)).append(".jaxws_asm").append(anonymous ? "_an" : "").toString();

  • Our application code com.abc.mobile.service.rss.GlobalProductRssService.java has:

    @WebMethod(operationName = "retrieveRssFeed")

  • Class WrapperClassGenerator in org.apache.cxf/cxf-bundle.jar/2.7.16 appends class name “Response” at line 164:

    className = new StringBuilder().append(className).append("Response").toString();

  • We tried to add asm/asm.jar/3.3.1 to WEB-INF/lib or WAS7.0/java/jre/lib/ext. It did not help.

  • We have enabled class loading trace log by following IBM MustGather document: http://www-01.ibm.com/support/docview.wss?uid=swg21196187.

Trace log shows that "jaxws.RetrieveRssFeedResponse" is being loaded:

[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

I have not found out why the above class loading trace log loads "jaxws.RetrieveRssFeedResponse". It's highly appreciated if anyone could share any clue about how to solve this ClassFormatError.


Solution

  • Thank you so much for your help. The issue has been solved by removing "[]" from @WebResult annotation. In other words, originally our application code has:

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

    The error is solved by changing it to:

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

    What we have done is:

    • Modify CXF/2.7.16/ASMHelper.java defineClass() method to print the dynamically generated classes. Totally 302 classes have been printed out.

              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();
              }
      
    • Among all 302 generated classes, only RetrieveRssFeedResponse.class has "[]" in field name

              @XmlElement(name="RssChannelDTO[]")
              private RssChannelDTO[] RssChannelDTO[];
      
    • Modify CXF/2.7.16/ASMHelper.java to add main method (because constructor of inner class TypeHelperClassLoader is private) to call loader.defineClass() method

    • After running main method, error is reported:

              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)
      
    • Then we modified our application code to remove "[]" from @WebResult annotation. The generated RetrieveRssFeedResponse.class has:

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

    Now error is gone and our WebSphere Application Server v7.0 can be started without any error.

    Regarding the IBM class loading trace log shows only "jaxws.RetrieveRssFeedResponse", I guess the situation is:

    • IBM logging statement might ignore "_" and anything after it during logging
    • But IBM class loader can still load "jaxws_asm.RetrieveRssFeedResponse"

    Anyway, this is only my guess and I have not checked any IBM source code.