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:

Using a Spring Cloud App Starter
Java Program to add two large numbers using Linked List
Using Spring ResponseEntity to Manipulate the HTTP Response
Intro to the Jackson ObjectMapper
Filtering a Stream of Optionals in Java
Java Program to Implement Best-First Search
Summing Numbers with Java Streams
Working with Kotlin and JPA
Tránh lỗi NullPointerException trong Java như thế nào?
Spring 5 and Servlet 4 – The PushBuilder
Working with Tree Model Nodes in Jackson
Java Program to Solve the 0-1 Knapsack Problem
Guide to System.gc()
Giới thiệu Swagger – Công cụ document cho RESTfull APIs
Checking for Empty or Blank Strings in Java
Spring Boot - Servlet Filter
Logout in an OAuth Secured Application
Mệnh đề Switch-case trong java
Changing Annotation Parameters At Runtime
SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS
Spring Security – Reset Your Password
Hướng dẫn Java Design Pattern – Strategy
Implementing a Runnable vs Extending a Thread
Java Program to Find k Numbers Closest to Median of S, Where S is a Set of n Numbers
Abstract class và Interface trong Java
Java Program to Check whether Undirected Graph is Connected using BFS
Loại bỏ các phần tử trùng trong một ArrayList như thế nào?
A Guide to Java HashMap
Hướng dẫn tạo và sử dụng ThreadPool trong Java
Registration – Password Strength and Rules
Java Program to Check Whether Topological Sorting can be Performed in a Graph
Giới thiệu Google Guice – Dependency injection (DI) framework