给 JDK 报了一个 P4 的 Bug,结果居然……

基于 MATLAB 的综合能源系统建模:全面解析与案例应用  本文详细介绍了基于 MATLAB 的综合能源系统建模相关知识,包括 MATLAB 在综合能源建模中的优势、综合能源系统各组件和网络的建模方法,并通过园区综合能源系统的案例展示了从建模到优化调度求解以及结果分析的全过程。在当今全球能源格局深刻变革的背景下,综合能源系统(Integrated Energy System,IES)作为一种创新的能源供应体系,整合了多种能源形式,如电力、热力、燃气等,以实现能源的高效生产、传输、分配和利用。需要考虑燃气的压力、流量特性以及管道的阻力特性等。 阅读详情

图 by:石头@北京-望京

关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。欢迎关注,交流和指导!

背景

分享一下之前踩的一个坑,背景是这样的:

我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是很常见的一个场景。本地和测试环境测试都没有问题,一切就绪上了生产后,程序调用接口就总是网络不通。

需要说明的是本地、测试环境、生产环境通过不同的域名访问该外部服务。生产程序调用不通,神奇的是在生产环境通过 curl 等命令却能够正常调用对方接口。

What??

这 TM 就神奇了,唯一不同的就是发起 HTTP 请求的客户端了,估计就是 http客户端有问题了?通过最后排查发现,居然发现了一枚 “JDK 的 bug”,然后石头就提交到了 JDK 的官网……

下面我们就来重现一下这个问题。

server 端准备

这里用 Nginx 模拟了一下 上文提到的 REST 服务,假设调用正常返回 "Hello, World\n",Nginx 配置如下:

server {
    listen    80;
    server_name test_1.tanglei.name;
    location /testurl {
        add_header Content-Type 'text/plain; charset=utf-8';
        return 200 "Hello, World\n";
    }
}

不同的 client 请求

下面用不同的 Http client (分别用命令行curl,python的 requests包,和 Java 的 URL 等尝试)去请求。

  • curl 请求,正常。

[root@VM_77_245_centos vhost]# curl -i "http://test_1.tanglei.name/testurl"
HTTP/1.1 200 OK
Server: nginx
Content-Length: 13
Connection: keep-alive
Content-Type: text/plain; charset=utf-8

Hello, World
[root@VM_77_245_centos vhost]#
  • python requests 正常。

>>> import requests
>>> r = requests.get("http://test_1.tanglei.name/testurl")
>>> r.text
u'Hello, World\n'
  • Java 的 java.net.URLConnection 同样正常。

static String getContent(java.net.URL url) throws Exception {
    java.net.URLConnection conn = url.openConnection();
    java.io.InputStreamReader in = new java.io.InputStreamReader(conn.getInputStream(), "utf-8");
    java.io.BufferedReader reader = new java.io.BufferedReader(in);    
    StringBuilder sb = new StringBuilder();
    int c = -1;
    while ((c = reader.read()) != -1) {
        sb.append((char)c);
    }
    reader.close();
    in.close();
    String response = sb.toString();
    return response;
}

上面的这个方法 String getContent(java.net.URL url) 传入一个构造好的 java.net.URL 然后 get 请求,并以 String 方式返回 response。

String srcUrl = "http://test_1.tanglei.name/testurl";
java.net.URL url = new java.net.URL(srcUrl);
System.out.println("\nurl result:\n" + getContent(url)); // OK

上面的语句输出正常,结果如下:

url result:
Hello, World

这就尼玛神奇了吧。看看我们程序中用的 httpclient 的实现,结果发现是有用 java.net.URI,心想,这不至于吧,用 URI 就不行了么。

换 java.net.URI 试试? (这里不展开讲URL和URI的区别联系了,可以简单的认为URL是URI的一个子集,详细的可参考 URI、URL 和 URN[1], wiki URI[2])

直接通过java.net.URI构造,再调用 URI.toURL 得到 URL,调用同样正常。

关键的来了,httpclient 源码中用的构造函数是另外一个:

URI(String scheme, String host, String path, String fragment)
Constructs a hierarchical URI from the given components.

我用这个方法构造URI,会构造失败:

new java.net.URI(uri.getScheme(), uri.getHost(), uri.getPath(), null) error: protocol = http host = null
new java.net.URI(url.getProtocol(), url.getHost(), url.getPath(), null) error: Illegal character in hostname at index 11: http://test_1.tanglei.name/testurl

