美文网首页Java互联网科技程序员
一起来看装箱引发的线上问题

一起来看装箱引发的线上问题

作者: 小美人鱼失去的腿 | 来源:发表于2020-09-19 09:46 被阅读0次

    背景

    客服同学反馈使用某功能时,页面提示异常。

    像往常一样,小伙伴积极响应,按部就班的先翻日志,找到异常信息,定位到哪一块范围,然后就...(给出反馈结果)

    小伙伴看了小一会儿,怎么看都感觉没有问题,正准备赶班车之际,小伙伴喊渣渣勇也看下这段逻辑,大概瞄了两眼确实没发现问题(主要还是太菜了),就先撤了...

    以下内容暂不讨论代码编写规范问题...

    正文

    1、一筹莫展

    路上回想那段逻辑,好像确实没什么问题... 坚信勤能补拙的渣渣勇,回来后还是决定翻下代码

    翻了下线上异常日志信息:

    image.png

    看到这日志信息,这不是很明显,类名 + 行数 都提示了嘛... 按常规套路,翻出对应代码... (需确保代码跟线上版本一致)

    异常 563行 逻辑如下:

    image.png

    这么看,好像这行代码确实没什么问题(其实这里有很大问题!

    后面想线上跟本地打的包不一致导致,down了对应的class文件下来,如红色框所示:

    image.png

    这就很奇怪了,难道真的是代码有毒?

    2、峰回路转

    事到如今,也只好拔出我的大杀器,40米长的大刀 -- Arthas !

    trace 一下对应的方法,页面再模拟请求下:

    image.png

    ok,很明显,空指针出来了!

    再使用 jad 命令反编译对应方法 (由不得感叹arthas 真香):

    image.png

    看到红色框所示,由不得感叹一声,what the help (Fxxx)?

    到这里,原因已经很明显了, 当对象不为空、属性为空时,就会出现 NPE;

    应该有小伙伴跟我一样会有疑问,为什么反编译会多出来 Integer.value; OK,其实就是图二中的 DEFAULT 搞得鬼!

    private static final int DEFAULT = 0;
    

    因为对象用的是 Integer,涉及到装箱的操作,所以会多出 Integer.value 方法;(这里体现出打的包中的 class 文件多么不靠谱)

    3、问题复现

    为了验证以上问题,写了个demo来复现一下:

    /**
     * Author : bingo624
     * Date : 2020/9/17 23:23
     * Description :
     * version : 1.0
     */
    @RestController
    public class HelloController {
    
        private static final int DEFAULT = 0;
    
        @RequestMapping("/hello1")
        public StudentVo hello1(){
            PhxUserDto phxUserDto = new PhxUserDto();
            StudentVo vo = new StudentVo(phxUserDto == null ? DEFAULT : phxUserDto.getGender());
            return vo;
        }
    
        @RequestMapping("/hello2")
        public StudentVo hello2(){
            PhxUserDto phxUserDto = new PhxUserDto();
            StudentVo vo = new StudentVo(phxUserDto == null ? null : phxUserDto.getGender());
            return vo;
        }
    
        @RequestMapping("/hello3")
        public StudentVo hello3(){
            PhxUserDto phxUserDto = new PhxUserDto();
            StudentVo vo = new StudentVo(phxUserDto == null ? Integer.valueOf(0) : phxUserDto.getGender());
            return vo;
        }
    }
    

    结合上述介绍,猜猜看,是否都能正常返回?

    聪明如你,不出所料, 请求 /hello1 是会出现 NPE 返回 500

    image.png

    /hello2 和 /hello3 都是能正常响应的!

    最后来看看打的jar包中的class文件,以及线上反编译后的类:

    jar包中的class文件:

    image.png

    线上反编译后:

    image.png

    4、柳暗花明

    翻了下阿里规约:(拆箱装箱都有可能引发 NPE)

    image.png

    官网指引: docs.oracle.com/javase/spec…

    image.png

    总结

    通过一个案例,体现出基础知识的重要性;代码编写规范,可以避免很多问题;

    犯错误是很正常的,更应该思考的是:出现问题如何通过掌握的各种工具来解决,以及不重复犯错!

    最后再安利一波 arthas, 真香!(还有很多高级特性等待你的发掘...)

    相关文章

      网友评论

        本文标题:一起来看装箱引发的线上问题

        本文链接:https://www.haomeiwen.com/subject/fdheyktx.html