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);
}
}
編集:
私の例を明確にするために、私は次のコンテキストにいます。
- ASM を使用して Java アプリケーションを計測する
- Java エージェントを使用しながら、インストルメント化された新しいクラスを実行する
- エージェントは、インストルメント化されたコードによって収集された情報を使用して、いくつかの測定を実行します
- エージェントは、アプリケーションのメソッドのパラメーターの値も収集します。
このため、メソッドの実行ごとに 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();
}