다른 사람들이 만든 바이트 코드를 수정하려면 ASM library을 사용하고 있습니다. 임의의 클래스에있는 임의의 메소드의 경우 스택에 현재 클래스를 추가하는 LdcInsnNode
을 생성하고 싶습니다.스택에 현재 클래스를 정적으로 추가하는 ASM LdcInsnNode를 만드는 방법은 무엇입니까?
예를 들어, com.example.ExampleClass
이라는 클래스를 변환한다고 가정 해 봅시다. 나는 System.out.println(ExampleClass.class.getName());
과 동등한 바이트 코드를 만들고 싶습니다.
이것은 비교적 간단한 작업처럼 보입니다. 나는 이클립스 바이트 코드 개요 플러그인을 사용하는 경우, 다음 바이트 코드가 같다고 말한다 : 그래서 name
,
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
의 확장에서 실행되고 :
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
나는 다음 코드를 시도
ClassNode.name
필드를 나타냅니다. 이 메서드에서 반환 된
InsnList
은
AbstractInsnNode
앞에 삽입되어
InsnList.insertBefore(AbstractInsnNode, printClass())
을 사용합니다. 이 점은 바이트 코드에 도달하면, 나는 다음과 같은 이유로 오류가 다음 LDC 명령이 실제 클래스
Lcom/example/ExampleClass;.class
대신 문자열
"Lcom/example/ExampleClass;.class"
를 추가하기 때문에
가
Type 'java/lang/String' (current frame, stack[1]) is not assignable to 'java/lang/Class'
이 명확하다.
해결 방법이 있습니까? 클래스가 아직 존재하지 않기 때문에 LdcInsnNode
에 Class
개체를 직접 추가하는 것은 불가능합니다. 그러나 Class
객체를로드하는 명령어를 추가하는 방법이 있습니까?
내 경우에는 Object.getClass()
메서드를 호출하는 것이 정적 컨텍스트에서 작동해야하기 때문에 옵션이 아닙니다.