用于方法入口/出口的 ASM 字节码检测
我创建了一个 JVMTI 代理,它在较高级别上执行以下操作:
onClassLoadHook 将已加载类的字节码发送到一个单独的 Java 进程,该进程将使用 ASM 检测该类
- 该类
获取字节码并加载它们
在我的单独的 Java 进程中检测加载的 Java 类,我执行以下操作:
.. ..
cr = new ClassReader(inBytes, offset, inLen);
cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new ClassAdapter(cw) {
..
..
@Override
public MethodVisitor visitMethod(final int access,
final String name,
final String desc,
String signature,
String[] exceptions) {
return new MethodAdapter(mv) {
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/amir/Tester", "callTestStatic3", "(Ljava/lang/Object;)V");
mv.visitCode();
}
}
}
当我尝试使用 Java Decompiler 反编译在该检测之后编写的类时 - 我看到以下反编译函数,我知道它是错误的:
public void func1(int arg1, int arg2)
{
int b;
Tester.callTestStatic3(???);
System.out.println("arg = " + a + " b = " + b);
}
因为我的函数实际上看起来像这样:
public void func1(int a, int b)
{
System.out.println("arg = " +a + " b = " +b);
}
任何人都可以告诉我我在这里是否做错了什么? 我唯一的线索是,如果我不将 THIS 指针作为参数传递给函数,而是传递原始类型,那么一切都会顺利进行。 我需要管理的 THIS 指针有什么特别之处吗? 我比较了字节码,并使用 ASMIFIER 来了解需要使用哪些语句来生成正确的字节码。
I've created a JVMTI agent that does the following at a high level:
onClassLoadHook send the bytecodes for the loaded class to a separate Java process that will instrument the class using ASM
get the bytecodes back and load them
In my seperate java process that instruments the loaded Java class I do the following :
..
..
cr = new ClassReader(inBytes, offset, inLen);
cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new ClassAdapter(cw) {
..
..
@Override
public MethodVisitor visitMethod(final int access,
final String name,
final String desc,
String signature,
String[] exceptions) {
return new MethodAdapter(mv) {
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/amir/Tester", "callTestStatic3", "(Ljava/lang/Object;)V");
mv.visitCode();
}
}
}
When I try to decompile the class that is written after this instrumentation using Java Decompiler - I see the following decompiled function which I know is wrong :
public void func1(int arg1, int arg2)
{
int b;
Tester.callTestStatic3(???);
System.out.println("arg = " + a + " b = " + b);
}
because my function actually looks like this :
public void func1(int a, int b)
{
System.out.println("arg = " +a + " b = " +b);
}
Can anyone tell me if I did something wrong here? My only clue is that if instead of passing in as an argument to my function the THIS pointer, if I pass in primitive types, everything works out finie. Is there something special about the THIS pointer that I need to manage? I've compared the bytecodes, and I've used ASMIFIER to get a clue as to what statements I need to use to generate the right bytecodes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
也许这并不重要,但是您不应该调用
super.visitCode()
吗?我会使用 TraceClassVisitor 来准确检查正在生成的内容。
Perhaps it does not matter, but shouldn't you be calling
super.visitCode()
?I'd use TraceClassVisitor to check exactly what was being generated.
看来您的代码是正确的,mv.visitCode()。 javap 显示预期的字节码。 我猜你原来的反编译器没有做正确的事情。
It looks like your code is correct, with mv.visitCode(). javap shows the expected bytecodes. I guess your original decompiler just wasn't doing the right thing.