Oracle JDK与OpenJDK的HttpURLConnection行为差异是特性还是Bug?
Oracle JDK与OpenJDK 8中HttpURLConnection代理回退行为差异分析
近期发现Oracle JDK与OpenJDK的HttpURLConnection存在行为差异,特此咨询该差异属于特性设计还是Bug。
- Oracle JDK 8u311版本中修复了JDK-8161016问题:原本HttpURLConnection在代理连接失败时会自动回退到直接连接,该版本将默认行为改为抛出异常,同时提供
sun.net.http.fallbackToDirect系统属性用于恢复旧的回退行为。 - 测试发现该属性在Oracle JDK中可正常工作,但在OpenJDK 8u312中完全无效。查看OpenJDK对应源码后发现,仅实现了该Bug修复的第一个子任务(修改默认行为为抛异常),第二个子任务(添加属性支持回退)并未实现。此外,OpenJDK的Bug追踪系统中标注该修复的版本为8u311,但OpenJDK本身并不存在8u311这个版本号。
补充测试1:可复现示例代码
基于原Bug修复的测试类编写了最小可复现示例(MRE):
- 在Oracle JDK 8u311中运行时,设置
sun.net.http.fallbackToDirect=true后,代理超时会触发回退到直接连接的尝试,测试输出Fallback to DIRECT connection works!; - 在OpenJDK 8u312-b07(Adoptium构建)中运行时,该属性被忽略,最终抛出
SocketTimeoutException,测试输出There is no fallback to a DIRECT connection attempt.。
测试环境为Windows 10。
import java.io.IOException; import java.net.ServerSocket; import java.net.URL; import java.net.URLConnection; public class ProxyMRE { public static void main(String... arg) { // 移除默认nonProxyHosts以用localhost测试 System.setProperty("http.nonProxyHosts", ""); System.setProperty("http.proxyHost", "1.1.1.1"); System.setProperty("http.proxyPort", "1111"); // 设置回退属性(OpenJDK中无此逻辑) System.setProperty("sun.net.http.fallbackToDirect", "true"); ServerSocket ss; URL url; URLConnection con; // 测试:使用系统属性设置的代理 try { ss = new ServerSocket(0); url = new URL("http://localhost:" + ss.getLocalPort()); con = url.openConnection(); con.setConnectTimeout(10 * 1000); con.connect(); System.out.println("Fallback to DIRECT connection works!"); } catch (IOException ie) { System.out.println("There is no fallback to a DIRECT connection attempt."); } } }
补充测试2:变更时间线梳理
- 原修复(代理失败时不再默认回退到直接连接)于2016年在Java 9开发阶段引入,Java 9首个版本的变更日志明确提及该变更,但未提到用于恢复回退的属性。
- 2021年该修复被反向移植到Java 7和8,此时Oracle引入了
sun.net.http.fallbackToDirect属性,在Oracle JDK 8u311、7u321的版本说明及子任务JDK-8268881中均有提及,但该属性的实现逻辑并未同步到OpenJDK源码中。 - 该行为差异在Java 8的最新版本8u361中仍然存在,Java 9及后续版本无此问题。
内容的提问来源于stack exchange,提问作者dimizuno
相关产品推荐
相关产品推荐

