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:
Migrating from JUnit 4 to JUnit 5
Giới thiệu về Stream API trong Java 8
Java Program to Implement a Binary Search Tree using Linked Lists
Using Optional with Jackson
Exploring the New Spring Cloud Gateway
REST Web service: Basic Authentication trong Jersey 2.x
Java Program to Implement Weight Balanced Tree
Guide to Java OutputStream
String Joiner trong Java 8
Hướng dẫn Java Design Pattern – Object Pool
The Spring @Controller and @RestController Annotations
Guide to Escaping Characters in Java RegExps
Java Program to Perform Matrix Multiplication
Getting Started with Stream Processing with Spring Cloud Data Flow
Registration – Password Strength and Rules
Java Program to Implement Rolling Hash
Setting a Request Timeout for a Spring REST API
Assertions in JUnit 4 and JUnit 5
CharSequence vs. String in Java
Jackson – Unmarshall to Collection/Array
String Processing with Apache Commons Lang 3
Spring WebClient Filters
Creating Docker Images with Spring Boot
New Features in Java 13
Hướng dẫn Java Design Pattern – Dependency Injection
OAuth2 Remember Me with Refresh Token
Getting Started with Custom Deserialization in Jackson
Java Program to Implement Fermat Primality Test Algorithm
Java Program to Implement ArrayBlockingQueue API
LIKE Queries in Spring JPA Repositories
Java Program to Implement Splay Tree
Java Program to Find the Longest Subsequence Common to All Sequences in a Set of Sequences