用于方法入口/出口的 ASM 字节码检测

发布于 2024-07-30 20:23:55 字数 1637 浏览 5 评论 0原文

我创建了一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮生未歇 2024-08-06 20:24:13

也许这并不重要,但是您不应该调用 super.visitCode() 吗?

@Override
public void visitCode() {
  super.visitCode();
  ...

我会使用 TraceClassVisitor 来准确检查正在生成的内容。

Perhaps it does not matter, but shouldn't you be calling super.visitCode()?

@Override
public void visitCode() {
  super.visitCode();
  ...

I'd use TraceClassVisitor to check exactly what was being generated.

最初的梦 2024-08-06 20:24:10

看来您的代码是正确的,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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文