1

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

2 に答える 2

5

まず、コードがメソッドに入ったことがスタック トレースに示されているため、エラーは行に表示されませんparams[0] = param1onMethodEntry

ifステートメントを追加してもまったく意味がありません。 param1isの場合、割り当てnullはありませんが、割り当てられていないすべての位置が最初に に設定されているため、残ります。nullparams[0] nullnew Object[10]null

この問題を解決するには、最初にnullパラメーターではなく配列に配置する必要があるオブジェクトを特定し、次に条件を次のように変更する必要があります。

if (param1 != null) {
    params[0] = param1;
} else {
    params[0] = // something else
}
于 2012-11-23T14:32:35.427 に答える
0

交換してみませんか

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

varargsバージョンのメソッド:

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

そうすれば、パラメーターの量が異なるだけで、すべて同じである他のメソッドを取り除くことができます。また、エラーを含むメソッドは消えます。それでもエラーが続く場合は、エラーの検出に一歩近づいています。また、シグネチャが同じであるため、メソッドを呼び出すコードを変更する必要はありません。

于 2012-11-23T15:51:41.493 に答える