他の人が作成したバイトコードを変更するためにASM ライブラリを使用しています。LdcInsnNode任意のクラスの任意のメソッドについて、現在のクラスをスタックに追加するを作成したいと思います。
たとえば、 というクラスを変換するとしcom.example.ExampleClassます。に相当するバイトコードを作成したいと思いますSystem.out.println(ExampleClass.class.getName());。
これは比較的単純な作業のようです。Eclipse Bytecode Outline プラグインを使用すると、次のバイトコードが同等であると表示されます。
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC Lcom/example/ExampleClass;.class
INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
次のコードを試しました:
private InsnList printClass() {
InsnList result = new InsnList();
result.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
result.add(new LdcInsnNode("L" + name + ";.class"));
result.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false));
result.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false));
return result;
}
これは の拡張機能で実行されているClassNodeため、フィールドnameを参照してください。ClassNode.nameこのInsnListメソッドによって返された は、既存のAbstractInsnNodeusingの前に挿入されていInsnList.insertBefore(AbstractInsnNode, printClass())ます。バイトコードがこのポイントに到達すると、次の理由でエラーが発生します。
Type 'java/lang/String' (current frame, stack[1]) is not assignable to 'java/lang/Class'
これは明らかに、LDC 命令が"Lcom/example/ExampleClass;.class"実際のクラスではなく文字列を追加しているためLcom/example/ExampleClass;.classです。
これに対する回避策はありますか? クラスがまだ存在しないため、Classオブジェクトを anに直接追加することは不可能のようです。しかし、オブジェクトLdcInsnNodeをロードする命令を追加する方法はありますか?Class
Object.getClass()私の特定のケースでは、静的コンテキストから動作する必要があるため、メソッドを呼び出すことはオプションではありません。