所以问题发现了,我们的项目中依赖的第三方 httpclient包底层用到了 java.net.URI,恰好在 java.net.URI 中是不允许以下划线(_)作为 hostname 字段的。

即 uri.getHost() 和 uri.toURL().getHost() 居然能不相等。

这是 JDK 的 Bug 吧?

有理由怀疑,这是 JDK 的 Bug 吧?

从官网上还真找到了关于包含下划线作为hostname的bug提交issue,戳这里 JDK-8132508 : Bug JDK-8029354 reproduces with underscore in hostname[3],然后发现该 "bug" reporter 的情况貌似跟我的差不多,只不过引爆bug的点不一样。

该 "bug" reviewer 最后以 "Not an Issue" 关闭,给出的理由是:

RFC 952 disallows _ underscores in hostnames. So, this is not a bug.

确实,rfc952[4] 明确明确说了域名只能由 字母 (A-Z)、 数字(0-9)、 减号 (-) 和 点 (.) 组成。

那 OK 吧,既然明确规定了 hostname 不能包含下划线,为啥 java.net.URL 确允许呢?

造成 java.net.URI 和 java.net.URL 在处理 hostname 时的标准不一致,且本身 java.net.URI 在构造的时候也带了 "有色"眼镜,同一个url字符串 通过静态方法 java.net.URI.create(String) 或者通过带1个参数的构造方法 java.net.URI(String) 都能成功构造出 URI 的实例,但通过带4个参数的构造方法就不能构造了。

要知道,在 coding 过程中,尽早反馈异常信息更有利于软件开发持续迭代的过程。我们在开发过程中也应该遵循这一点原则。

于是我就去 JDK 官网提交了一个 bug,大意是说 java.net.URI 和 java.net.URL 在处理hostname的时候标准不一致,容易使开发人员埋藏一些潜在的bug,同时也还把这个问题反馈到 stackoverflow[5] 了

I am wondering, if hostname with underscore is not valid, why the result is differrent between java.net.URI and java.net.URL? Is it a bug or a feature? Here is the example.

java.net.URL url = new java.net.URL("http://test_1.tanglei.name"); 

System.out.println(url.getHost()); //test_1.tanglei.name 

java.net.URI uri = new java.net.URI("http://test_1.tanglei.name"); 

System.out.println(uri.getHost()); //null

这个 JDK bug issue 详细信息见 JDK-8170265 : underscore is allowed in java.net.URL while not in java.net.URI[6],openjdk JDK-8170265[7]

经过初步 Review,被认为是一个 P4 的 Bug,说的是 java.net.URL 遵循的是 RFC 2396 规范,确实不允许含有下划线的 hostname,java.net.URI 做到了, 而 java.net.URL 没有做到。

重点来了,然后,却被另外一个 Reviewer 直接个毙了。给出的原因是 java.net.URL 构造方法中,API 文档中说了本来也不会做验证即 No validation of the inputs is performed by this constructor.  在线 api doc 戳这里[8] (可以点连接,进去搜索关键字 "No validation")

当初没有收到及时反馈,就没有来得及怼回去。

其实就算 "No validation of the inputs is performed by this constructor." 是合理的,里面也只有3个构造函数有这样的说明,按照这样的逻辑是不是说另外的构造函数有验证呢..... (示例中的默认的构造函数都没有说呀)

这里有java.net.URL 的源码[9],看兴趣的同学可以看看。

恩,以上就是结论了。

不过,反正我自己感觉目前 Java API 关于这里的设计不太合理,欢迎大家讨论。

我在SO提问的这个回答[10]比较有意思,哈哈。

The review is somewhat terse, but the reviewer's point is the URL constructor is behaving in accordance with its specification. Since the specification explicitly states that no validation is performed, this is not a bug in the code. This is indisputable.

What he didn't spell out is that fixing this inconsistency (by changing the URL class specification) would break lots of peoples' 20+ year old code Java code. That would be a really bad idea. It can't happen.

So ... this inconsistency is a "feature".

后记

觉得本号分享的文章有价值,记得添加星标哦。写文不易,不要白 piao,需要来点正反馈,安排个 “一键三连”(点赞、在看、分享)如何????? 这将是我持续输出优质文章的最强动力。

