raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.29k stars 807 forks source link

Not able to intercept methods of java.net.HttpURLConnection class in Java 17 #1581

Closed parmar-tejas closed 1 month ago

parmar-tejas commented 10 months ago

The provided code intercepts the connect method of the HttpURLConnection class in Java 8. However, when attempting to run the same code with Java 17, it results in an error provided below. please provide any solutions or suggestion.

CODE :

package com.bytebuddy.bytebuddydemo.test;

import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;

import java.io.File;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.Collections;
import java.util.concurrent.Callable;

public class Test {
    public static void main(String[] args) throws Exception {
        premain(null, ByteBuddyAgent.install());
        HttpURLConnection urlConnection = (HttpURLConnection) new URL("http://www.google.com").openConnection();
        System.out.println(urlConnection.getRequestMethod());
        System.out.println(urlConnection.getResponseCode());
    }

    public static void premain(String arg, Instrumentation instrumentation) throws Exception {
        File tempDirectory = Files.createTempDirectory("tmp").toFile();
        ClassInjector.UsingInstrumentation
                .of(tempDirectory, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, instrumentation)
                .inject(Collections.singletonMap(new TypeDescription.ForLoadedType(MyInterceptor.class),
                        ClassFileLocator.ForClassLoader.read(MyInterceptor.class)));
        new AgentBuilder.Default().ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
                .with(new AgentBuilder.InjectionStrategy.UsingInstrumentation(instrumentation, tempDirectory))
                .type(ElementMatchers.nameEndsWith(".HttpURLConnection"))
                .transform((builder, typeDescription, classLoader, module) -> builder
                        .method(ElementMatchers.named("connect")).intercept(MethodDelegation.to(MyInterceptor.class)))
                .installOn(instrumentation);
    }

    public static class MyInterceptor {
        public static void intercept(@SuperCall Callable<?> zuper, @Origin Method method) throws Exception {
            System.out.println("Intercepted!");
            System.out.println("method :: !" + method);
            zuper.call();

        }
    }
}

ERROR :

Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended Exception in thread "main" java.lang.ExceptionInInitializerError at java.base/sun.net.www.protocol.http.Handler.openConnection(Handler.java:62) at java.base/sun.net.www.protocol.http.Handler.openConnection(Handler.java:57) at java.base/java.net.URL.openConnection(URL.java:1094) at com.JavaAgent.Agent.Test.main(Test.java:26) Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/sun.net.www.protocol.http.HttpURLConnection.(HttpURLConnection.java:435) ... 4 more Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at net.bytebuddy.dynamic.Nexus.initialize(Nexus.java:143) ... 9 more Caused by: java.lang.IllegalStateException: Cannot load injected class at net.bytebuddy.dynamic.loading.ClassInjector$UsingInstrumentation.injectRaw(ClassInjector.java:2498) at net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase.inject(ClassInjector.java:118) at net.bytebuddy.agent.builder.AgentBuilder$InitializationStrategy$SelfInjection$Dispatcher$InjectingInitializer.onLoad(AgentBuilder.java:3855) ... 14 more Caused by: java.lang.ClassNotFoundException: sun/net/www/protocol/http/HttpURLConnection$auxiliary$vcxnSSGw at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:467) at net.bytebuddy.dynamic.loading.ClassInjector$UsingInstrumentation.injectRaw(ClassInjector.java:2487) ... 16 more

raphw commented 10 months ago

I assume this has to do with the module system preresolving names and not finding the new class. I would avoid auxiliary classes in such injection and rather use Advice to address such instrumentation.