You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 17无法拦截java.net.HttpURLConnection方法的解决方案咨询

解决方案:Java 17下用ByteBuddy拦截HttpURLConnection.connect()

问题根源

Java 17的模块系统(JPMS)限制了对核心模块内部类的访问,且ByteBuddy旧版手动注入方式无法适配模块权限;同时java.net.HttpURLConnection是抽象类,实际执行connect()逻辑的是其实现类sun.net.www.protocol.http.HttpURLConnection,直接拦截抽象类方法不会生效。

修改步骤与代码

1. 适配模块权限与ByteBuddy API

使用ByteBuddy内置的bootstrap注入策略自动处理拦截器的类加载权限,修正transform方法参数以适配Java 17编译要求,并指定拦截实际实现类。

2. 修改后的完整代码

package com.bytebuddy.bytebuddydemo.test;

import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
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.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
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());
        urlConnection.connect();
        System.out.println(urlConnection.getResponseCode());
    }

    public static void premain(String arg, Instrumentation instrumentation) {
        new AgentBuilder.Default()
                .ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
                // 启用重转换,支持修改已加载的类
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                // 自动处理bootstrap类加载器下的注入权限
                .with(AgentBuilder.InitializationStrategy.ForBootstrapInjection.INSTANCE)
                // 拦截实际实现类
                .type(ElementMatchers.named("sun.net.www.protocol.http.HttpURLConnection"))
                // 补充protectionDomain参数适配Java 17编译要求
                .transform((builder, typeDescription, classLoader, module, protectionDomain) -> 
                        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 connect() method!");
            System.out.println("Method details: " + method);
            zuper.call();
        }
    }
}

3. 运行所需JVM参数

Java 17下需添加以下参数开放核心模块访问权限:

--add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED

关键修改说明

  • 拦截实际实现类:替换原匹配规则为sun.net.www.protocol.http.HttpURLConnection,确保拦截到真正执行逻辑的方法。
  • 自动bootstrap注入:移除手动ClassInjector代码,改用ByteBuddy内置策略,自动处理模块环境下的类注入权限问题。
  • 适配编译要求:补充protectionDomain参数,满足Java 17对AgentBuilder.transform方法的参数要求。
  • 启用重转换:添加重转换策略,保证已加载的目标类可以被修改。

内容的提问来源于stack exchange,提问作者Tejas Soneri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:35:38