Подстановка байтового члена Заменяющая ошибка IllegalStateException - PullRequest
1 голос
/ 08 марта 2020

Я пытаюсь написать инструментальный агент java, используя байтового партнера. Моя цель - заменить стандартный метод библиотеки java собственным прокси-вызовом. Мне предложили использовать MemberSubstitution Byte Buddy для достижения этой цели. Для справки я использовал это и это вопросы от SO.

Я использую Intellij IDEA для кодирования. Код моего агента разделен на несколько файлов следующим образом:

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 со следующим:

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);
        }
    }
}

Когда я создаю толстую банку моего агента и запустить его с моим приложением, я получаю следующую ошибку:

[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 и приборостроении в целом, поэтому я могу упустить что-то фундаментальное здесь, пожалуйста, извините меня и укажите, если это так.

1 Ответ

0 голосов
/ 19 марта 2020

Чтобы подстановка работала, целевой метод должен принимать те же аргументы, что и замененный метод, в вашем случае - int. Кроме того, поскольку вы вызываете член, неявным первым аргументом вашего класса должен быть тип получателя, то есть ArrayList или любой супертип, даже Object. Кроме того, ваш метод замены должен быть следующим: c:

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

MemberSubstitution все еще не настолько гибок, как это должно быть. Тем не менее, вы можете уже ввести пользовательский байт-код, используя шаг chained, если вы этого хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...