阿里巴巴fastjson-1.2.12.jarjson解析异常java.lang.classformaterror:invalidmethodcodelength66865incla(代码片段)

passedbylove passedbylove     2022-12-20     192

关键词:

承接上篇:fastjson反序列化LocalDateTime失败的问题java.time.format.DateTimeParseException: Text ‘2019-05-24 13:52:11‘ could not be parsed at index 10

之前在线上用的版本是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.netmarch.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编译生成的类,在运行时被进行检测,防止有恶意代码被注入。

Start-up time, I‘d say. Verification that classes are correct takes some time when the class is loaded. Since classes might be loaded in a lazy fashion (not on app start, but when being used for the first time), this might cause unexpected and undesired runtime delays.

Actually the class does not need to be checked in general. The compiler will not emit any invalid bytecode or class construct. The reason for verification is that the class may be build on one system, get hosted online and is transmitted to you through the unprotected internet. On this path, a malicious attacker might modify the bytecode and create something the compiler might never create; something that can crash the JVM or possibly circumvents security restrictions. Thus the class is verified before it is used. If this is a local application, there is usually no need to check the bytecode again.

 

JVM加载class文件时会做字节码校验(bytecode verification)。这篇文档非常详细地讲了JVM会做哪些校验。 如果你的class文件是由java源文件通过javac编译出来的,那么基本上不用担心bytecode verification。 如果class文件是由asm、cglib等动态生成出来的或者由其它编译器生成的,那么JVM在校验它的bytecode时就有可能失败。 失败的原因可能是你生成的bytecode有bug,也可能是由于新版本的JVM加入了新的验证条件后导致原来可以通过验证的bytecode现在不能通过了。

很多Java框架都会动态生成class文件,再加上JVM版本也会时不时地修改它的bytecode verification行为。 所以,运行代码时偶尔会遇到java.lang.VerifyError错误。 在不能修改框架代码或者切换JVM实现的情况下,JVM提供了一些选项可以让你改变或者绕过bytecode verification。

-XX:-UseSplitVerifier

-XX:-UseSplitVerifier可以让JVM不开启“type-checking verifier”。 这样就不强制要求class文件含有StackMapTable(所有Java 7 version 51之后的class文件默认要求含有StackMapTable)。

-noverify

-noverify选项可以关闭bytecode verification。

有的观点认为某些bytecode verification除了给动态生成bytecode增加麻烦之外,并没有什么大用。 但是这篇文章强烈建议不要关闭bytecode verification,特别是在生产环境里。 因为bytecode verification可以检测到恶意代码或者代码中的bug。 特别是代码中的bug,因为没有人可以保证(动态产生的)字节码是百分百bug free的。

回到我的问题,由于PactProviderRule类来自于外部依赖,CI上的JVM也不能替换 (CI上用的是非oracle的JVM实现,该测试代码在本地的官方JVM上是可以运行通过,所以CI上的失败有一定可能是其用的JVM实现的原因), 所以一个简单的方法是在maven跑测试代码时,给JVM加上-noverify选项。

按照以上方法给jvm加了参数 -noverify  -XX:-UseSplitVerifier启动后并未凑效也没解决问题。

最终放弃添加jvm参数,按照官方的bug修复跟踪,替换成了1.2.13版本了,修复代码在167行,至此,线上正常接口运行了。

相关参考:

Ensuring JVM method size limit is never exceeded #661

一个fastjson转换JSON字符串的报错排查

Use of -noverify when launching java apps

阿里巴巴收购雅虎中国的过程

1.2005年10月,阿里巴巴集团与美国雅虎达成长期战略合作伙伴关系。阿里巴巴收购雅虎美国在中国的全部资产,并获得雅虎中国的运营权,雅虎美国投资10亿美元成为阿里巴巴集团的战略股东。雅虎共同创始人兼首席财务官杨致... 查看详情

idea阿里巴巴规范插件报错

参考技术A等级调到Inspactions。idea是阿里巴巴所研发的代码规范插件,idea阿里巴巴规范插件报错等级调到Inspactions即可,规范基于《阿里巴巴Java开发手册》,在IntelliJIDEA的插件管理中直接搜索AlibabaJavaCodingGuidelines即可。 查看详情

阿里巴巴推出的伙伴计划是啥?

...备和住宿旅馆都有优惠是嘛?2009年“伙伴计划”推出。阿里巴巴方面定义为,以阿里巴巴为中间服务平台,围绕中小企业的订单难、管理难和发展难等问题,联合各个行业的优秀供应商,为中国中小企业提供更优惠、更贴心、... 查看详情

《阿里巴巴人力资源管理》读后感

