简介
在Java14之前,如果出现NullPointerException
,只会知道有对象为null导致空指针,如果在多个对象上调用了方法,那么就很难区分到底哪个对象为null。在 Java14中,JEP 358(详情见参考资料1)的出现改善了这样的情况,丰富了NullPointerException
的输出,但目前常用的版本还是Java8或11等长期支持的版本,所以下面介绍一种方法来让8和11也能实现更加丰富的NullPointerException
提示。
增加空指针异常提示
示例代码如下:
public static void main(String[] args) {
Map<String, String> map = null;
demo(map);
}
public static void demo(Map<String,String> map){
System.out.println(map.get("foo").toLowerCase());
}
8和11在增强之前的输出如下:
Exception in thread "main" java.lang.NullPointerException
at com.nereusyi.npe.NpeDemo.demo(NpeDemo.java:18)
at com.nereusyi.npe.NpeDemo.main(NpeDemo.java:14)
并没有什么有用的信息,根据这段异常也没法判断到底是哪个对象为null。
下面就可以开始动手增强异常提示了,我们可以在https://github.com/odnoklassniki/jvmti-tools/tree/master/richNPE中找到增强异常提示的代码,具体使用方法也在首页中有详细说明。
下载该文件之后,需要手动编译该文件,首页中少了Mac的编译命令,我在这里也补上:
# Linux
g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibrichNPE.so richNPE.cpp
# Windows
cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" richNPE.cpp
# Mac
g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -olibrichNPE.so richNPE.cpp
Windows下如果安装了MINGW64,那么也可以使用g++编译(一般装了git for windows都会有)。
编译好之后,会生成一个librichNPE.so
(Windows下会生成一个.exe文件)的文件,在运行时候使用如下方式启动就行:
java -agentpath:/path/to/librichNPE.so MainClass
在idea中运行时,需要在Run Configurations
中增加VM options,再输入-agentpath:/path/to/librichNPE.so
参数就可以。
这时,再运行示例代码时,异常提示就会变成如下所示:
Exception in thread "main" java.lang.NullPointerException: Called method 'get' on null object at bci 6
at com.nereusyi.npe.NpeDemo.demo(NpeDemo.java:18)
at com.nereusyi.npe.NpeDemo.main(NpeDemo.java:14)
现在就可以知道是调用了get方法导致的NullPointerException
,也就是说map对象是null。
参考资料
[1]JEP 358:https://openjdk.java.net/jeps/358
[2]jvmti-tools:https://github.com/odnoklassniki/jvmti-tools
评论
发表评论