Skip to content
微信扫码关注公众号

JEP 418: Internet-Address Resolution SPI | Internet 地址解析 SPI

摘要

为主机名和地址解析定义一个服务提供者接口(SPI),以便 java.net.InetAddress 能够利用除平台内置解析器之外的其他解析器。

非目标

  • 不是要在 JDK 中包含一个替代的解析器。JDK 的内置解析器将继续作为默认解析器使用。

  • SPI 的目标不是支持 InetAddress API 所需之外的解析操作。

  • 不是定义非阻塞或异步解析 API。

动机

java.net.InetAddress API 将主机名解析为互联网协议(IP)地址,反之亦然。当前,该 API 使用操作系统的本机解析器,该解析器通常配置为使用本地 hosts 文件和域名系统(DNS)的组合。

为名称和地址解析定义服务提供者接口的动机包括:

  • Project Loom — 使用 InetAddress API 的解析操作目前在操作系统调用中阻塞。这对于 Loom 的用户模式虚拟线程来说是一个问题,因为它会阻止底层平台线程在等待解析操作完成时为其他虚拟线程提供服务。替代解析器可以直接实现 DNS 客户端协议,而不会造成阻塞。

  • 新兴网络协议 — 解析器 SPI 将支持无缝集成 DNS over QUIC、TLS 或 HTTPS 等新的解析协议。

  • 自定义 — 解析器 SPI 将使框架和应用程序能够更精细地控制解析结果,并允许使用自定义解析器对现有库进行改造。

  • 测试 — 原型设计和测试活动通常需要控制主机名和地址解析结果,例如,在模拟使用 InetAddress API 的组件时。

描述

InetAddress API 定义了多个用于查找操作的方法:

默认情况下,InetAddress 使用操作系统的本机解析器来执行查找。无论是正向还是反向的查找结果,都可能会被缓存,以避免对同一主机的重复查找。

服务提供者接口

InetAddress API 将使用 服务加载器 来定位解析器提供者。如果没有找到提供者,将像之前一样使用内置实现。

java.net.spi 包中的新类是:

  • InetAddressResolverProvider — 一个抽象类,定义了将由 java.util.ServiceLoader 定位的服务。InetAddressResolverProvider 本质上是一个解析器的工厂。实例化后的解析器将被设置为系统范围的解析器,InetAddress 将把所有查找请求委托给该解析器。

  • InetAddressResolver — 一个定义了基本正向和反向查找操作方法的接口。该接口的实例是从 InetAddressResolverProvider 的实例中获取的。

  • InetAddressResolver.LookupPolicy — 一个其实例描述解析请求特性的类,包括请求的地址类型和地址应返回的顺序。

  • InetAddressResolverProvider.Configuration — 一个描述平台内置解析操作配置的接口。它提供了对本地主机名和内置解析器的访问。自定义解析器提供者使用它来引导解析器构造或实现将解析请求部分委托给操作系统本机解析器的功能。

替代方案

如果没有像这里提出的这样的 SPI,应用程序将不得不继续使用当前可用的变通方法。

  • 应用程序可以使用 Java 命名和目录接口(JNDI)及其 DNS 提供程序来查找网络名称和地址。这种方法对于需要精细控制 DNS 查找的应用程序很有用,但它与 InetAddress 是解耦的,因此与平台的网络 API 一起使用需要额外的努力。

  • 应用程序可以通过 Java 本地接口(JNI)或来自 Project Panama外部函数 API 直接使用操作系统的解析器库。然而,与 JNDI 一样,这种方法与 InetAddress 是解耦的,因此使用起来更加笨拙。

  • 应用程序可以使用非标准的、JDK 特定的系统属性 jdk.net.hosts.file 来配置 InetAddress 以使用特定文件(而不是操作系统的本机解析器)来将主机名映射到 IP 地址。此功能对于测试很有用,但它不是一个通用解决方案,因为完整的主机名列表并不总是提前知道。

测试

我们将为解析器 SPI 开发新的测试。

我们将开发概念验证解析器提供者,以演示和验证 SPI 是否可用于开发和部署优先于 JDK 内置实现的替代实现。我们将至少提供一个这样的提供者,以促进更完整实现的开发。