Я пытался понять, как кадры стоп-кадров работают на Java, играя с прыжками в ASM. Я создал простой способ попробовать некоторые вещи: (разобранный с Кракатау):ClassWriter COMPUTE_FRAMES в ASM
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
Все это делает создать StringBuilder
присоединиться некоторые строки с переменными.
Поскольку вызов invokespecial на L35 имеет точно такой же стек, что и вызов invokespecial на L10, я решил добавить последовательность непосредственно перед L35 с ASM.
Когда я разобрался (снова с Кракатау), я нашел результаты довольно странными. 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
, как я ожидал.
Кроме того, этот класс также не прошел бы проверку, как нельзя позвонить StringBuilder#<init>
по телефону Top
. Согласно руководству ASM, Top
относится к неинициализированному значению, но он не кажется неинициализированным в коде, как из места перехода, так и из кода раньше. Я не понимаю, что случилось с прыжком.
Есть ли что-то не так с прыжком, который я вставил, что каким-то образом делает класс невозможным для вычисления кадров? Возможно, это ошибка с ClassWriter ASM?
Благодарим вас за то, что каждое неинициализированное значение связано с созданным им оператором NEW. – konsolas