我的计划是使用带有ByteBuddy的Java代理来操纵不同Java模块之间的指定方法。我想替换方法主体,并注入一个zeroMQ-client,它调用在另一个JVM中运行的服务,其中包括被替换的方法。
Java:
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
ByteBuddy 1.8.12
因此,我编写了以下代理类:
public static void premain(String arg, Instrumentation inst) {
System.out.println("\"Entered premain\"");
new AgentBuilder.Default().with(new AgentBuilder.Listener() { /*...*/})
.type(ElementMatchers.any())
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {
return builder.method(ElementMatchers.nameMatches("calc"))
.intercept(MethodDelegation.to(FooInterceptor.class));
}
}).installOn(inst);
}//premain
和拦截器:
public class FooInterceptor {
static FooInterceptor dispatcher = new FooInterceptor();
@RuntimeType
public static void doIntercept(@Argument(0) String[] arg, @Origin Method method) {
dispatcher.intercept("String");
}
@RuntimeType
public static void doIntercept(@Argument(0) double[] arg, @Origin Method method) {
double d = dispatcher.intercept("double");
}
public double intercept(String typ) {
System.out.println(typ + " Interceptor called");
InnerClass c = new InnerClass();
return 1.0;
}
class InnerClass {
private final static int REQUEST_TIMEOUT = 2500;
private final static int REQUEST_RETRIES = 3;
private String SERVER_ENDPOINT;
private ZContext ctx;
private Socket client;
private double avg = 0;
InnerClass() {
this.ctx = new ZContext();
this.client = ctx.createSocket(ZMQ.REQ);
}
}
}
InnerClass应该代表客户端的生成。但是在运行我的应用程序时,我得到了以下堆栈跟踪:
java.lang.NoClassDefFoundError: jdk/internal/reflect/GeneratedMethodAccessor8
at jdk.internal.reflect.GeneratedMethodAccessor8.<clinit>(Unknown Source)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at java.base/java.lang.Class.newInstance(Class.java:560)
at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:404)
at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/jdk.internal.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
at java.base/jdk.internal.reflect.MethodAccessorGenerator.generateMethod(MethodAccessorGenerator.java:75)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:53)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at jeromq@0.4.3/zmq.pipe.YPipe.<clinit>(YPipe.java:5)
at jeromq@0.4.3/zmq.Mailbox.<init>(Mailbox.java:38)
at jeromq@0.4.3/zmq.Ctx.<init>(Ctx.java:159)
at jeromq@0.4.3/zmq.ZMQ.createContext(ZMQ.java:274)
at jeromq@0.4.3/zmq.ZMQ.init(ZMQ.java:312)
at jeromq@0.4.3/org.zeromq.ZMQ$Context.<init>(ZMQ.java:273)
at jeromq@0.4.3/org.zeromq.ZMQ.context(ZMQ.java:257)
at jeromq@0.4.3/org.zeromq.ZContext.getContext(ZContext.java:285)
at jeromq@0.4.3/org.zeromq.ZContext.createSocket(ZContext.java:124)
at FooInterceptor$InnerClass.<init>(FooInterceptor.java:56)
at FooInterceptor.intercept(FooInterceptor.java:37)
at FooInterceptor.doIntercept(FooInterceptor.java:29)
at service.a/com.service.ServiceImpl.calc(ServiceImpl.java)
at app/com.main.Main.main(Main.java:30)
Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedMethodAccessor8
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 28 more
我发现
this.client = ctx.createSocket(ZMQ.REQ);
是问题的根源,但我不知道如何解决。
有人在这里,谁对异常有更多了解,或有解决方法的提示?也许这也是一个明显的错误,那么对不起。这是我的第一个项目,它更多地参与了Java反射和字节码操作。
最好的问候 弗洛里安