当日志插件中,有一功能是打印日志文件的功能,今天调试时,遇到上述异常,记录下排查过程和解决办法。
问题出在调用下面的方法上:
this.processSysLog(log, syslog, JSON.toJSONString(result));
JSON.toJSONString(Object object)异常记录如下:
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
可以看到,代码在执行到ASMClassLoader.defineClassPublic这个方法时报错了,报的错是:
Caused by: java.lang.ClassFormatError: JVMCFRE042 bytecode array size > 65535; class=Serializer_57, offset=53261
字节数组超长,这个长度65535,很显然是长度规定了2的16次方(65536),也就是64K大小。
再来看看ASMClassLoader这个类,这个类继承了java的类装载器ClassLoader,fastjson内嵌了ASM框架来动态生成类;
public class ASMClassLoader extends ClassLoader {
并且报错的方法其实就是调用了ClassLoader的类定义方法defineClass,本质上调用的是JVM的native功能:
public Class<?> defineClassPublic(String name, byte[] b, int off, int len) throws ClassFormatError {
Class<?> clazz = defineClass(name, b, off, len, DOMAIN);
return clazz;
}
这里其实也就是传的需要生成的类的字节码,在这里也就对应着我们需要转换成JSON串的对象类的字节码,所以这个报错应该就是对象类字节码超长了,也就是类里面的东西太多了,试着删掉这个bean里的一些变量,测试一把,果然不报错了。
至此,问题就定位清晰了,就是bean里面字段太多,导致序列化后,生成class文件的方法超长,也就导致转为json字符串失败了,这个除了拆分bean,貌似也没什么好办法了,而且这个bean确实太大了,拆开可读性也会好很多