参考技术A    《阿里巴巴人力资源管理》主要讲解的是阿里巴巴在人力资源管理的特色之处,整本书分为3个部分、12个章节,分别从理念、基层和高层三个篇章打开,涉及到企业管理中的企业文化、战略规划规划... 查看详情

wwwhy76888com19908836661芯片就是阿里巴巴

“芯片就是阿里巴巴的一个核心技术竞争力。”21日,阿里巴巴集团首席技术官(CTO)张建锋向中新社表示。阿里巴巴CTO:“中国芯”亦有新机会新优势阿里巴巴集团首席技术官张建锋。一天前,阿里巴巴全资收购中国大陆唯一的... 查看详情

美国政府重新将阿里巴巴列入“恶名市场”名单

 美国贸易代表办公室周三重新将阿里巴巴列入年度“恶名市场”黑名单。4年前,阿里巴巴也曾被列入这一名单。  阿里巴巴集团总裁迈克尔·埃文斯(MichaelEvans)表示:“我们对于美国贸易代表办公室的决定感到非常失望,... 查看详情

阿里云可以做啥?

...户用不到!问题四:阿里云是做什么的阿里云2009年9月,阿里巴巴集团在十周年庆典上宣布成立子公司“阿里云”,该公司将专注于云计算领域的研究和研发。“阿里云”也成为继阿里巴巴、淘宝、支付宝、阿里软件、中国雅虎... 查看详情

阿里星球阉割音乐服务阿里巴巴大文娱总算有点靠谱了

...里星球乃至天天动听变身而来,2012年10月,天天动听接受阿里巴巴投资,2013年年底正式并入阿里巴巴旗下。到了今年4月15日,天天动听正式更名为阿里星 查看详情

markdown阿里巴巴(代码片段)

查看详情

阿里巴巴

近日,记者从新潮传媒集团官方公众号获悉:原阿里巴巴中供铁军、区域经理何长星出任集团COO,工作直接向集团董事长张继学汇报。据称,新潮传媒全国布局第一阶段已经基本完成,其核心高管层悉数到位。这些高管来自包括... 查看详情

开放下载!《阿里巴巴devops实践手册》

简介:覆盖DevOps演进史、核心理念与阿里巴巴DevOps最佳实践的全方位解析手册,揭开阿里巴巴高效研发的秘密!最新下载>>《阿里巴巴DevOps实践指南》了解详情火遍全球的DevOps到底是什么?如何利用DevOps进行... 查看详情

开放下载!《阿里巴巴devops实践手册》

简介:覆盖DevOps演进史、核心理念与阿里巴巴DevOps最佳实践的全方位解析手册,揭开阿里巴巴高效研发的秘密!最新下载>>《阿里巴巴DevOps实践指南》了解详情火遍全球的DevOps到底是什么?如何利用DevOps进行... 查看详情

开放下载!《阿里巴巴devops实践手册》

简介:覆盖DevOps演进史、核心理念与阿里巴巴DevOps最佳实践的全方位解析手册,揭开阿里巴巴高效研发的秘密!最新下载>>《阿里巴巴DevOps实践指南》了解详情火遍全球的DevOps到底是什么?如何利用DevOps进行... 查看详情

阿里巴巴java开发规约及插件安装

【上海尚学堂编辑整理】10.14日,阿里巴巴在杭州云栖大会上,正式发布了由阿里巴巴P3C项目组,经过近一年的持续研发,正式发布众所期待的《阿里巴巴Java开发规约》的扫描插件。 插件全球首发仪式,大牛云集平日低调的... 查看详情

阿里巴巴java开发手册

目录前言...................................................................................................................................................................................................1 查看详情

阿里巴巴如何添加客服

参考技术A问题一:怎么在阿里巴巴里面添加客服在“精准营销”里边可以设置接待客服的!但必须先申请好账号,写上你要加入的客服账号,然后点妖请,再用旺旺登录你加入的客服账号确认妖请就可以了!问题二:阿里巴巴... 查看详情

阿里巴巴矢量图库

iconfont-阿里巴巴矢量图标库iconfont-国内功能很强大且图标内容很丰富的矢量图标库,提供矢量图标下载、在线存储、格式转换等功能。阿里巴巴体验团队倾力打造,设计和前端开发的便捷工具https://www.iconfont.cn/search/index?s... 查看详情

阿里巴巴矢量图库

iconfont-阿里巴巴矢量图标库iconfont-国内功能很强大且图标内容很丰富的矢量图标库,提供矢量图标下载、在线存储、格式转换等功能。阿里巴巴体验团队倾力打造,设计和前端开发的便捷工具https://www.iconfont.cn/search/index?s... 查看详情