JDK-8154834 : DNS name lookup cache policy not respected when calling InetAddress.getHostName() from IP address
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2016-04-20
  • Updated: 2022-12-07
  • Resolved: 2022-09-09
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux  3.10.0-229.11.1.el7.x86_64 #1 SMP Thu Aug 6 01:06:18 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
For java.net.InetAddress object initialized with IP address, the method call  to InetAddress.getHostName() will invoke InetAddress.getHostFromNameService(), which directly calls name service with following line, without checking cache 

    host = nameService.getHostByAddr(addr.getAddress());

This implementation causes serious performance issue when the DNS server is slow, or primary DNS server is down.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Simulate primary DNS server down situation, by editing /etc/resolv.conf, and change the first nameserver's ip address to an non-existing address; this would cause OS level  name service call response slowdown due to primary DNS server call would always timeout.

2. Run the test Java class, it will print out very slow response time, about 5 seconds, which is the default DNS lookup time out value:

5048 ms,   i = 1
5047 ms,   i = 2
5045 ms,   i = 3
5043 ms,   i = 4
5054 ms,   i = 5 

3. profiling with VisualVM shows the delay were caused by java.net.InetAddress.getHostFromNameService(), with stacktrace below:

        at java.net.Inet4AddressImpl.getHostByAddr(Native Method)
        at java.net.InetAddress$1.getHostByAddr(InetAddress.java:905)
        at java.net.InetAddress.getHostFromNameService(InetAddress.java:590)
        at java.net.InetAddress.getHostName(InetAddress.java:532)




EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When name lookup caching is enabled, InetAddress.getHostFromNameService() should respect the caching policy and only the first call need to invoke name service, subsequent calls should check the cache, which would achieve the designed benefit of caching. 


ACTUAL -
Due to above method invoking name service every time, response become consistently slow, and cannot achieve the designed benefit of caching.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.net.InetAddress;
import java.net.Inet4Address;

public class InetTest 
{
	
	public String getHost( )
	throws Exception
	{
		//ip of oracle.com
		InetAddress addr = Inet4Address.getByName("137.254.120.50");
		
		String name = addr.getHostName();
		//System.out.println(addr.getHostAddress()+"="+name);
		return name;
	}
	
	public static void main(String[] args) throws Exception
	{
	    java.security.Security.setProperty("networkaddress.cache.ttl" , "180");
	    java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "180");
	    System.out.println(
	    	"networkaddress.cache.ttl: " + java.security.Security.getProperty("networkaddress.cache.ttl") + "\n" +
	        "networkaddress.cache.negative.ttl: " + java.security.Security.getProperty("networkaddress.cache.negative.ttl")

	    );
		InetTest test = new InetTest();
		//long i=0;
		for(long i=0;i<100l;i++){
			long start = System.currentTimeMillis();
			String name = test.getHost();
			long dur = System.currentTimeMillis()-start;
			if(i==0)
				System.out.println("Hostname = "+name);
			System.out.println(dur+" ms,   i = "+i);
			
		}
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
May try to enable some OS level caching tools; but they are complex and  not reliable enough for production env.


Comments
Implementing a reverse lookup cache on InetAddress level looks like a complicated task. The problem looks like an O/S configuration issue, i.e. non-responsive DNS server in '/etc/resolv.conf'. Apps that needs to add reverse lookup caching or/and configurable timeouts can provide their own implementation of InetAddressResolver (see JEP-418 - JDK-8263693) which will wrap built-in resolver with additional functionality dictated by an application logic added. The stack behaves the same on latest Java 20 build with modified /etc/resolv.conf with non-existent DNS server set as first nameserver: networkaddress.cache.ttl: 180 networkaddress.cache.negative.ttl: 180 Hostname = vp-ocoma-cms-adc.oracle.com 10206 ms, i = 0 5006 ms, i = 1 5004 ms, i = 2 5004 ms, i = 3 5004 ms, i = 4 5004 ms, i = 5 5003 ms, i = 6 5004 ms, i = 7 5004 ms, i = 8 5004 ms, i = 9 5004 ms, i = 10 Closing as "Won't Fix"
09-09-2022

Attached test case executed on: JDK 8u77 - Fail JDK 9 - Fail Output of test case: networkaddress.cache.ttl: 180 networkaddress.cache.negative.ttl: 180 Hostname = 137.254.120.50 4506 ms, i = 0 4640 ms, i = 1 4501 ms, i = 2 4503 ms, i = 3 5004 ms, i = 4 4500 ms, i = 5 4500 ms, i = 6
21-04-2016