java - Bytebuddy - 拦截 java.net.ServerSocket 构造函数
问题描述
我试图拦截java.net.ServerSocket
. 拦截这两种方法getLocalPort
并且getInetAddress
工作正常。ServerSocket(int)
但是,不会触发应该处理构造函数的类。我要检测的代码(在主项目中包含的不同 jar 文件中):
包检测;
public class Instrumenting {
private static final String CLASS_NAME = "java.net.ServerSocket";
public static void instrument(Instrumentation instrumentation) throws Exception {
System.out.println("[Instrumenting] starting to instrument '" + CLASS_NAME + "'");
instrumentation.appendToBootstrapClassLoaderSearch(new JarFile("C:\\Users\\Moritz\\Instrumenting\\dist\\Instrumenting.jar"));
File temp = Files.createTempDirectory("tmp").toFile();
ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, instrumentation).inject(Collections.singletonMap(
new TypeDescription.ForLoadedType(GetLocalPortIntercept.class),
ClassFileLocator.ForClassLoader.read(GetLocalPortIntercept.class)));
new AgentBuilder.Default()
.ignore(ElementMatchers.none())
.with(new AgentBuilder.InjectionStrategy.UsingInstrumentation(instrumentation, temp))
.type(ElementMatchers.named(CLASS_NAME))
.transform((DynamicType.Builder<?> builder, TypeDescription td, ClassLoader cl, JavaModule jm) ->
builder
.method(ElementMatchers.named("getLocalPort"))
.intercept(MethodDelegation.to(GetLocalPortIntercept.class))
.method(ElementMatchers.named("getInetAddress"))
.intercept(MethodDelegation.to(GetInetAddressIntercept.class))
.constructor(ElementMatchers.takesArguments(1).and(ElementMatchers.takesArguments(Integer.class)))
.intercept(MethodDelegation.to(ServerSocketIntercept.class))
).installOn(instrumentation);
System.out.println("[Instrumenting] done");
}
public static class ServerSocketIntercept {
public static void intercept(int port) throws Exception {
System.out.println("[ServerSocketIntercept] port: " + port);
}
}
public static class GetLocalPortIntercept {
public static int intercept() throws Exception {
System.out.println("[GetLocalPortIntercept]");
return 42;
}
}
public static class GetInetAddressIntercept {
public static InetAddress intercept() throws Exception {
System.out.println("[GetInetAddressIntercept]");
return InetAddress.getByAddress(new byte[] {1, 2, 3 ,4});
}
}
}
它是如何命名的:
import instrumenting.Instrumenting;
...
public class Main {
public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception {
Instrumenting.instrument(instrumentation);
}
public static void main(String[] args) throws MalformedURLException, IOException {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Localport: " + serverSocket.getLocalPort());
System.out.println("InetAddress: " + serverSocket.getInetAddress());
}
}
输出:
[Instrumentation] starting to instrument 'java.net.ServerSocket'
[Instrumentation] done
[GetLocalPortIntercept] Localport: 42
[GetInetAddressIntercept] InetAddress: /1.2.3.4
如您所见,拦截getLocalPort
和工作正常。getInetAddress
但是为什么构造函数没有被拦截呢?
解决方案
这是因为ServerSocket
接受 anint
而不是Integer
. 但是,如果您尝试这样做,它会崩溃,因为 JVM 需要将超级方法调用硬编码到任何构造函数中。您需要运行:SuperMethodCall.INSTANCE.andThen(...)
在实际拦截之前使其工作。
一般来说,我建议您Advice
在 JVM 类上使用此类引导代理,您可以在其中将代码内联到目标中。它会更健壮。
推荐阅读
- python - 如何使用 Selenium Python XPATH 获取文本
- json - jq在变量的帮助下更新键和值
- android - Scaffold 主体中的有状态小部件
- sql-server - 如何处理聚合根之间的引用并发?
- go - 为什么会出现致命错误:所有 goroutine 都处于休眠状态 - 死锁!在这段代码中?
- javascript - 在 node.js 中显示网络摄像头提要、捕获图像并将其保存在本地?
- c# - 401错误,此请求的授权已被拒绝
- javascript - 如何使用 JavaScript 滚动到目标 html 部分的垂直中心?
- javascript - 如何使用 javascript 中的搜索过滤器和复选框过滤器制作高级过滤器逻辑?
- assembly - 为什么 NASM 汇编 64 位 printf 不打印浮点除法的值?