Is there a way to view/dump DNS cached used by java.net api?
The above answer does not work with Java 11. In Java 11, both positive and negative cache entries can be retrieved using the 'cache' instance variable. Here are new adaptations:
import java.net.InetAddress;
import java.net.UnknownHostException;
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;
import java.util.concurrent.ConcurrentHashMap;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class DnsCacheFetcher {
static long startTimeinNano = System.nanoTime();
public static void main(String[] args) throws Exception {
System.out.println("SecurityManager: " + System.getSecurityManager());
InetAddress.getByName("stackoverflow.com");
InetAddress.getByName("www.google.com");
InetAddress.getByName("www.yahoo.com");
InetAddress.getByName("www.ankit.com");
try {
InetAddress.getByName("nowhere.example.com");
} catch (UnknownHostException e) {
System.out.println("Unknown host: " + e);
}
String addressCache = "cache";
System.out.println(">>>>" + addressCache);
printDNSCache(addressCache);
/*
* String negativeCache = "negativeCache"; System.out.println(">>>>" +
* negativeCache); printDNSCache(negativeCache);
*/
}
private static void printDNSCache(String cacheName) throws Exception {
Class klass = InetAddress.class;
Field[] fields = klass.getDeclaredFields();
/*
* for (Field field : fields) { System.out.println(field.getName()); }
*/
Field acf = klass.getDeclaredField(cacheName);
acf.setAccessible(true);
Object addressCache = acf.get(null);
Class cacheKlass = addressCache.getClass();
Map cache = (Map) acf.get(addressCache);
for (Map.Entry hi : cache.entrySet()) {
/* System.out.println("Fetching cache for: " + hi.getKey()); */
Object cacheEntry = hi.getValue();
Class cacheEntryKlass = cacheEntry.getClass();
Field expf = cacheEntryKlass.getDeclaredField("expiryTime");
expf.setAccessible(true);
long expires = (Long) expf.get(cacheEntry);
Field af = cacheEntryKlass.getDeclaredField("inetAddresses");
af.setAccessible(true);
InetAddress[] addresses = (InetAddress[]) af.get(cacheEntry);
List ads = null;
if (addresses != null) {
ads = new ArrayList(addresses.length);
for (InetAddress address : addresses) {
ads.add(address.getHostAddress());
}
}
/*
* System.out.println(hi.getKey() + " expires in " +
* (Instant.now().until(Instant.ofEpochMilli(expires), ChronoUnit.SECONDS)) +
* " seconds. inetAddresses: " + ads);
*/
/*
* System.nanoTime() + 1000_000_000L * cachePolicy : this how java 11 set
* expiryTime
*/
System.out.println(hi.getKey() + " expires in approx " + (expires - startTimeinNano) / 1000_000_000L
+ " seconds. inetAddresses: " + ads);
}
}
}