我注意到我的一个 Spring Boot 应用程序在嵌入式 Tomcat 关闭过程中通过
URISyntaxException
出现了一种特殊的抑制 TomcatWebServer#stop()
- 经过调试,发现源代码在这里:
(这发生在我的 Eclipse Temurin 17.0.8.1 上,但我尝试了其他 Java 版本,看起来基本相同)
基本上,无论我多么努力地盯着它看,对于 IPv6(我的用例)来说,这段代码看起来都已经损坏了。
epoint.getHostString()
给出有效的 IPv6,无大括号(例如 fd00:baba:babe:0:0:0:0:862
)epoint
并添加大括号,[fd00:baba:babe:0:0:0:0:862]
ParseUtil.encodePath(host)
将 host
编码为 %5bfd00:baba:babe:0:0:0:0:862%5d
- 这是有问题的,因为稍后无法通过 URI 解析来区分主机名和端口,但本身不应导致异常socket://%5fd00:baba:babe:0:0:0:0:862%5d:55507
- 问题更大,因为现在它对于人眼来说甚至对于 new URI
输入解析器来说看起来都更加令人烦恼,new URI
c-tor 构造了一个 URI,其中编码的主机名和端口集中在一起为 authority
、host == null
和 port == -1
为了在基于 IPv6 的主机上正常工作,
new URI
需要一个 非编码 IPv6 地址 带有必需的文字大括号,即 [fd00:baba:babe:0:0:0:0:862]
,
简单复制案例:
URI uri = new URI("socket://[fd00:baba:babe:0:0:0:0:862]:55507");
System.out.println(uri.getHost()); // [fd00:a89f:8b41:0:0:0:0:862] - OK
uri = new URI("socket://%5fd00:baba:babe:0:0:0:0:862%5d:55507");
System.out.println(uri.getHost()); // null - port is -1, everything got clumped in authority
uri = new URI("socket://fd00:baba:babe:0:0:0:0:862:55507");
System.out.println(uri.getHost()); // null - port is -1, everything got clumped in authority
我认为拥有
host == null
稍后会导致 SocksSocketImpl 崩溃,但是,令人惊讶的是,在唯一真正使用 uri
的地方,即对 DefaultProxySelector#select(URI uri)
的调用,我发现了一个不相关的解决方法...所描述的明确表示不适用于本例,但允许代码不会失败! https://github.com/openjdk/jdk/blob/jdk-10%2B24/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java#L168(即,此代码 在正常情况下实际上会崩溃,如果不是因为几十年前的黑客解决方法 对于完全不相关的情况 - 国际域名和带下划线的域名)。
我是否遗漏了一些明显的东西,或者它是 stdlib 本身的堆积错误(因此应该向上游报告)?