假设我想在调用某些感兴趣的方法之前调用(强)> 之前的
是否可以将当前堆栈存储在某处,调用日志并重新填充堆栈?我错过了任何明显的堆栈变异操作符吗?或者我真的需要:
示例:给出原始代码
public static void main()
{
doSomethingUnrelated();
methodOfInterest(); // line 5 for example
doSomethingUnrelated();
}
结果代码应该是:
public static void main()
{
doSomethingUnrelated();
Logger.log("methodOfInterest", "main", 5);
methodOfInterest();
doSomethingUnrelated();
}
public Logger
{
public static void log(String method, String callee, int line)
{ ... }
}
上下文:我的实际ASM MethodVisitor如下所示:
class UsageClassMethodVisitor extends MethodVisitor implements Opcodes
{
private final String fileName;
private final String visitedClass;
private final String visitedMethod;
private int lineNumber;
UsageClassMethodVisitor(MethodVisitor mv, String fileName, String visitedClass, String visitedMethod, boolean isStatic)
{
super(Opcodes.ASM5, mv);
this.fileName = fileName;
this.visitedClass = visitedClass;
this.visitedMethod = visitedMethod;
}
@Override
public void visitLineNumber(int i, Label label) {
lineNumber = i;
super.visitLineNumber(i, label);
}
@Override
public void visitMethodInsn(int access, String ownerClass, String method, String signature, boolean isInterface) {
if(ownerClass.contains("org/example/package/")) {
System.out.printf("prepending to visitMethodInsn(%s, %s, %s, %b) @ %s.%s:%d\n",
ownerClass, method, signature, isInterface,
visitedClass, visitedMethod, lineNumber);
super.visitLdcInsn(fileName);
super.visitLdcInsn(visitedClass);
super.visitLdcInsn(visitedMethod);
super.visitLdcInsn(lineNumber);
super.visitMethodInsn(Opcodes.INVOKESTATIC,
Hook.ACCESS_OWNER_NAME,
Hook.ACCESS_METHOD_NAME,
Hook.ACCESS_METHOD_DESC, false);
}
super.visitMethodInsn(access, ownerClass, method, signature, isInterface);
}
}
但显然这是一个错误,因为在调用时堆栈是8长而不是4:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
org.using.package.Main.main([Ljava/lang/String;)V @13: invokestatic
Reason:
Type integer (current frame, stack[8]) is not assignable to 'java/lang/String'
Current Frame:
bci: @13
flags: { }
locals: { '[Ljava/lang/String;' }
stack: { long, long_2nd, long, long_2nd, 'java/util/concurrent/TimeUnit', 'java/lang/String', 'java/lang/String', 'java/lang/String', integer }
答案 0 :(得分:2)
没有理由将堆栈存储在任何地方,因为堆栈很好,是堆栈。您只需按下日志参数,调用日志记录功能,弹出结果,您就可以保留原始堆栈。