Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Java does not provide a supported public API for listing the entries in its built-in DNS cache. You can still see the addresses a JVM currently returns, inspect its positive and negative cache policies, and confirm whether lookups reach a resolver using DNS logs or packet capture. Those methods answer different questions: a returned address alone does not tell you which cache layer supplied it.

What Java caches

Java’s InetAddress resolver caches successful hostname lookups (positive results) and failed lookups (negative results, which can lead to UnknownHostException). Newer JDK documentation also describes an optional stale-name cache that can retain an expired result when a refresh fails. The exact behavior depends on the JDK and its configuration; consult the documentation for the runtime you deploy. See the Java 24 InetAddress documentation.

This is distinct from the DNS record’s TTL and from caches elsewhere in the system. Java resolves names through configured local naming services, which may involve an operating-system resolver, a local DNS stub, or other services. An HTTP client, connection pool, proxy, service-discovery library, container, or service mesh may also cache or reuse destinations independently.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Print the addresses visible to the JVM

Use InetAddress.getAllByName to display every address returned to the current process:

import java.net.InetAddress;

public class ResolveHost {
    public static void main(String[] args) throws Exception {
        String host = args.length == 0 ? "example.com" : args[0];
        System.out.println("Host: " + host);

        InetAddress[] addresses = InetAddress.getAllByName(host);
        for (int i = 0; i < addresses.length; i++) {
            InetAddress address = addresses[i];
            System.out.printf("%d: %s%n", i + 1, address.getHostAddress());
        }
    }
}

Run it with an optional hostname argument, for example java ResolveHost api.example.com. Multiple results, including both IPv4 and IPv6 addresses, are normal. The order returned is not a guarantee of traffic distribution or connection preference.

This shows the result available through that JVM’s resolver path; it does not prove that Java’s cache supplied it or that a DNS packet was sent. Avoid calling getCanonicalHostName() in a forward-lookup test: it may trigger reverse resolution and add another name-service operation. getHostAddress() prints the numeric address without that extra lookup.

There is no documented public InetAddress.listCache() or cache-flush method. The public lookup methods return addresses, not cache entries, remaining TTLs, or cache-hit metadata. Reflection into JDK internals may expose implementation details on some runtimes, but field names, access rules, and behavior can change; it is not a portable production solution.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Inspect the JVM’s DNS cache policy

The documented controls are Java security properties. Read them with Security.getProperty, not System.getProperty:

import java.security.Security;

public class DnsCachePolicy {
    private static String value(String name) {
        String result = Security.getProperty(name);
        return result == null ? "<unset>" : result;
    }

    public static void main(String[] args) {
        System.out.println("positive TTL = "
                + value("networkaddress.cache.ttl"));
        System.out.println("negative TTL = "
                + value("networkaddress.cache.negative.ttl"));
        System.out.println("stale TTL    = "
                + value("networkaddress.cache.stale.ttl"));
    }
}
Property Controls How to read it
networkaddress.cache.ttl Successful lookups Seconds to retain positive results. The default is implementation-specific in current documentation.
networkaddress.cache.negative.ttl Failed lookups Seconds to retain failures. The documented default is 10 seconds.
networkaddress.cache.stale.ttl Stale results after a failed refresh Optional and JDK-version-dependent; unset or zero disables this stale-name cache in the documented behavior.

For the positive and negative policies, 0 means do not cache that category, while a negative value means cache indefinitely. Stale-cache behavior has its own documented qualifications: negative values are ignored, and support should be checked against the target JDK. The JDK API documentation and networking properties documentation describe the applicable properties. Early-access documentation may not match every released runtime, so verify the version you run.

Because these are security properties, do not assume -Dnetworkaddress.cache.ttl=60 or System.setProperty("networkaddress.cache.ttl", "60") configures them. The networking-properties documentation specifically distinguishes them from ordinary system properties. Configure the security properties using the mechanism supported by your JDK and deployment, before relevant lookups occur. A configuration change is not a reliable way to erase entries already held by a running JVM.

Test whether results change over time

A repeated lookup can reveal changes in results and provide useful timing evidence, but it cannot identify a cache hit by itself:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import java.net.InetAddress;
import java.time.Instant;

