저는 스택 맵 프레임이 Java에서 어떻게 작동 하는지를 ASM의 점프와 함께 재생하여 이해하려고 노력해 왔습니다. 그것은이하는 모든 변수를 몇 가지 문자열을 결합하기 위하여 StringBuilder
을 만드는 것입니다ClassWriter ASM의 COMPUTE_FRAMES
L0: ldc 'hello'
L2: astore_1
L3: getstatic Field java/lang/System out Ljava/io/PrintStream;
L6: new java/lang/StringBuilder
L9: dup
L10: invokespecial Method java/lang/StringBuilder <init>()V
L13: ldc 'concat1'
L15: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L18: aload_1
L19: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L22: invokevirtual Method java/lang/StringBuilder toString()Ljava/lang/String;
L25: invokevirtual Method java/io/PrintStream println (Ljava/lang/String;)V
L28: getstatic Field java/lang/System out Ljava/io/PrintStream;
L31: new java/lang/StringBuilder
L34: dup
L35: invokespecial Method java/lang/StringBuilder <init>()V
L38: ldc 'concat2'
L40: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L43: aload_1
L44: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L47: invokevirtual Method java/lang/StringBuilder toString()Ljava/lang/String;
L50: invokevirtual Method java/io/PrintStream println (Ljava/lang/String;)V
L53: return
: (크라 카타로 분해) : 나는 몇 가지를 시도하는 간단한 방법을 만들었습니다.
L35의 invokespecial 호출은 L10의 invokespecial 호출과 정확히 같은 스택을 가지고 있기 때문에 L35 바로 앞에 ASN을 사용하여 ICONST_1; IFEQ L10
시퀀스를 추가하기로 결정했습니다.
내가 (다시 Krakatau로) 분해했을 때, 나는 결과가 이상하다는 것을 발견했다. ASM은 할 L10에서 스택 프레임을 계산했다 :
.stack full
locals Object [Ljava/lang/String; Object java/lang/String
stack Object java/io/PrintStream Top Top
.end stack
대신 내가 기대했던대로
stack Object java/io/PrintStream Object java/lang/StringBuilder Object java/lang/StringBuilder
의.
또한이 클래스는 Top
에 StringBuilder#<init>
을 호출 할 수 없으므로 확인을 통과하지 못합니다. ASM 설명서에 따르면 Top
은 초기화되지 않은 값을 나타내지 만 점프 위치와 코드 이전의 코드에서는 초기화되지 않은 것처럼 보입니다. 나는 점프에 무엇이 잘못되었는지 이해하지 못한다.
내가 삽입 한 점프에 문제가있어 어떻게 든 프레임을 계산할 수없는 클래스를 만들었습니까? 아마도 ASM의 ClassWriter에 버그가 있습니까?
감사합니다. 초기화되지 않은 각 값이 생성 된 NEW 문에 바인딩되어 있다는 사실이 여기에 핵심적인 것처럼 보입니다. – konsolas