漫画:兄弟,今晚又得熬个通宵了!

从月薪三千到月薪三千

大牛是怎么练成的?又是怎么赚钱的?

漫画:量子计算为什么这么牛?

架构师劝退指南

Java每次遇难,总会有大神拯救

程序员的宿命

芯片战争70年,真正的王者即将现身!

干掉软件开发的最大怪兽:狼人!

宇宙第一IDE到底是谁?

HTTP Server :一个差生的逆袭

如何降低程序员的工资?

程序员,你得选准跑路的时间!

两年,我学会了所有的编程语言!

Javascript: 一个屌丝的逆袭

我是一个线程

TCP/IP之大明邮差

一个故事讲完Https

CPU 阿甘

附本文链接:

[1] URI、URL 和 URN: https://www.ibm.com/developerworks/cn/xml/x-urlni.html

[2]wiki URI: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

[3]JDK-8132508 : Bug JDK-8029354 reproduces with underscore in hostname: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8132508

[4]rfc952: https://tools.ietf.org/html/rfc952

[5]stackoverflow: https://stackoverflow.com/questions/44226003/conflicts-between-java-net-url-and-java-net-uri-when-dealing-with-hostname-conta

[6]JDK-8170265 : underscore is allowed in java.net.URL while not in java.net.URI: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8170265

[7]openjdk JDK-8170265: https://bugs.openjdk.java.net/browse/JDK-8170265

[8]在线 api doc 戳这里: https://docs.oracle.com/javase/8/docs/api/java/net/URL.html

[9]这里有java.net.URL 的源码: http://www.docjar.com/html/api/java/net/URL.java.html

[10]我在SO提问的这个回答: https://stackoverflow.com/questions/44226003/conflicts-between-java-net-url-and-java-net-uri-when-dealing-with-hostname-conta?answertab=active#tab-to

Android 9.0 延时开机动画解决首次开机黑屏和去掉android正在启动的提示框 在9.0的系统产品rom定制化开发中,在一些产品中会出现在首次开机的时候,由于在开机动画播放完以后会出现几秒短暂的黑屏情况,然后进入默认Launcher,这在产品体验上 也是感觉到有点差,所以会要求在去掉这个首次开机黑屏的效果,和在启动过程中的 android is starting这个提示框的这些效果优化,接下来就分析下相关功能, 然后实现这个功能的开发 阅读详情

相关推荐

ST7789驱动实战:从SPI时序到RGB565显示的完整配置解析

本文详细解析了ST7789液晶驱动芯片的SPI时序配置与RGB565显示实现,从数据手册解读到代码实战,涵盖SPI接口配置、关键寄存器设置及完整初始化流程。通过优化DMA传输和常见问题排查,帮助开发者高效驱动ST7789显示屏,适用于嵌入式显示项目开发。

weixin_29162439的博客 184

域名解析过程_在Java反序列化过程中通过java.net.URL触发域名解析请求

标题: 在Java反序列化过程中通过java.net.URL触发域名解析请求☆前言☆Serializable接口详解9)URLDNS9.1)HashMapURLDNS.java9.2)简化版调用关系9.3)ysoserial.payloads.URLDNS☆Fastjson10)Fastjson反序列化过程中触...

weixin_39760206的博客 537

在 CentOS7 下安装 Cadence IC验证平台 INCISIVE152

前言 本文所使用的软件 虚拟机软件:VMware Workstation 15 PRO 如何安装? 操作系统:CentOS-7, CentOS-7-x86_64-DVD-1810.iso 如何安装? 简介 INCISIVE Incisive是nc_verilog, nc_sim, nc_lauch,以及ABV,TBV的集合,用于仿真和验证。 InstallScape InstallSc...

沈醉不知的博客 2万+

java.net.URL

Class URL表示统一资源定位符,指向万维网上“资源”的指针。资源可以是文件或目录这样简单的东西,也可以是对更复杂的对象的引用,例如对数据库或搜索引擎的查询。有关URL类型及其格式的更多信息,请参阅: URL类型 通常,URL可以分为几个部分。请考虑以下示例: http://www.example.com/docs/resource1.html URL是一个URI,URI只标识资源,...

书香水墨 8432

