com.alibaba.fastjson.JSONException: create asm serializer error

Keywords: Java JSON jvm

When the log plug-in, a function is to print the log file function, debugging today, encountered the above exception, record the investigation process and solutions.

The problem lies in calling the following methods:

this.processSysLog(log, syslog, JSON.toJSONString(result));

The JSON. to JSONString (Object object) exception record is as follows:

Caused by: com.alibaba.fastjson.JSONException: write javaBean error
    at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:234)
    at Serializer_5.write1(Unknown Source)
    at Serializer_5.write(Unknown Source)
    at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:369)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:393)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:567)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at 
    ... 81 common frames omitted
Caused by: com.alibaba.fastjson.JSONException: create asm serializer error, class class com.feifei.bean.TestBean
    at com.alibaba.fastjson.serializer.SerializeConfig.createJavaBeanSerializer(SerializeConfig.java:113)
    at com.alibaba.fastjson.serializer.JSONSerializer.getObjectWriter(JSONSerializer.java:527)
    at com.alibaba.fastjson.serializer.ListSerializer.write(ListSerializer.java:81)
    at com.alibaba.fastjson.serializer.ObjectFieldSerializer.writeValue(ObjectFieldSerializer.java:118)
    at com.alibaba.fastjson.serializer.ObjectFieldSerializer.writeProperty(ObjectFieldSerializer.java:67)
    at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:216)
    ... 94 common frames omitted
Caused by: java.lang.ClassFormatError: JVMCFRE042 bytecode array size > 65535; class=Serializer_57, offset=53261
    at java.lang.ClassLoader.defineClassImpl(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:275)
    at com.alibaba.fastjson.util.ASMClassLoader.defineClassPublic(ASMClassLoader.java:42)
    at com.alibaba.fastjson.serializer.ASMSerializerFactory.createJavaBeanSerializer(ASMSerializerFactory.java:287)
    at com.alibaba.fastjson.serializer.ASMSerializerFactory.createJavaBeanSerializer(ASMSerializerFactory.java:36)
    at com.alibaba.fastjson.serializer.SerializeConfig.createASMSerializer(SerializeConfig.java:78)
    at com.alibaba.fastjson.serializer.SerializeConfig.createJavaBeanSerializer(SerializeConfig.java:106)
    ... 99 common frames omitted

As you can see, the code is wrong when executing the method of ASMClassLoader.defineClassPublic. The error is:

Caused by: java.lang.ClassFormatError: JVMCFRE042 bytecode array size > 65535; class=Serializer_57, offset=53261

The byte array is too long. This length is 65535. It is obvious that the length of the byte array specifies the 16th power of 2 (65536), which is the size of 64K.

Let's look at the class ASMClassLoader, which inherits the class loader ClassLoader of java, and fastjson embedded the ASM framework to generate classes dynamically.

public class ASMClassLoader extends ClassLoader {

And the way to report errors is to call ClassLoader's class definition method defineClass, which essentially calls JVM's native function:

public Class<?> defineClassPublic(String name, byte[] b, int off, int len) throws ClassFormatError {
        Class<?> clazz = defineClass(name, b, off, len, DOMAIN);
    return clazz;
}

In fact, this is the bytecode of the class that needs to be generated, which corresponds to the bytecode of the object class that we need to convert into JSON string. So the error should be that the bytecode of the object class is too long, that is, there are too many things in the class. Try to delete some variables in the bean and test them, and sure enough, the error will not be reported.

So far, the problem is clear, that is, there are too many fields in the bean, which leads to the method of generating class file is too long after serialization, which leads to the failure of converting to json string. Apart from splitting beans, there seems to be no good way to solve the problem. Moreover, the bean is really too big, and the splitting readability will be much better.

Posted by mattcass on Thu, 16 May 2019 04:25:02 -0700