14

I am facing a problem with JVM and DNS.

Everything I'm reading (including the docs and this) says that I can disable JVM DNS caching using networkaddress.cache.ttl, which can be set using java.security.Security.setProperties, but through the standard approach of using system properties. I have successfully changed this to 0, so no more caching in my JVM.

But now, on each call of InetAddress.getByName("mytest.com"), it seems that my JVM is using the system DNS cache (in my case Windows 8). Indeed, between 2 calls of the method, I have changed the BIND9 properties for "mytest.com", but the IP return is still the same. Here is the workflow:

  1. setCachePolicyInJVM(0) in my Java code.
  2. set mytest.com to 192.168.1.188 in BIND9, restart.
  3. InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.188
  4. set mytest.com -> 192.168.1.160 in BIND9, restart.
  5. InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.188 (should be 160 if there was no caching).
  6. Flush the Windows DNS
  7. InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.160

I have read several times that the JVM does not use the system cache, but that is wrong: it clearly does.

How do we force a new DNS resolution on each call, bypassing the OS DNS cache?

Robert Fischer
  • 1,436
  • 12
  • 26
zeraDev
  • 381
  • 1
  • 3
  • 16
  • This would also be useful to me: I am attempting to disable JVM DNS caching in an effort to exercise all the IP addresses on the other side of a load balancer during a failover scenario. Since we're in a failover scenario, I can't know the new IP addresses ahead of time, and it's also not clear when the new IP addresses will come online. So I really need the DNS lookup to happen each time. – Robert Fischer Jan 07 '14 at 17:41

3 Answers3

6

I think I've run into this problem, or a very similar one. What I did then was to implement my own DNS provider for the JVM, see how to change the java dns service provider for details. You can use the dnsjava mentioned there or roll your own.

Community
  • 1
  • 1
Alexander Torstling
  • 18,552
  • 7
  • 62
  • 74
  • Can you change the "root" DNS service provider? I thought you could only add new providers that would be called when the earlier providers are negative. – Robert Fischer Jan 09 '14 at 13:38
3

You can either edit your $JAVA_HOME/jre/lib/security/java.security for Java 6-8 and $JAVA_HOME/conf/security/java.security property file to add the following property .

networkaddress.cache.ttl=1

It is not available to set it in command line.

Since these 2 properties are part of the security policy, they are not set by either the -D option or the System.setProperty() API, instead they are set as security properties.

To set this property inside the code, you can use the following method.

java.security.Security.setProperty("networkaddress.cache.ttl", "1")

Or add the following property in the java command line.

-Dnetworkaddress.cache.ttl=1

It is also important to note that values are effective only if the corresponding networkaddress.cache.* properties are not set in the security file.

See Java 8 Networking Properties, Java 9 Networking Properties and VeriSign DNS Caching in Java Virtual Machines for more details.

This answer also adds some details.

Nicolas Henneaux
  • 11,507
  • 11
  • 57
  • 82
  • setting `-Dnetworkaddress.cache.ttl=1` on the command line does not work, because this is a security property and not a system property. `sun.net.inetaddr.ttl` can be set in java 8 at least, however this feature is deprecated. – zhujik Sep 08 '20 at 06:10
  • @Nicolas Henneaux In Spring Boot, does using @ Configuration class with java.security.Security.setProperty("networkaddress.cache.ttl", "1") make sense? I am using `application.properties` to connect to JDBC but it seems Hikari CP connects before setting this property. Is that a problem? – alext Jan 02 '21 at 11:29
  • It is important the property is set before the first DNS resolution in the whole JVM. Setting it where Hikari CP is configured should work but it needs to be tested since another name might be resolved before calling this class. – Nicolas Henneaux Jan 02 '21 at 13:31
0

From here it seems you should set sun.net.inetaddr.ttl. This worked for me.

Example from link:

java -Dsun.net.inetaddr.ttl=1 test
Enter the hostname
rrr
Output isrrr/129.145.146.100
Enter the hostname
rrr
Output isrrr/129.147.146.100
tudor
  • 151
  • 2
  • 8