Java DNS cache viewer

Viewed 22361

Is there a way to view/dump DNS cached used by java.net api?

5 Answers

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<InetAddress> 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<String, Object> cache = (Map<String, Object>) acf.get(addressCache);
    for (Map.Entry<String, Object> 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<String> ads = null;
        if (addresses != null) {
            ads = new ArrayList<String>(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);


    }
}}

https://github.com/alibaba/java-dns-cache-manipulator

A simple 0-dependency thread-safe Java™ lib for setting/viewing dns programmatically without touching host file, make unit/integration test portable; and a tool for setting/viewing dns of running JVM process.

This lib/tool read and set java dns cache by reflection, with concerns:

  • compatibility with different java version(support Java 6/8/11/17).
    dns cache implementation in java.net.InetAddress is different in different java version.
  • thread-safety
  • support IPv6
Related