AddressSelection
Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address

Severity
WARNING

The problem

Avoid APIs that convert a hostname to a single IP address:

Depending on the value of the -Djava.net.preferIPv6Addresses=true system property, those APIs will return an IPv4 or IPv6 address. If a client only has IPv4 connectivity, it will fail to connect with -Djava.net.preferIPv6Addresses=true. If a client only has IPv6 connectivity, it will fail to connect with -Djava.net.preferIPv6Addresses=false.

The preferred alternative is for clients to consider all addresses returned by java.net.InetAddress.html#getAllByName(String), and try to connect to each one until a successful connection is made.

TIP: To resolve a loopback address, prefer InetAddress.getLoopbackAddress() over hard-coding an IPv4 or IPv6 loopback address with InetAddress.getByName("127.0.0.1") or InetAddress.getByName("::1").

This is, prefer this:

  Socket doConnect(String hostname, int port) throws IOException {
    IOException exception = null;
    for (InetAddress address : InetAddress.getAllByName(hostname)) {
      try {
        return new Socket(address, port);
      } catch (IOException e) {
        if (exception == null) {
          exception = e;
        } else {
          exception.addSuppressed(e);
        }
      }
    }
    throw exception;
  }
  Socket doConnect(String hostname, int port) throws IOException {
    IOException exception = null;
    for (InetAddress address : InetAddress.getAllByName(hostname)) {
      try {
        Socket s = new Socket();
        s.connect(new InetSocketAddress(address, port));
        return s;
      } catch (IOException e) {
        if (exception == null) {
          exception = e;
        } else {
          exception.addSuppressed(e);
        }
      }
    }
    throw exception;
  }

instead of this:

  Socket doConnect(String hostname, int port) throws IOException {
    return new Socket(hostname, port);
  }
  void doConnect(String hostname, int port) throws IOException {
    Socket s = new Socket();
    s.connect(new InetSocketAddress(hostname, port));
  }
  void doConnect(String hostname, int port) throws IOException {
    Socket s = new Socket();
    s.connect(new InetSocketAddress(InetAddress.getByName(hostname), port));
  }

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("AddressSelection") to the enclosing element.