Java 为何为你的 HTTP 请求选择了 SOCKS 代理
在套用旧的 Windows 代理变通方案之前,先检查 ProxySelector 的结果和生效的 JVM 设置。
一个 Java 请求可能遇到多种代理输入:显式的客户端配置、默认选择器、JVM 网络属性以及受支持的操作系统设置。当日志意外提到 SOCKS 时,先确定是哪一种输入选择了它。
对于使用默认选择器的代码,检查针对确切目标的决策:
URI target = URI.create("https://example.com/");
ProxySelector selector = ProxySelector.getDefault();
if (selector != null) {
System.out.println(selector.select(target));
}
这会报告选择器的候选者。它不能证明最终哪条连接成功,而且自带显式路由的客户端可能做出不同选择。
检查生效的设置
检查 http.proxyHost、https.proxyHost、socksProxyHost 及其端口,还有 java.net.useSystemProxies。JDK 网络属性文档说明了它们的作用范围和优先级。系统代理发现只在启动时检查;启动 JVM 时要有意设置它。
历史答案描述的是旧 Windows 对话框与旧 JDK 的特定组合。那些报告可以解释某个变通方案的由来,但不能证明当前运行时存在同样的缺陷。在更改每个应用的操作系统设置之前,先记录运行时版本和选择器输出。
如果应用需要为单个客户端使用 HTTP 代理,显式代理配置可以让这一要求更清楚。如果需要集中自动路由,就要调查选择器为何收到或返回了意外的 SOCKS 条目。
自定义选择器应保留有意的绕过和失败处理。不加区分地过滤每个 SOCKS 候选者,可能破坏本应使用它的连接。用你能确定的最小范围修正错误的规则。