问题描述
Iam试图拦截 java.net.ServerSocket
的两个方法和一个构造函数.拦截两个方法 getLocalPort
和 getInetAddress
可以正常工作.但是,不会触发应处理构造方法 ServerSocket(int)
的类.我要检测的代码(在包含在mainproject中的另一个jar文件中):
Iam Trying to Intercept two methods and one constructor of java.net.ServerSocket
.Intercepting the two methods getLocalPort
and getInetAddress
works fine. However, the class which should handle the constructor ServerSocket(int)
is not triggered. My code to instrument (inside a different jar-file which is included to the mainproject):
包装检测;
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
可以正常工作.但是为什么构造函数没有被拦截?
Intercepting getLocalPort
and getInetAddress
works fine as you can see. But why is the constructor not intercepted?
推荐答案
这是因为 ServerSocket
接受 int
而不是 Integer
.但是,如果您尝试此操作,则会崩溃,因为JVM需要将超级方法调用硬编码到任何构造函数中.您需要先运行: SuperMethodCall.INSTANCE.andThen(...)
,然后才能进行实际拦截.
It's because ServerSocket
accepts an int
and not an Integer
. It would however crash if you tried this since the JVM requires a super method call hard-coded into any constructor. You'd need to run: SuperMethodCall.INSTANCE.andThen(...)
before your actual intercept to make it work.
通常,我建议您对JVM类上的此类引导代理使用 Advice
,您可以在其中将代码内联到目标中.这样会更健壮.
In general, I'd recommend you to use Advice
for such bootstrap agents on JVM classes where you can inline code into a target. It would be more robust.
这篇关于Bytebuddy-拦截java.net.ServerSocket构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!