问题
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):
package instrumenting;
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});
}
}
}
how its caled:
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());
}
}
The output:
[Instrumentation] starting to instrument 'java.net.ServerSocket'
[Instrumentation] done
[GetLocalPortIntercept] Localport: 42
[GetInetAddressIntercept] InetAddress: /1.2.3.4
Intercepting getLocalPort
and getInetAddress
works fine as you can see. But why is the constructor not intercepted?
回答1:
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.
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.
来源:https://stackoverflow.com/questions/61232301/bytebuddy-intercept-java-net-serversocket-constructor