Я хочу, чтобы компилировать блок Try/Catch с использованием структуры ASM из моего компилятора (это означает, что блок try, блоки обработчика и переменные являются динамическими). Это то, что мой код в настоящее время выглядит следующим образом:Java ASM Generate Catch Block
org.objectweb.asm.Label tryStart = new org.objectweb.asm.Label();
org.objectweb.asm.Label tryEnd = new org.objectweb.asm.Label();
org.objectweb.asm.Label endLabel = new org.objectweb.asm.Label();
writer.writeLabel(tryStart);
if (this.action != null)
{
this.action.writeStatement(writer);
writer.writeJumpInsn(Opcodes.GOTO, endLabel);
}
writer.writeLabel(tryEnd);
for (int i = 0; i < this.catchBlockCount; i++)
{
CatchBlock block = this.catchBlocks[i];
org.objectweb.asm.Label handlerLabel = new org.objectweb.asm.Label();
int varIndex;
writer.push(block.type);
// Check if the block's variable is actually used
if (block.variable != null)
{
// If yes register a new local variable for the exception and
// store it.
varIndex = block.variable.index = writer.registerLocal(block.type);
writer.writeFrameLabel(handlerLabel);
writer.writeVarInsn(Opcodes.ASTORE, varIndex);
block.action.writeStatement(writer);
writer.removeLocals(1);
}
// Otherwise pop the exception from the stack
else
{
varIndex = -1;
writer.writeFrameLabel(handlerLabel);
writer.writeInsn(Opcodes.POP);
block.action.writeStatement(writer);
}
writer.writeTryCatchBlock(tryStart, tryEnd, handlerLabel, block.type);
writer.writeJumpInsn(Opcodes.GOTO, endLabel);
}
writer.writeFrameLabel(endLabel);
Однако эта реализация порождает следующие VerifyError
:.
java.lang.VerifyError: Stack map does not match the one at exception handler 20
Exception Details:
Location:
dyvil/test/Main.main([Ljava/lang/String;)V @20: astore_1
Reason:
Type top (current frame, locals[1]) is not assignable to 'Ljava/lang/Exception;' (stack map, locals[1])
Current Frame:
bci: @0
flags: { }
locals: { '[Ljava/lang/String;' }
stack: { 'java/lang/Exception' }
Stackmap Frame:
bci: @20
flags: { }
locals: { '[Ljava/lang/String;', 'Ljava/lang/Exception;' }
stack: { 'Ljava/lang/Exception;' }
Bytecode:
0000000: b200 1312 15b6 001b b200 1304 036c b600
0000010: 1ea7 0013 4cb2 0013 1224 b600 1b2b b600
0000020: 29a7 0003 b1
Exception Handler Table:
bci [0, 20] => handler: 20
Stackmap Table:
full_frame(@20,{Object[#32],Object[#34]},{Object[#34]})
chop_frame(@36,1)
(Обратите внимание, что методы writer
начиная с writeX
лишь делегаты MethodVisitor.visitX
writeFrameLabel
также сообщает MethodWriter
, что он должен генерировать стек стека перед записью следующей инструкции)
Вы создали «ClassWriter» с параметром [ClassWriter.COMPUTE_FRAMES] (http://asm.ow2.org/asm50/javadoc/user/org/objectweb/asm/ClassWriter.html#COMPUTE_FRAMES) и версией класса 1,6+? – apangin
Это именно то, чего я пытаюсь избежать, используя пользовательский метод MethodWriter по соображениям производительности. Версия класса установлена в 1.8. – Clashsoft