public class RepeatedDnsLookup {
    public static void main(String[] args) throws Exception {
        String host = args.length == 0 ? "example.com" : args[0];

        for (int i = 1; i <= 10; i++) {
            long start = System.nanoTime();
            InetAddress[] addresses = InetAddress.getAllByName(host);
            long elapsedMicros = (System.nanoTime() - start) / 1_000;

            System.out.printf("%s lookup %d: %d microseconds%n",
                    Instant.now(), i, elapsedMicros);
            for (InetAddress address : addresses) {
                System.out.println("  " + address.getHostAddress());
            }
            Thread.sleep(1_000);
        }
    }
}

Run a controlled test against a hostname whose answer you can change, and record the JVM version, configuration, timestamps, and returned addresses. A fast second lookup is only suggestive: an OS cache, local resolver, container DNS, or upstream cache can also make it fast. A changed result does not prove Java’s entry expired; the resolver path or answer may have changed. Timing alone is not a cache-hit detector.

For negative caching, test a name that is genuinely nonexistent, such as a name under .invalid, and observe whether repeated lookups continue to fail. Failures may be retained according to networkaddress.cache.negative.ttl. A temporary resolver problem is not the same as a nonexistent name, and application libraries may add their own failure caching. Use a fresh JVM when checking a changed policy.

Confirm whether DNS traffic was sent

To establish whether a query reached the network, observe the resolver path rather than infer it from Java’s return value. Options include DNS server query logs, local resolver metrics, container or node telemetry, and packet capture. On Linux, a basic capture is:

sudo tcpdump -ni any '(udp port 53 or tcp port 53)'

Make a lookup from the application while capturing, and check which interface and resolver are actually in use. A port-53 capture can show nothing if the process uses encrypted DNS, a custom resolver, a local socket-based service, or another path. DNS logs are often more useful when queries are forwarded or captured outside the application host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You can compare Java’s result with dig example.com, but treat that as a comparison between two resolver paths, not a definitive cross-check. dig may run on a different host or in a different container or network namespace, and it may read resolver settings differently from the JVM. Confirm both tools are testing the same environment and resolver before interpreting a mismatch.

How to start with a clean Java cache

For a dependable, portable reset of the built-in in-process resolver state, restart the JVM. Set the desired policy before the application performs lookups. Changing a property or configuration file while a process is running should not be treated as a guaranteed flush of existing positive or negative entries.

There is no documented public InetAddress cache-flush call. Internal reflection is version-sensitive and may be blocked by module-access rules, so avoid relying on it for incident response or production behavior. Restarting an HTTP client alone may not help if the same JVM’s resolver cache remains in use; conversely, a fresh JVM may not clear a client’s external proxy, service-discovery, or network-level cache.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot stale destinations in production

  1. Log what the JVM resolves. Record the hostname, all numeric addresses from getAllByName, timestamp, and lookup duration at a controlled diagnostic point.
  2. Check connection reuse. Existing pooled connections do not need to resolve the hostname again. A DNS change will not necessarily move an established connection.
  3. Check every cache layer. Review the JDK policy, HTTP-client or framework resolver, service discovery, proxy, sidecar, and node/container resolver.
  4. Check failures as well as successes. A negative cache can preserve a transient lookup failure after DNS becomes healthy.
  5. Compare like with like. Run diagnostic tools in the same container and network namespace as the application, and identify the resolver they contact.
  6. Use network evidence for query claims. Packet capture or resolver logs can show queries; returned values and timing cannot conclusively identify their source.

For specialized systems, a custom InetAddressResolverProvider or a library-level resolver can provide explicit resolution behavior and observability, but those approaches replace or extend resolution; they do not automatically reveal entries in the built-in cache. See the JDK InetAddress documentation for resolver-provider details.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does Java cache DNS forever?

Not universally. Positive-cache defaults depend on the runtime and configuration. Inspect the running JDK’s security properties and documentation rather than assuming a fixed default.

Does Java honor the DNS record’s TTL?

Do not assume the JVM cache duration matches the authoritative record TTL. Java’s cache policy is governed by its own security properties and runtime behavior.

Does InetAddress.getByName always query DNS?

No. It resolves through the JVM’s configured naming path and may return a cached result or use a local naming service rather than sending a DNS query.

Can I use -Dnetworkaddress.cache.ttl to set the cache duration?

Do not rely on it. These controls are documented as security properties, not ordinary system properties; use the configuration mechanism for your JDK and deployment.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.