之前在线上用的版本是fastjson-1.2.7.jar 一切正常,更换以后时间解析看似一切正常。
因为在系统中设计json反序列化的地方比较多,刚刚放到生产环境,app那边的接口报错了
java.lang.ClassFormatError: Invalid method Code length 66865 in class file com/alibaba/fastjson/serializer/ASMSerializer_6_UserKdlb
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at com.alibaba.fastjson.util.ASMClassLoader.defineClassPublic(ASMClassLoader.java:174)
at com.alibaba.fastjson.serializer.ASMSerializerFactory.createJavaBeanSerializer(ASMSerializerFactory.java:396)
at com.alibaba.fastjson.serializer.SerializeConfig.createASMSerializer(SerializeConfig.java:95)
at com.alibaba.fastjson.serializer.SerializeConfig.createJavaBeanSerializer(SerializeConfig.java:163)
at com.alibaba.fastjson.serializer.SerializeConfig.createJavaBeanSerializer(SerializeConfig.java:117)
at com.alibaba.fastjson.serializer.SerializeConfig.getObjectWriter(SerializeConfig.java:504)
at com.alibaba.fastjson.serializer.SerializeConfig.getObjectWriter(SerializeConfig.java:320)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:884)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:812)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:853)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:812)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:840)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:812)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:892)
at com.alibaba.fastjson.JSON.toJSON(JSON.java:812)
at com.xxx.pointlocationapp.controller.AppPointLocationControllerNew.getList(AppPointLocationControllerNew.java:204)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1152)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
找到相应的方法,签名如下
@RequestMapping("/list")
@ResponseBody
public JSONObject getList(@RequestBody String body, UserKdlb userKdlb, Pager<UserKdlb> pagers,
HttpServletRequest request, HttpServletResponse response) {
AppUtils.setHeader(request, response);
JSONObject obj = null;
ReturnParam rp = new ReturnParam();
...
obj = (JSONObject) JSON.toJSON(rp);
return obj;
}
这是一直运行的代码,按常理来说如果有bug早就反应出来了。
codereview发现,这个json对象之前的步骤中插入一个list,相关代码如下
List<UserKdlb> list = null; public class UserKdlb implements Serializable{ private Byte pre_distribution_work_for_outsourcing_companies;//建设外包公司预分配工作
private String company_employees_must_complete_the_commissioning_time;//公司员工调试必须完成时间 //室外周报关联查询列表添加页面显示字段
private Integer number_of_points_entered_into_outdoor_construction_sites; //室外点位资料字表对应字段;
private List<PointLocationFaultRecord> ltPLFR; //管理合同表查询此字段进而在页面显示样式,点位表f_htbh 存的可能是合同关联字段,也可能是项目关联字段,所以要查询两次;
private String whxfxq; //关联点位子记录最新一条添加记录显示列
private String estimated_date_of_repair;//预计修复日期
private String dname;//同一故障点位名称
private String application_stop_instruction;//申请停用说明
private String son_estimated_date_of_repair;//子记录最新预计修复日期
private String son_application_stop_instruction;//子记录申请停用说明
//最新连接时间
private String ping_time; private int prediction_and_debugging_amount;//(预-调试完)总量
private int debugging_completion_difficulty;//调试完成难度
private int count;//项目数量
private int sum;//项目和 private int count_percent;
private float total_commissioning_percent;
private float debugging_completion_difficulty_percent;
private float prediction_and_debugging_amount_percent;
private float prediction_and_debugging_difficulty_percent; private Float projectPoints;//项目金额
private Integer projectCount;//项目个数
网上的说法是方法名太长,超过了65535(2^16-1,64K),里面有很多参数名比较长,可能在生成Getter/Setter时候过长,报错了。
由于记录这篇博文的时间比较仓促,笔者没有时间去深究java中方法(method)相关的结构信息,各位看官可以去了解一下
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3
经过在网上一番搜索,说是非java编译生成的类,在运行时被进行检测,防止有恶意代码被注入。
按照以上方法给jvm加了参数 -noverify -XX:-UseSplitVerifier启动后并未凑效也没解决问题。
最终放弃添加jvm参数,按照官方的bug修复跟踪,替换成了1.2.13版本了,修复代码在167行,至此,线上正常接口运行了。
相关参考: