JDK-8263693 : JEP 418: Internet-Address Resolution SPI
  • Type: JEP
  • Component: core-libs
  • Sub-Component: java.net
  • Priority: P3
  • Status: Candidate
  • Resolution: Unresolved
  • Submitted: 2021-03-16
  • Updated: 2021-09-20
Related Reports
Relates :  
Relates :  
Description
Summary
-------

Define a service-provider interface (SPI) for host name and address resolution, so that [`java.net.InetAddress`] can make use of resolvers other than the platform's built-in resolver.

Non-Goals
---------

- It is not a goal to develop an alternative resolver to include in the JDK. The JDK's built-in resolver will continue to be used by default.

- It is not a goal for the SPI to support resolution operations beyond those required by the `InetAddress` API.

- It is not a goal to define non-blocking or asynchronous resolution APIs.

Motivation
----------

The [`java.net.InetAddress`] API resolves host names to Internet Protocol (IP) addresses, and vice versa. The API currently uses the operating system's native resolver, which is typically configured to use a combination of a local `hosts` file and the Domain Name System (DNS).

Motivations for defining a service-provider interface for name and address resolution include:

- [_Project Loom_][loom] — A resolution operation with the `InetAddress` API currently blocks in an operating-system call. This is a problem for Loom's user-mode virtual threads, since it prevents underlying platform threads from servicing other virtual threads while waiting for a resolution operation to complete. An alternative resolver could implement the DNS client protocol directly, without blocking.

- _Emerging network protocols_ — A resolver SPI would enable the seamless integration of new resolution protocols such as DNS over QUIC, TLS, or HTTPS.

- _Customization_ — A resolver SPI would enable frameworks and applications to have finer control over resolution results, and would allow existing libraries to be retrofitted with a custom resolver.

- _Testing_ — Prototyping and testing activities often require control of host name and address resolution results, for example when mocking components that use the `InetAddress` API.


Description
-----------

The `InetAddress` API defines multiple methods for lookup operations:

- [`InetAddress::getAllByName`] performs a _forward_ lookup, mapping a host name to a set of IP addresses.

- [`InetAddress::getByName`] also performs a forward lookup, mapping a host name to the first address in its set of addresses.

- [`InetAddress::getCanonicalHostName`] performs a _reverse_ lookup, mapping an IP address to a fully qualified domain name. For example:

  ```
  var addressBytes = new byte[] { (byte) 192, 0, 43, 7};
  var resolvedHostName = InetAddress.getByAddress(addressBytes)
                                    .getCanonicalHostName();
  ```

- [`InetAddress::getHostName`] also performs a reverse lookup, if needed.

By default, `InetAddress` uses the operating system's native resolver to perform lookups. The result of that lookup, whether positive or negative, may be cached in order to avoid further lookups of the same host.

### Service-provider interface

The `InetAddress` API will use a [service loader][sl] to locate a resolver provider. If no provider is found, the built-in implementation will be used as before.

The new classes in the `java.net.spi` package are:

- `InetAddressResolverProvider` — an abstract class defining the service to be located by [`java.util.ServiceLoader`][sl]. An `InetAddressResolverProvider` is, essentially, a factory for resolvers. The instantiated resolver will be set as the system-wide resolver, and
`InetAddress` will delegate all lookup requests to that resolver.

- `InetAddressResolver` — an interface that defines methods for the fundamental forward and reverse lookup operations. An instance of this interface is obtained from an instance of `InetAddressResolverProvider`.

- `InetAddressResolver.LookupPolicy` — a class whose instances describe the characteristics of a resolution request, including the requested address type and the order in which addresses should be returned.

- `InetAddressResolverProvider.Configuration` — an interface describing the platform's built-in configuration for resolution operations. It provides access to the local host name and the built-in resolver. It is used by custom resolver providers to bootstrap resolver construction or to implement partial delegation of resolution requests to the operating system's native resolver.

Alternatives
------------

Without an SPI such as the one proposed here, applications will have to continue to use the workarounds available today.

 - An application can use the Java Naming and Directory Interface (JNDI) and its DNS provider to look up network names and addresses. This approach can be useful for applications that require fine control of DNS lookups, but it is decoupled from `InetAddress` and thus using it with the platform's networking API requires additional effort.

 - An application can use the operating system's resolver libraries directly via the Java Native Interface (JNI) or the [foreign function API][jep412] from [Project Panama]. As with JNDI, however, this approach is decoupled from `InetAddress` and thus more awkward to use.

 - An application can use the non-standard, JDK-specific system property `jdk.net.hosts.file` to  configure `InetAddress` to use a specific file, rather than the operating system's native resolver, to map host names to IP addresses. This feature is useful for testing but it is not a general purpose solution since the complete list of host names is not always known in advance.


Testing
-------

We will develop new tests for the resolver SPI.

We will develop proof-of-concept resolver providers to demonstrate and verify that the SPI can be used to develop and deploy alternative implementations that are used in preference to the JDK's built-in implementation. We will make at least one of these providers available to seed development of more complete implementations.


[`java.net.InetAddress`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html
[loom]: https://openjdk.java.net/projects/loom/
[`InetAddress::getAllByName`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html#getAllByName(java.lang.String)
[`InetAddress::getByName`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html#getByName(java.lang.String)
[`InetAddress::getCanonicalHostName`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html#getCanonicalHostName()
[`InetAddress::getHostName`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html#getHostName()
[`InetAddress::getByAddress`]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/InetAddress.html#getByAddress(byte%5B%5D)
[sl]: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/ServiceLoader.html
[Project Panama]: https://openjdk.java.net/projects/panama/
[jep412]: https://openjdk.java.net/jeps/412

Comments
[~mr] I'm done with the changes for this JEP: I've only added InetAddress API's bullet point for 'InetAddress::getHostName'. If it looks good to you then I believe it can be promoted to Candidate.
03-09-2021

Thank you for the corrections Mark. The changes look good to me. That is correct that "InetAddress::getHostName" can also do a reverse lookup. I've added additional bullet point to the InetAddress API section to clarify that. I also agree that 'jdk.net.hosts.file' needs to be documented. I've logged a bug to track its addition: https://bugs.openjdk.java.net/browse/JDK-8273289
02-09-2021

WRT jdk.net.hosts.file: good catch Mark! I agree that this property needs to be documented. The only documentation we currently have for this property is in the JDK 9 release notes (see https://bugs.openjdk.java.net/browse/JDK-8176361)
02-09-2021

I’ve edited this JEP to tighten the wording, correct some terminology, fix some links and add others, and shorten the title. Please look it over, make any additional necessary changes, and then I’ll promote it to Candidate. One question: InetAddress::getHostName will also do a reverse lookup, won’t it? Is that worth mentioning in the description of the InetAddress API? (Don’t worry about the random “<code” noise in the JBS display of this JEP; that’s due to bugs in JBS’s Markdown renderer. The actual JEP document (https://openjdk.java.net/jeps/8263693) looks fine. (Side note: Shouldn’t the system property “jdk.net.hosts.file” be documented somewhere, either in the InetAddress API Javadoc or on the networking properties page? (https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/net/doc-files/net-properties.html))
01-09-2021