Я пытаюсь поймать исключение во время выполнения через исключение. Я могу захватить обычный метод выхода из событий. Но контроль никогда не достигает opcode==Opcodes.ATHROW
.Как уловить исключение во время выполнения в байткоде через ASM
Я думаю, что я делаю что-то неправильно при вызове событий.
Вот мой пример кода:
public void visitCode() {
// mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
// mv.visitLdcInsn("Entering method " + fQMethodName);
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream","println","(Ljava/lang/String;)V");
}
@Override
public void visitInsn(int opcode)
{
if (opcode == Opcodes.ATHROW)
{
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Exiting on exception ");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
}
super.visitInsn(opcode);
}
public void visitMethodInsn(int opcode, String owner, String name,
String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
//
if (opcode == Opcodes.ATHROW)
{
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Exiting on exception " + name);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
}
else if (!name.equals("println")
&& !name.equals("<init>")
&& (opcode == Opcodes.INVOKEVIRTUAL || opcode == Opcodes.INVOKESPECIAL
|| opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKEDYNAMIC)) {
this.currentMethod = name;
onFinally(opcode);
}
}
private void onFinally(int opcode) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err",
"Ljava/io/PrintStream;");
mv.visitLdcInsn("Returning to " + fQMethodName + " from " + currentMethod);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
}
В то время исключения времени выполнения, существующий контент стек очищается, и только Throwable объект остается. Могу ли я получить элемент верхнего стека (например, в стеке) через ASM?
Спасибо в adavance.
EDIT:
Вот моя измененная программа после добавления попытки - поймать блок.
@ Хольгер: Благодарим за помощь. Действительно ценю это.
Итак, я пытаюсь вставить динамический блок try-catch в MethodVisitor ASM.
Вот мой код:
public void visitCode()
{
super.visitCode();
this.visitTryCatchBlock(lblTryBlockStart, lblTryBlockEnd, lblCatchExceptionBlockStart, "java/lang/Exception");
this.visitLabel(lblTryBlockStart);
}
public void visitMaxs(int maxStack, int maxLocals)
{
// visit try block end label
this.visitLabel(lblTryBlockEnd);
// visit normal execution exit block
this.visitJumpInsn(Opcodes.GOTO, exitBlock);
// visit catch exception block
this.visitLabel(lblCatchExceptionBlockStart);
// store the exception
this.visitVarInsn(Opcodes.ASTORE, 1);
// load the exception
this.visitVarInsn(Opcodes.ALOAD, 1);
// call printStackTrace()
//this.visitInsn(Opcodes.ATHROW);
this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Exception", "printStackTrace", "()V");
// exit from this dynamic block
this.visitLabel(exitBlock);
super.visitMaxs(maxStack+2, maxLocals+2);
}
Мое намерение добавить динамическую попробовать - поймать блок, и если исключение, распечатать его.
Вы знаете, где выдается фактическое исключение RuntimeException? Если он вызывается самой JRE, это не сработает с тех пор (я предполагаю), что вы не трансформируете классы в пакет java (чего вы не должны делать в любом случае). – Emiel
Ваше последнее обновление работает? Я тоже хотел добавить try catch block в метод. Пожалуйста ответьте. – AKS