Hello,
I have a service running on a few Linux computers. Those computers have a NIC, which is configured with a fixed IP address. So /etc/resolv.conf contains the IP address of the LAN's DNS server. But most of the time, the computers are not plugged into the LAN at all. Instead, they connect themselves periodically to the Internet by establishing a ppp connection. When it happens, the ISP's DHCP server assign them new IP parameters, including their DNS server's IP address. And /etc/resolv.conf gets updated with this address.
But it seems that java doesn't take care of DNS change taking place during a run. Which means that my program (started at boot with no connectivity at all) tries to connect to some host, and obviously trigger an "UnknownHostException" (at that point it does try to contact the LAN's DNS server). Quite logical. Later, the ppp link become active. But my program still try to contact the LAN's DNS server, despite the new configuration in /etc/resolv.conf. As such, it will forever trigger UnknowHostExceptions, until it gets restarted (it will then pick up the new settings) or it is plugged back into the LAN (it will finally reach the LAN's DNS server).
This is quite a problem as during one single execution, the machine may encounter several DNS configuration changes, and this problem basically means that it will be impossible for my application to resolve any name at all.
So is there a way to tell Java to re-read the system wide DNS configuration? Or is there some option to prevent Java to "cache" the DNS server to use?
To demonstrate my problem, I've written a simple test case, see below.
To get the problem:
1) Put a bogus DNS server into your /etc/resolv.conf
2) Start the test program. Wait for some time: it will trigger UnknownHostExceptions.
3) Fix the entry in /etc/resolv.conf, and check it actually works (eg ping www.google.be)
4) Test program will continue to trigger UnknownHostExceptions forever.
One interesting fact is that someone tried this test on Windows, and didn't suffer from this behaviour, eg the application reacts to DNS system settings changes dynamically. So it looks like a Linux-only problem.
Thanks in advance for your insight.
Pierre-Yves
package com.test.dnsresolver;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class DnsResolver {
private static String urlString = "www.google.com";
public static void main(String[] args) {
/**
* Specified in java.security to indicate the caching policy for successful
* name lookups from the name service. The value is specified as as integer
* to indicate the number of seconds to cache the successful lookup.
*/
java.security.Security.setProperty("networkaddress.cache.ttl" , "10");
/**
* Specified in java.security to indicate the caching policy for un-successful
* name lookups from the name service. The value is specified as as integer to
* indicate the number of seconds to cache the failure for un-successful lookups.
* A value of 0 indicates "never cache". A value of -1 indicates "cache forever".
*/
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "0");
int loopCounter = 0;
while (true) {
InetAddress resolved;
try {
resolved = InetAddress.getByName(urlString);
System.out.println("Loop " + loopCounter + ": resolved IP address: " + resolved);
} catch (UnknownHostException e) {
System.out.println("Loop " + loopCounter + ": UnknownHostException");
e.printStackTrace();
}
loopCounter++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}