问题
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