字节好友成员替换引发IllegalStateException错误 [英] Byte Buddy Member Substitution throwing IllegalStateException error

查看:70
本文介绍了字节好友成员替换引发IllegalStateException错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用字节伙伴来编写Java工具代理.我的目标是用我自己的代理调用替换java标准库方法调用.建议我使用Byte Buddy的 MemberSubstitution 来实现此目的.我使用了 this

I'm trying to write a java instrumentation agent using byte buddy. My goal is to replace a java standard library method call with a proxy call of my own. I was suggested to use Byte Buddy's MemberSubstitution to achieve this. I used this and this questions from SO for my reference.

我正在使用Intellij IDEA进行编码.我的座席代码分为以下多个文件:

I'm using Intellij IDEA for coding. My Agent code is split into multiple files as follows:

MyFirstAgent.java

public class MyFirstAgent {

    public static void premain(String agentArgs, Instrumentation inst) {

        new AgentBuilder.Default()
                .type(ElementMatchers.any())
                .transform(new ByteBuddyTransformer())
                .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
                .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
                .installOn(inst);
}

ByteBuddyTransformer.java

public class ByteBuddyTransformer implements AgentBuilder.Transformer {

    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
                                            ClassLoader classLoader, JavaModule javaModule) {

        try {
            return builder.visit(MemberSubstitution.relaxed()
                    .method(named("add"))
                    .replaceWith(MyClass.class.getMethod("printLine"))
                    .on(any()));

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return builder;
    }
}

MyClass.java

public class MyClass {
    public boolean printLine(){
        System.out.println("This is the proxy!");
        return true;
    }
}

我要检测的应用程序位于另一个具有以下内容的Intellij IDEA项目中:

And the application that I want to instrument is in another Intellij IDEA project with the following:

Main.java

public class Main {
    public static void main(String[] args) {
        ClassToMonitor classToMonitor = new ClassToMonitor();
        classToMonitor.bar();
    }
}

ClassToMonitor.java

package com.company;

import java.util.ArrayList;
import java.util.Arrays;

public class ClassToMonitor {
    public void bar() {
// create an empty array list with an initial capacity
        ArrayList<Integer> arrlist = new ArrayList<Integer>(5);

// use add() method to add elements in the list
        arrlist.add(15);

// print all the elements available in list
        for (Integer number : arrlist) {
            System.out.println("Number = " + number);
        }
    }
}

当我构建代理的胖子并用我的应用程序运行它时,出现以下错误:

When I build the fat jar of my agent and run it with my application, I get the following error:

[Byte Buddy] ERROR com.company.ClassToMonitor [jdk.internal.loader.ClassLoaders$AppClassLoader@2626b418, unnamed module @385e9564, loaded=false]
java.lang.IllegalStateException: Cannot invoke public boolean com.company.MyClass.printLine() on [class java.util.ArrayList, E]

如果需要,我可以提供完整的错误消息.另外,我一般都不是Java和Instrumentation的新手,所以我可能在这里缺少一些基本的知识,请原谅并指出是这种情况.

I can provide the full error message if required. Also, I'm new to Java and Instrumentation in general so I might be missing something fundamental here, please kindly excuse me and point it out if that's the case.

推荐答案

为使替换起作用,目标方法需要接受与被替换方法相同的参数,在您的情况下为 int .另外,由于您正在调用成员,因此该类的隐式第一个参数必须是接收器类型,即 ArrayList 或任何超级类型,甚至是 Object .另外,您的替换方法必须是静态的:

For substitution to work, the target method needs to accept the same arguments as the replaced method, in your case an int. Also, since you are calling a member, the implicit first argument of your class needs to be the receiver type, i.e. ArrayList or any super type, even Object. Also, your replacement method needs to be static:

public class MyClass {
  public static boolean printLine(Object ignored, int ignored2){
    System.out.println("This is the proxy!");
    return true;
  }
}

MemberSubstitution仍然没有它应有的灵活性.但是,如果需要的话,您可以使用 chained 步骤注入自定义字节码.

MemberSubstitution is still not as flexible as it is supposed to be. You can however already inject custom byte code using the chained step if that is what you want.

这篇关于字节好友成员替换引发IllegalStateException错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