ESP32-CAM与Thonny的完美搭配:从烧录到通信的完整流程

本文详细介绍了如何将ESP32-CAM与Thonny IDE完美结合,从固件烧录到通信测试的完整流程。通过硬件连接、MicroPython固件烧录、Thonny环境配置以及摄像头功能开发等步骤,帮助开发者快速搭建高效的物联网开发环境,实现图像采集与无线通信功能。

tomato的博客 1128

如何打开本地网络的防火墙端口(Windows版)解决ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。问题

ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。 最开始在遇到这个报错的时候十分不解,后来经过思考,有可能是服务器端口占用,或者并没有放行。因此搜查问题的关键是要先去排查问题。 在搜索栏输入控制面板 选择防火墙 选择开关 保证这些选项是开着的 选择高级设置 新建规则 创建协议端口 选择端口 允许连接 点击下一步 创建规则后点击下一步(后命名) 选择任意端口ALL即可 问题排查完毕!socket创建网络通信时,有读者

weixin_46900108的博客 9万+

bug提单 java_Oracle JDK7 bug 发现、分析与解决实战

本文首发于 vivo互联网技术 微信公众号链接:作者:vivo 官网商城开发团队众所周知,Oracle JDK 是 Java 语言的绝对权威,很多时候 JDK 与 Java 语言近似一个概念。但我们始终要保持实事求是的精神,敢于质疑。本文记录了一次线上troubleshoot 实战,包含问题分析、解决并提交bug 的核心过程。一、背景现象总之 就是某系统上线后 CLOSE_WAIT数量随着时间增...

weixin_35625397的博客 219

18、偏微分方程数值计算:粘性不可压缩流与电磁学的有限元方法

本文系统介绍了偏微分方程数值计算在粘性不可压缩流与电磁学中的应用,重点探讨了稳态与非稳态Navier-Stokes问题的混合有限元方法及求解技术,包括弱形式构建、半离散与时间离散格式、牛顿迭代法等。同时,详细阐述了电磁学中Maxwell方程的有限元与时域有限差分法(FDTD)求解方法,涵盖时间谐波与时域波方程、边界条件处理、稳定性分析与误差估计。结合MATLAB代码示例和实际案例,展示了速度场、压力、电场与磁场的数值模拟过程,并通过流程图与表格对比了两类问题的方法原理、应用场景与收敛性特性。最后展望了多物理

lemon的博客 90

太极限了,JDK的这个BUG都能被我踩到

之前遇到个文件监听变更的问题,刚好这周末有空研究了一番,整理出来分享给大家。从一次故障说起我们还是从故障说起,这样更加贴近实际,也能让大家更快速理解背景。有一个下发配置的服务,这个配置服务的实现有点特殊,服务端下发配置到各个服务的本地文件,当然中间经过了一个agent,如果没有agent也就无法写本地文件,然后由client端的程序监听这个配置文件,一旦文件有变更,就重新加载配置,画个架构图大概是这样:今天的重点是文件的变更该如何监听(watch),我们当时的实现非常简单:单独起个线程,定时去获取文件的最后

资料免费分享,点击名片 197

Clawdbot安装教程:从零开始到接入飞书

这几天,Clawdbot把整个科技圈都刷屏了。就是这个胖逼小龙虾🦞。不过现在改名叫Moltbot了。原因很简单:被Anthropic告了。Anthropic觉得Clawdbot这名字太像Claude Code的延伸产品,要求改名。真的,Anthropic你这家伙…更离谱的是,因为Clawdbot太火,Mac Mini都被抢断货了。无数人为了用它,疯狂买Mac Mini。我刚打开美团外卖,发现居然没货了???

Maynor的博客 2180

康复训练监测系统:基于YOLOv8的患者动作规范识别

本文系统介绍了基于YOLOv8的康复训练动作规范识别系统,从理论背景、数据准备、模型训练、推理应用到UI界面,提供了完整技术链条及代码示范。希望对康复领域的智能监测应用提供参考和借鉴。

YOLO 453

No Java JDK is detected on the host.(hadoop )

CHM中出现No Java JDK is detected on the host.这个错误时,首先通过命令行的模式,查看一下是不是有默认的jdk。 查看后,发现能正常显示jdk的版本,但是出现了上面的报警,然后我们去查一下上面报警的意思,原来说是有个共享文件满了,无法正常运行。 使用df -h 命令查看 发现这个文件真的满了,然后我们百度一下,给这个磁盘扩容或者删除部分内容即可。 ...

