Невозможно установить apache httpclient, используя javaagent для приложения весенней загрузки Uber JAR

Я пытаюсь написать javaagent с Bytebuddy для перехвата запросов Apache httpclient, и я хочу использовать этот агент для весенней загрузки приложения. Агент работает нормально, когда я запускаю тестовое весеннее загрузочное приложение из Idea (напрямую запускаю метод main). Тем не менее, когда я упаковываю приложение в весеннюю загрузку Uber JAR и запускаю его с помощьюjava -javaagent:myagent.jar -jar myapplication.jar, он бросает следующее исключение.

onError:org.apache.http.impl.client.AbstractHttpClient
java.lang.NoClassDefFoundError: org/apache/http/HttpHost
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.getDeclaredMethods(Class.java:1975)
    at net.bytebuddy.description.method.MethodList$ForLoadedType.<init>(MethodList.java:106)
    at net.bytebuddy.description.type.TypeDescription$ForLoadedType.getDeclaredMethods(TypeDescription.java:985)
    at net.bytebuddy.implementation.MethodDelegation$MethodContainer$ForExplicitMethods.ofStatic(MethodDelegation.java:1037)
    at net.bytebuddy.implementation.MethodDelegation.to(MethodDelegation.java:247)
    at net.bytebuddy.implementation.MethodDelegation.to(MethodDelegation.java:226)
    at com.yiji.dtrace.agent.httpclient4.interceptor.HttpClient4Interceptors$1.transform(HttpClient4Interceptors.java:48)
    at net.bytebuddy.agent.builder.AgentBuilder$Transformer$Compound.transform(AgentBuilder.java:457)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$Transformation$Simple$Resolution.apply(AgentBuilder.java:2791)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:3081)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:170)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:142)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:170)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:142)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:170)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:142)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at com.yjf.common.net.HttpUtil.<init>(HttpUtil.java:118)
    at com.yjf.common.net.HttpUtil.<init>(HttpUtil.java:81)
    at com.yjf.common.net.HttpUtil.<clinit>(HttpUtil.java:78)
    at com.daidai.dtrace.agent.test.Main.main(Main.java:35)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.http.HttpHost
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 60 more

и вот мой код, связанный с агентом.

public class DTraceAgent {

    public static TypeDescription abstractHttpClientDescription() {
        return new TypeDescription.Latent("org.apache.http.impl.client.AbstractHttpClient",
                Modifier.PUBLIC|Modifier.ABSTRACT,
                TypeDescription.OBJECT,
                Arrays.asList(httpClientDescription()));
    }

    public static TypeDescription httpHostDescription() {
        return new TypeDescription.Latent("org.apache.http.HttpHost",
                Modifier.PUBLIC|Modifier.FINAL,
                TypeDescription.OBJECT,
                Arrays.asList(new TypeDescription.ForLoadedType(Cloneable.class),
                        new TypeDescription.ForLoadedType(Serializable.class)));
    }

    public static TypeDescription httpContextDescription() {
        return new TypeDescription.Latent("org.apache.http.protocol.HttpContext",
                getInterfaceModifiers(),
                TypeDescription.OBJECT,
                null);
    }

    public static TypeDescription httpRequestDescription() {
        return new TypeDescription.Latent("org.apache.http.HttpRequest",
                getInterfaceModifiers(),
                httpMessageDescription(),
                null);
    }

    public static void premain(String arguments, Instrumentation instrumentation) {
        new AgentBuilder.Default()
                //.withBinaryLocator(binaryLocatorFor(instrumentation))
                .withListener(DebugListener.getListener())
                .type(is(abstractHttpClientDescription()))
                .transform(new AgentBuilder.Transformer() {
                    public DynamicType.Builder transform(DynamicType.Builder builder,
                                                         TypeDescription typeDescription) {
                        return builder.method(named("execute")
                                .and(takesArguments(httpHostDescription(), httpRequestDescription(), httpContextDescription()))
                                .and(returns(named("org.apache.http.HttpResponse"))))
                                .intercept(MethodDelegation.to(HttpClientInterceptor4dot3Plus.class));
                    }
                }).installOn(instrumentation);
    }
}

public class HttpClientInterceptor4dot3Plus {

    public static CloseableHttpResponse doExecute(
            @SuperCall Callable<CloseableHttpResponse> client, @Argument(1)HttpRequest request
            ) throws Exception {
        StringBuilder builder = new StringBuilder(1024);
        if (request != null && request.getRequestLine() != null) {
            RequestLine requestLine = request.getRequestLine();
            builder.append(requestLine.getMethod()).append(" ").append(requestLine.getUri());
        }
        try (TraceScope scope = Trace.startSpanForEntry(builder.toString())) {
            Trace.spanType(Span.SPAN_TYPE_HTTP);
            try {
                return client.call();
            } catch (Exception e) {
                Trace.except,ion(e);
                throw e;
            }
        }
    }
}

public class DebugListener {
    public static AgentBuilder.Listener getListener() {
        return new AgentBuilder.Listener() {
            @Override
            public void onTransformation(TypeDescription typeDescription, DynamicType dynamicType) {
                System.err.println("onTransformation:" + typeDescription.getCanonicalName());
                try {
                    dynamicType.saveIn(new File("generated_classes"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onIgnored(TypeDescription typeDescription) {
                //System.err.println("onIgored:" + typeDescription.getCanonicalName());
            }

            @Override
            public void onError(String typeName, Throwable throwable) {
                System.err.println("onError:" + typeName);
                throwable.printStackTrace();
            }

            @Override
            public void onComplete(String typeName) {
                //System.err.println("onComplete:" + typeName);
            }
        };
    }
}

Я думаю, что эта проблема вызвана тем, как весенняя загрузка uber jar загружает приложение. Spring boot предоставляет специальный загрузчик классов с именем LaunchedURLClassLoader для загрузки классов, связанных с приложением, из uber jar, в то время как javaagent jar загружается по умолчанию системным загрузчиком классов (если я правильно понимаю). Таким образом, apache httpclient lib (включенный в uber jar) не виден системному загрузчику классов.

Я пытался предоставить BinaryLocator для AgentBuilder, но он не работал. Возможно, BinaryLocator был создан неправильно. В любом случае, правильный BinaryLocator может быть возможным решением.

Большое спасибо за любые решения или предложения.

Другая информация может быть полезна:
версия 1.3.1 с весенней загрузкой
byte-buddy 0.7.7, упакованный в агент с помощью jar-with-dependencies maven-assembly-plugin descriptorRef
apache httpclient 4.3.2

Ответы на вопрос(1)

Ваш ответ на вопрос