繁体   English   中英

检查不为空后的空指针异常

[英]Null pointer exception after checking for not null

我在一个不应该为null的变量上有一个奇怪的java.lang.NullPointerException。

Object[] params = new Object[10];
if (param1 != null)
    params[0] = param1;

param1作为方法参数给出,它可以为null。 通常,在将param1转换为params [0]时,它不为null(否则它将不传递if语句)。

这是错误(行144是“ params [0] = param1;”):

Exception in thread "Jalen Agent" java.lang.NullPointerException
    at jalen.MethodStats.onMethodEntry(MethodStats.java:144)
    at hanoi.TowersOfHanoi.solveHanoi(TowersOfHanoi.java)
    at hanoi.TowersOfHanoi.main(TowersOfHanoi.java:29)

这是发生异常的方法的完整代码:

public static void onMethodEntry(int id, String className, String methodName, Object param1, Object param2, Object param3, Object param4, Object param5) {
    synchronized (globalLock) {
        Object[] params = new Object[10];
        if (param1 != null)
            params[0] = param1;
        if (param2 != null)
            params[1] = param2;
        if (param3 != null)
            params[2] = param3;
        if (param4 != null)
            params[3] = param4;
        if (param5 != null)
            params[4] = param5;
        MethodStats.onMethodEntry(id, className, methodName, params);
    }
}

编辑:

为了阐明我的示例,我处于以下情况:

  1. 使用ASM检测Java应用程序
  2. 使用Java代理时运行新的检测类
  3. 代理将使用检测到的代码收集的信息来进行一些测量
  4. 该代理还收集应用程序的方法参数值。

为此,onMethodEntry在每次运行的方法上执行。 我有几种带有不同签名的方法。 尤其是:

public static void onMethodEntry(int id, String className, String methodName, Object[] params) {
    synchronized (globalLock) {
        StringBuilder fullMethodName = new StringBuilder(className).append('.').append(methodName).append('-').append(Thread.currentThread().getId());
        MethodStats.addNewMethod(id, fullMethodName.toString());
        System.out.println(fullMethodName.toString() + " -- " + id);
        for (Object param : params) {
            if (param != null)
                System.out.println("Param: " + param.toString());
        }
        startTimes[depth] = System.nanoTime();
        stack[depth++] = MethodStats.getMethodInfo(id);
    }
}

public static void onMethodEntry(int id, String className, String methodName, Object param1) {
    synchronized (globalLock) {
        Object[] params = new Object[10];
        if (param1 != null)
            params[0] = param1;
        MethodStats.onMethodEntry(id, className, methodName, params);
    }
}

public static void onMethodEntry(int id, String className, String methodName, Object param1, Object param2) {
    synchronized (globalLock) {
        Object[] params = new Object[10];
        if (param1 != null)
            params[0] = param1;
        if (param2 != null)
            params[1] = param2;
        MethodStats.onMethodEntry(id, className, methodName, params);
    }
}

这是我用来检测程序类的代码(例如,河内塔):

public void visitCode() {
    mv.visitLdcInsn(new Integer(this.methodID));
    this.visitLdcInsn(this.className);
    this.visitLdcInsn(this.methodName);
    String paramCall = "";
    if (this.numParam > 0) {
        // Load parameters
        for (int i=1; i<=this.numParam; i++) {
            this.visitVarInsn(Opcodes.ALOAD, i);
            paramCall += "Ljava/lang/Object;";
        }
    }
    System.out.println(paramCall);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC,
            "jalen/MethodStats",
            "onMethodEntry",
            "(ILjava/lang/String;Ljava/lang/String;" + paramCall + ")V");
    super.visitCode();
}

首先,该错误不在 params[0] = param1行上,因为堆栈跟踪显示您的代码输入了onMethodEntry方法。

添加if语句绝对没有意义:如果param1null ,则不会有null赋值,但是params[0] 仍将为 null因为new Object[10]中所有未分配的位置最初都设置为null

为了解决此问题,您应该首先确定必须在数组中放置哪些对象而不是null参数,然后按如下所示修改条件:

if (param1 != null) {
    params[0] = param1;
} else {
    params[0] = // something else
}

你为什么不更换你的

onMethodEntry(int id, String className, String methodName, Object[] params) {

varargs版本的方法:

onMethodEntry(int id, String className, String methodName, Object... params) {

这样,您就可以摆脱其他方法,它们都是相同的,只是参数数量不同。 同样,包含您的错误的方法也会消失。 如果错误仍然存​​在,那么您离发现它只有一步之遥。 同样,您不必在调用方法的地方更改任何代码,因为它的签名是相同的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM