Java 字节伙伴成员替换引发IllegalStateException错误
我正在尝试使用byte buddy编写java检测代理。我的目标是用我自己的代理调用替换java标准库方法调用。有人建议我使用Byte Buddy的Java 字节伙伴成员替换引发IllegalStateException错误,java,instrumentation,byte-buddy,Java,Instrumentation,Byte Buddy,我正在尝试使用byte buddy编写java检测代理。我的目标是用我自己的代理调用替换java标准库方法调用。有人建议我使用Byte Buddy的MemberSubstitution来实现这一点。我使用了SO提出的问题作为参考 我正在使用Intellij IDEA进行编码。我的代理代码被拆分为多个文件,如下所示: MyFirstAgent.java public class MyFirstAgent { public static void premain(String agentA
MemberSubstitution
来实现这一点。我使用了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);
}
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;
}
}
public class MyClass {
public boolean printLine(){
System.out.println("This is the proxy!");
return true;
}
}
public class Main {
public static void main(String[] args) {
ClassToMonitor classToMonitor = new ClassToMonitor();
classToMonitor.bar();
}
}
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);
}
}
}
ByteBuddyTransformer.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);
}
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;
}
}
public class MyClass {
public boolean printLine(){
System.out.println("This is the proxy!");
return true;
}
}
public class Main {
public static void main(String[] args) {
ClassToMonitor classToMonitor = new ClassToMonitor();
classToMonitor.bar();
}
}
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);
}
}
}
我想在另一个Intellij IDEA项目中使用的应用程序如下所示:
Main.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);
}
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;
}
}
public class MyClass {
public boolean printLine(){
System.out.println("This is the proxy!");
return true;
}
}
public class Main {
public static void main(String[] args) {
ClassToMonitor classToMonitor = new ClassToMonitor();
classToMonitor.bar();
}
}
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);
}
}
}
ClassToMonitor.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);
}
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;
}
}
public class MyClass {
public boolean printLine(){
System.out.println("This is the proxy!");
return true;
}
}
public class Main {
public static void main(String[] args) {
ClassToMonitor classToMonitor = new ClassToMonitor();
classToMonitor.bar();
}
}
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);
}
}
}
如果需要,我可以提供完整的错误消息。另外,我对Java和插装一般来说是新手,所以我可能缺少一些基本的东西,请原谅,如果是这样的话,请指出。要让替换工作,目标方法需要接受与替换方法相同的参数,在您的例子中是一个
int
。此外,由于您正在调用一个成员,因此类的隐式第一个参数需要是接收方类型,即ArrayList
或任何超类型,甚至Object
。此外,您的替换方法需要是静态的:
public class MyClass {
public static boolean printLine(Object ignored, int ignored2){
System.out.println("This is the proxy!");
return true;
}
}
成员替代仍然没有想象的那么灵活。但是,如果需要,您已经可以使用
链接的步骤注入自定义字节码。要进行替换,目标方法需要接受与替换方法相同的参数,在您的示例中是int
。此外,由于您正在调用一个成员,因此类的隐式第一个参数需要是接收方类型,即ArrayList
或任何超类型,甚至Object
。此外,您的替换方法需要是静态的:
public class MyClass {
public static boolean printLine(Object ignored, int ignored2){
System.out.println("This is the proxy!");
return true;
}
}
成员替代仍然没有想象的那么灵活。但是,如果您需要的话,您可以使用chained
步骤注入自定义字节码