Share this page 

Examine the internal DNS cache Tag(s): Networking


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]

In this HowTo, we saw that is possible to change the default behaviour of DNS caching.

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]