宁武皇仁光九年锦文轩刻本《异闻录》载: 扶桑画师浅溪,居泰安,喜绘鲤。院前一方荷塘,锦鲤游曳,溪常与嬉戏。 其时正武德之乱,潘镇割据,战事频仍,魑魅魍魉,肆逆于道。兵戈逼泰安,街邻皆逃亡,独溪不舍锦鲤,未去。 是夜,院室倏火。有人入火护溪,言其本鲤中妖,欲取溪命,却生情愫,遂不忍为之。翌日天明,火势渐歇,人已不见。 溪始觉如梦,奔塘边,但见池水干涸,莲叶皆枯,塘中鲤亦不知所踪。 自始至终,未辨眉目,只记襟上层迭莲华,其色魅惑,似血着泪。 后有青岩居士闻之,叹曰:魑祟动情,必作灰飞。犹蛾之投火耳,非愚,乃命数也。 ————《锦鲤抄》

【打印空指针异常信息getMessage为null】

版本:JDK 1.8

某次解析数据进业务表时数据异常,查询接口表想查看错误消息结果发现字段均为空,由于接口表其余字段均回写正常,推测应该是捕获异常信息来返回错误消息字段这部分出了问题。

写了测试方法如下: 

    @Test
    public void returnErrorMessage(){
        try {
            User user = null;
            List<User> userList = new ArrayList<>();
            // 模拟数组越界
            userList.get(0);
/*            if(user.getId()!= 0){
                System.out.println("异常测试");
            }*/
        } catch (Exception e) {
            System.out.println("测试直接getMessage是否能打印异常: "+e.getMessage());
            System.out.println("==分割线==");
            StringWriter stringWriter= new StringWriter();
            PrintWriter writer= new PrintWriter(stringWriter);
            e.printStackTrace(writer);
            StringBuffer buffer= stringWriter.getBuffer();
            // 截取前200长度的报错信息
            String error = buffer.toString().substring(0, 200);
            System.out.println("测试Buffer能否打印异常 "+error);
            // printStackTrace()是指将异常本身和异常信息输出到标准的错误流
            System.out.println("e.printStackTrace: ");
            e.printStackTrace();
        }
    }

控制台输出:

测试直接getMessage是否能打印异常: Index: 0, Size: 0
==分割线==
测试Buffer能否打印异常 java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at com.wang.dao.UserDaoTest.returnErro
e.printStackTrace: 
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at com.wang.dao.UserDaoTest.returnErrorMessage(UserDaoTest.java:1625)
   下略.............

Process finished with exit code 0

如果 换成 空指针测试:

        try {
            User user = null;
            List<User> userList = new ArrayList<>();
 // userList.get(0);
            if(user.getId()!= 0){
                System.out.println("异常测试");
            }
        } catch (Exception e) {同上}

 

控制台输出:

测试直接getMessage是否能打印异常: null
==分割线==
测试Buffer能否打印异常 java.lang.NullPointerException
    at com.wang.dao.UserDaoTest.returnErrorMessage(UserDaoTest.java:1627)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAcc
e.printStackTrace: 
java.lang.NullPointerException
    at com.wang.dao.UserDaoTest.returnErrorMessage(UserDaoTest.java:1627)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

发现getMessage获得返回信息为null,debug模式下可以看到:

空指针捕获:

 数组越界捕获:

可以看到数组越界的异常时getMessage有返回值

点击getMessage,在源码里发现Throwable 方法有多个,但是通过断点发现它每个方法都执行了,在这里detailMessage已经是空了

于是继续追溯,我们在空指针源码里打了断点:

 我感觉是因为这个原因,它走了无detailMessage的构造方法,所以最后返回为null

 

 小结:

  总之是因为detailMessage为null且返回导致结果为空,不过栈打印是有内容的,所以我们可以先打印输出流 e.printStackTrace(writer);

用getBuffer 获取转为字符串 存储: StringBuffer buffer= stringWriter.getBuffer();

// 截取前200长度的报错信息 String error = buffer.toString().substring(0, 200);

这样就可以获取具体的错误信息了

具体代码见最上

 

posted @ 2022-06-07 17:50  哒布溜  阅读(1188)  评论(0编辑  收藏  举报