carey2017的博客 4206

MATLAB点云处理(八):为点云添加高斯噪声

本文对如何借助MATLAB,为点云添加高斯噪声做出了说明,并给出实现代码。

孙悟空 2844

给 JDK 报了一个 P4 的 Bug,结果居然……

作者 | 码农唐磊来源 |程序猿石头(id:tangleithu)图 by:石头@北京-望京背景分享一下之前踩的一个坑,背景是这样的:我们的项目依赖于一个外部服务,该外部服务提供 RE...

优快云资讯 2706

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

给JDK报了一个P4的Bug,结果居然……

点击上方好好学java,选择星标公众号重磅资讯、干货,第一时间送达 今日推荐:腾讯推出高性能 RPC 开发框架个人原创100W+访问量博客:点击前往,查看更多 作者:程序猿石...

好好学java 381

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

jdk说明文档_给JDK报了一个P4的Bug,结果居然……

(给ImportNew加星标,提高Java技能)作者:程序猿石头/码农唐磊(本文来自作者投稿)背景分享一下之前踩的一个坑,背景是这样的:我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是很常见的一个场景。本地和测试环境测试都没有问题,一切就绪。上了生产后,程序调用接口就总是网络不通。需要说明的是本地、测试环境、生产环境通过不同的域名访问该外部服务。生产程序调用不...

weixin_39564527的博客 75

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

winform bug 调用close()方法窗体不关闭_给 JDK 报了一个 P4 的 Bug,结果居然……

关注“脚本之家”,与百万开发者在一起图 by:石头@北京-望京关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。欢迎关注,交流和指导!背景分享一下之前踩的一个坑,背景是这样的:我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是很常见的一个场景。本地和测试环境测试都没有问题,一切就绪上了生产后,程序调...

weixin_39969448的博客 127

winform bug 调用close()方法窗体不关闭_给 JDK 报了一个 P4 的 Bug,结果居然……

背景我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是很常见的一个场景。本地和测试环境测试都没有问题,一切就绪上了生产后,程序调用接口就总是网络不通。需要说明的是本地、测试环境、生产环境通过不同的域名访问该外部服务。生产程序调用不通,神奇的是在生产环境通过 curl 等命令却能够正常调用对方接口。这 就神奇了,唯一不同的就是发起 HTTP 请求的客户端了,估计就是 htt...

weixin_39617044的博客 109

winform bug 调用close()方法窗体不关闭_给 JDK 报了一个 P4 的 Bug,结果…

分享一下之前踩的一个坑,背景是这样的:我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是很常见的一个场景。本地和测试环境测试都没有问题,一切就绪上了生产后,程序调用接口就总是网络不通。需要说明的是本地、测试环境、生产环境通过不同的域名访问该外部服务。生产程序调用不通,神奇的是在生产环境通过curl等命令却能够正常调用对方接口。What??这 TM 就神奇了,...

weixin_39555415的博客 157

一个 P4 的 Bug,就难倒了 JDK 吗 ?

作者 |码农唐磊来源 |程序猿石头(ID:tangleithu)背景分享一下之前踩的一个坑,背景是这样的:我们的项目依赖于一个外部服务,该外部服务提供 REST 接口供我方调用,这是...

程序人生的博客 320

给 JDK 官方提了一个 Bug,结果...

图 by:石头@北京-望京关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。背景分享一下之前踩的一个坑,背景是这样的:我们的...

磊哥聊Java 638

有幸遇到jdk bug的一些总结和反思

有幸遇到jdk bug的一些总结和反思 1 遇到一个jdk bug-过程描述 最近工作中出现一个问题,抓包发现所有的tcp报文,都出现重传现象,怀疑是cpu出现异常,因此特地查看top命令,发现果真是cpu100%. 通过jstack定位发现是一个线程池出现了问题。具体jdk定位工具实用见博客的相关定位思路! jdk问题定位工具箱-线程挂死、堆栈满问题定位 检查出现位置的线程,我们没有发现特别的...

936
上一篇: 漫画:如何盗刷别人的支付宝?
下一篇: 漫画:兄弟,下班别走啊,一起填坑!
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值