Bytebuddy - Перехватчик java. net .ServerSocket конструктор - PullRequest
1 голос
/ 15 апреля 2020

Я пытаюсь перехватить два метода и один конструктор 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 работает нормально, как вы можете видеть. Но почему конструктор не перехватывается?

1 Ответ

1 голос
/ 16 апреля 2020

Это потому, что ServerSocket принимает int, а не Integer. Однако, если вы попробуете это, то будет стоить sh, поскольку JVM требует супер-вызова метода, жестко запрограммированного в любом конструкторе. Вам нужно выполнить: SuperMethodCall.INSTANCE.andThen(...) до фактического перехвата, чтобы он заработал.

В общем, я бы рекомендовал вам использовать Advice для таких bootstrap агентов в классах JVM, где вы можете встроенный код в цель. Это было бы более надежным.

...