Java 如何通过ASM捕获字节码中的运行时异常
我试图通过异常捕获运行时异常。我能够捕获常见的方法退出事件。 但是,控件从未在Java 如何通过ASM捕获字节码中的运行时异常,java,java-bytecode-asm,Java,Java Bytecode Asm,我试图通过异常捕获运行时异常。我能够捕获常见的方法退出事件。 但是,控件从未在opcode==opcode.ATHROW中到达 我认为我把这些事件称为是做错了什么 以下是我的示例代码: public void visitCode() { // mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // mv.visitLdcIns
opcode==opcode.ATHROW
中到达
我认为我把这些事件称为是做错了什么
以下是我的示例代码:
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");
}
我的意图是添加动态try-catch块,如果抛出任何异常,请打印它。
RuntimeException
s不需要抛出athrow
指令。idiv
或irem
指令可以抛出一个算术异常
,getfield
,putfield
或invoke…
指令可以抛出一个NullPointerException
,举几个例子。所以在这些地方找不到athrow指令
拦截所有这些异常的唯一方法是插入一个处理代码的异常处理程序,如果愿意,可以重新抛出异常。您知道实际的RuntimeException是在哪里抛出的吗?如果它是由JRE本身抛出的,那么这将不起作用,因为(我猜)您没有在java包中转换类(您无论如何都不应该这样做)。您的最新更新是否起作用?我也想在方法中添加try-catch块。请回复。我已经添加了
标签
声明并访问了它们。我还尝试了visittrychtblock
方法。但是,在那之后,我不能再继续了。在这方面你能帮我一点忙吗?它正确吗?mv.visittrychtblock(lTryBlockStart,lTryBlockEnd,lCatchBlockStart,“java/lang/Exception”);超级访问方法(操作码、所有者、名称、描述);mv.visitLabel(lTryBlockEnd);mv.visitJumpInsn(org.objectweb.asm.Opcodes.GOTO,lCatchBlockEnd);mv.visitLabel(lCatchBlockStart);mv.visitVarInsn(org.objectweb.asm.Opcodes.ASTORE,1);mv.visitVarInsn(org.objectweb.asm.Opcodes.ALOAD,1);mv.visitMethodInsn(org.objectweb.asm.Opcodes.INVOKEVIRTUAL,“java/lang/Exception”,“printStackTrace”,“V”);mv.visitLabel(lCatchBlockEnd);}
这超出了评论的范围;我建议为此打开一个新问题。我已编辑了该问题。请查收。提前感谢。ldc
与调用方法无关。如果您的方法是类foo.Bar
中的publicstaticvoidexceptionoccurrend(Throwable){}
,那么只需执行aload_1
将参数放在堆栈上,后跟visitMethodInsn(Opcodes.INVOKESTATIC,“foo/Bar”,“exceptionoccurrend”,“(Ljava/lang/Throwable;)V)代码>
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);
}