ADDITIONAL SYSTEM INFORMATION :
Any OS (see sources above). Tested with all major hotspot and OpenJ9 versions from Java 8 onwards.
A DESCRIPTION OF THE PROBLEM :
When opening a socket, for example for an https or ldaps connection, the dns is being queried before the target port known. From the DNS, only the first result is ever used when querying an IP for a hostname.
This is due two code paths:
1. in InetAddress.java (ref: https://github.com/openjdk/jdk/blob/270674ce1b1b8d44bbe92949c3f7db7b7c767cac/src/java.base/share/classes/java/net/InetAddress.java#L1236-L1239)
Java will always return getAllByName(host)[0]
2. getAddress() being called in https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/net/Socket.java#L634-L637
and connect methods in AbstractPlainSocketImpl.java.
This is also true for the more recent implementations of AbstractPlainSocketImpl.java in Java 14+.
All other IPs are discarded.
Other languages, like python and .NET-languages, wait until the the target port is known. They will then iterate through all the IPs, trying to open the socket. If the destination is not reachable, the next IP:Port will be tried.
This way, outages and regional unavailability can be mitigated.
As java does not implement this behaviour, it is the only platform which does not provide a similar failsafe dns resolution.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Connect to a host (e.g. via ldaps, https) where the dns resolution will provide multiple answers. Make sure the first target IP of the DNS response is not reachable.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Java will pick the second (or any other) IP from the dns result after discovering the first ip cannot be used to open a socket.
ACTUAL -
Java takes the first dns result without checking, resulting in an exception (unreachable).
No non-java applications are affected, as only Java implements this behaviour.
As only java implements this behaviour, I consider this a bug.
CUSTOMER SUBMITTED WORKAROUND :
None possible. It is not possible to write an agent which modifies any classes in java.net, as they are protected.
FREQUENCY : always