在JVM中清除DNS服务器

3
在我第一篇关于DNS的文章中,仍然没有解决:JVM和操作系统DNS缓存,我面临一个新问题。
首先,这是我的用例:我想检查我的私有DNS是否正常运行。如果不是,我想使用通用DNS(例如8.8.8.8)。
我的私有DNS(在Ubuntu上的bind9,IP地址为192.168.1.188)有一个特定的记录:test.testdnd.fr -> 192.168.1.100
所以我认为我可以这样做:
if(InetAddress.getByAddress(my_dns_ip_in_byte).isReachable()){
    System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
    System.setProperty("sun.net.spi.nameservice.nameservers", 192.168.1.188);
}else{
    System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
    System.setProperty("sun.net.spi.nameservice.nameservers", "8.8.8.8");
}
 InetAddress.getHostByAddress(test.testdnd.fr) -> unknow host exception

但如果我只做这个:
System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
System.setProperty("sun.net.spi.nameservice.nameservers", 192.168.1.188);
InetAddress.getHostByAddress(test.testdnd.fr) -> 192.168.1.100

在设置系统属性之前调用InetAddress方法,似乎会导致系统属性无效。可能是因为当调用InetAddress方法时,JVM会加载系统DNS值,即使它不使用DNS解析。

这是JVM的标准行为还是我漏掉了什么?

欢迎任何帮助,


可能是重复的问题:设置DNS属性没有任何效果 - frostmatthew
这并不是重复的问题,我想使用私有 DNS 服务器。 - zeraDev
你确定 InetAddress.getByAddress(my_dns_ip_in_byte).isReachable() 返回 true 吗?(如果你还没有检查过,应该在 if 块中添加一些调试输出来查看) - frostmatthew
Yup InetAddress.getByAddress(my_dns_ip_in_byte).isReachable() 返回 true,如果我在两个括号块中放一个日志,我会看到它不会进入“else”块。 - zeraDev
2个回答

7

问题在于,名称服务提供者仅在InetAddress中加载一次,并被缓存以供进一步使用。这个加载发生在InetAddress类的静态初始化器中。因此,一旦InetAddress被初始化,设置或更改sun.net.spi.nameservice.provider属性将不再产生作用。


感谢您的解释。 - zeraDev

0

JVM仅在使用系统默认值的查找失败时使用您设置的DNS提供程序。 您可以在文档(http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html)中看到此内容,相关摘录:

默认情况下,Java将使用系统配置的名称查找机制

您可以指定逗号分隔的IP地址列表,这些地址指向您想要使用的DNS服务器

在JDK 7中,提供程序被链接在一起,这意味着如果一个提供程序的查找失败,则会咨询列表中的下一个提供程序来解析名称。


是的,但在我的情况下,我尝试解析一个私有记录(不在公共DNS中)。因此,通常JVM应该尝试使用下一个提供程序(我的私有DNS),但如果我在设置属性之前调用了网络方法,则不会这样做。 - zeraDev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接