Examine the internal DNS cache

Once an application has performed network access (i.e. urlconnection, parsing of xml document with external references, etc), the DNS settings get cached internally so any subsequent operation will use the previously read settings to achieve a better performance. There is one cache for successful lookups and one for unsuccessful lookups. To get the contents of 2 caches, we are using introspection because these are private elements of the InetAdress object.

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class DNSCache {
   public static void main(String[] args) throws Exception {

      // put some values in the internal DNS cache

      // good DNS name
      InetAddress.getByName("stackoverflow.com");
      InetAddress.getByName("www.google.com");
      InetAddress.getByName("www.rgagnon.com");
      try {
         // bad DNS name
         InetAddress.getByName("bad.rgagnon.com");
      }
      catch (UnknownHostException e) {
         // do nothing
      }

      // dump the good DNS entries
      String addressCache = "addressCache";
      System.out.println("---------" + addressCache + "---------");
      printDNSCache(addressCache);

      // dump the bad DNS entries
      String negativeCache = "negativeCache";
      System.out.println("---------" + negativeCache + "---------");
      printDNSCache(negativeCache);
   }

   /**
    * By introspection, dump the InetAddress internal DNS cache
    *
    * @param cacheName  can be addressCache or negativeCache
    * @throws Exception
    */

   @SuppressWarnings({ "rawtypes", "unchecked" })
   private static void printDNSCache(String cacheName) throws Exception {
      Class<InetAddress> iaclass = InetAddress.class;
      Field acf = iaclass.getDeclaredField(cacheName);
      acf.setAccessible(true);
      Object addressCache = acf.get(null);
      Class cacheClass = addressCache.getClass();
      Field cf = cacheClass.getDeclaredField("cache");
      cf.setAccessible(true);
      Map<String, Object> cache = (Map<String, Object>) cf.get(addressCache);
      for (Map.Entry<String, Object> hi : cache.entrySet()) {
         Object cacheEntry = hi.getValue();
         Class cacheEntryClass = cacheEntry.getClass();
         Field expf = cacheEntryClass.getDeclaredField("expiration");
         expf.setAccessible(true);
         long expires = (Long) expf.get(cacheEntry);

         Field af = cacheEntryClass.getDeclaredField("addresses"); // JDK 1.7, older version maybe "address"
         af.setAccessible(true);
         InetAddress[] addresses = (InetAddress[]) af.get(cacheEntry);
         List<String> ads = new ArrayList<String>(addresses.length);

         for (InetAddress address : addresses) {
            ads.add(address.getHostAddress());
         }

         System.out.println(hi.getKey() + " "+new Date(expires) +" " +ads);
      }
   }
}

Output:

---------addressCache---------
0.0.0.0 Wed Jul 22 15:41:35 EDT 2015 [0.0.0.0]
stackoverflow.com Wed Jul 22 15:41:35 EDT 2015 [198.252.206.16]
www.google.com Wed Jul 22 15:41:35 EDT 2015 [173.194.123.49, 173.194.123.50, 173.194.123.48, 173.194.123.52, 173.194.123.51]
www.rgagnon.com Wed Jul 22 15:41:35 EDT 2015 [72.55.186.40]
---------negativeCache---------
bad.rgagnon.com Wed Jul 22 15:41:15 EDT 2015 [0.0.0.0]

To disable the caching:

public class DNSCache {
   public static void main(String[] args) throws Exception {
     java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); // no cache
     java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0"); // no cache
     ...

and the caches are empty:

---------addressCache---------
---------negativeCache---------

To cache forever:

public class DNSCache {
   public static void main(String[] args) throws Exception {
     java.security.Security.setProperty("networkaddress.cache.ttl" , "-1"); // cache forever
     java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "-1"); // cache forever
     ...

and the result is:

---------addressCache---------
0.0.0.0 Wed Dec 31 18:59:59 EST 1969 [0.0.0.0]
stackoverflow.com Wed Dec 31 18:59:59 EST 1969 [198.252.206.16]
www.google.com Wed Dec 31 18:59:59 EST 1969 [173.194.123.116, 173.194.123.114, 173.194.123.113, 173.194.123.112, 173.194.123.115]
www.rgagnon.com Wed Dec 31 18:59:59 EST 1969 [72.55.186.40]
---------negativeCache---------
bad.rgagnon.com Wed Dec 31 18:59:59 EST 1969 [0.0.0.0]

Done! Happy Coding!

Related posts:

Function trong Java 8
Hướng dẫn Java Design Pattern – Bridge
Spring Boot - Hystrix
Spring Security OAuth2 – Simple Token Revocation
Spring Boot - OAuth2 with JWT
Java Program to Find the Median of two Sorted Arrays using Binary Search Approach
Request Method Not Supported (405) in Spring
Convert Time to Milliseconds in Java
Tips for dealing with HTTP-related problems
Java Program to Implement Solovay Strassen Primality Test Algorithm
Java Program to Find the Peak Element of an Array O(n) time (Naive Method)
Java Program to Implement Find all Back Edges in a Graph
Creating a Custom Starter with Spring Boot
Java Program to Implement Aho-Corasick Algorithm for String Matching
Spring WebClient vs. RestTemplate
JUnit5 Programmatic Extension Registration with @RegisterExtension
Concrete Class in Java
Using Custom Banners in Spring Boot
Spring Security Custom AuthenticationFailureHandler
Java Program to Check Whether a Given Point is in a Given Polygon
Spring Data – CrudRepository save() Method
XML Serialization and Deserialization with Jackson
How to Get the Last Element of a Stream in Java?
Java Program to Emulate N Dice Roller
Java Program to Repeatedly Search the Same Text (such as Bible by building a Data Structure)
Java Program to Perform Searching Based on Locality of Reference
Java Program to Implement Sorted Circular Doubly Linked List
Java Program to Implement TreeSet API
Initialize a HashMap in Java
Java Program to Implement Naor-Reingold Pseudo Random Function
Converting Java Date to OffsetDateTime
An Introduction to ThreadLocal in Java