Adel
Adel

Reputation: 451

Null pointer exception after checking for not null

I have a strange java.lang.NullPointerException on a variable that should not be null.

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

param1 is given as a method parameter, and it can be null. Normally, when affecting param1 to params[0], it is not null (otherwise it won't pass the if statement).

Here is the error (line 144 is "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)

Here is the full code of the method where the exception occurs:

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);
    }
}

EDIT:

To clarify my example, I am in a context of:

  1. Instrument a Java application using ASM
  2. Run the new instrumented classes while using a Java agent
  3. The agent will use information collected by the instrumented code to run some measurements
  4. The agent also collects the values of methods' parameters of the application.

For this, onMethodEntry is executed on each method run. I have several of these methods with different signatures. In particular:

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);
    }
}

And this is the code I used for instrumenting the program classes (i.e. Tower of Hanoi):

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();
}

Upvotes: 1

Views: 3942

Answers (2)

jlordo
jlordo

Reputation: 37833

Why don't you replace your

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

method with the varargs version:

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

That way, you can get rid of your other methods, which are all the same, just with different amount of parameters. Also the method containing your error would disappear. If the error still persists, you're one step closer to finding it. Also, you wouldn't have to change any code where you call the method, because it's signature is the same.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

First, the error is not on the params[0] = param1 line, because the stack trace shows that your code entered the onMethodEntry method.

There is absolutely no point in adding if statements: in case param1 is null, there would be no null assignment, but params[0] would remain null because all unassigned positions in new Object[10] are initially set to null.

In order to fix the problem, you should first figure out what objects must be placed in the array instead of null parameters, and then modify the conditions as follows:

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

Upvotes: 5

Related Questions