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