在通过DNS查找域名的过程中,可能会经过多台中间DNS服务器才能找到指定的域名,因此,在DNS服务器上查找域名是非常昂贵的操作。在Java中为了缓解这个问题,提供了DNS缓存。当InetAddress类第一次使用某个域名(如www.csdn.net)创建InetAddress对象后,JVM就会将这个域名和它从DNS上获得的信息(如IP地址)都保存在DNS缓存中。当下一次InetAddress类再使用这个域名时,就直接从DNS缓存里获得所需的信息,而无需再访问DNS服务器。
DNS缓存在默认时将永远保留曾经访问过的域名信息,但我们可以修改这个默认值。一般有两种方法可以修改这个默认值:
1. 在程序中通过java.security.Security.setProperty方法设置安全属性networkaddress.cache.ttl的值(单位:秒)。如下面的代码将缓存超时设为10秒:
java.security.Security.setProperty( " networkaddress.cache.ttl " , 10 );
2. 设置java.security文件中的networkaddress.cache.negative.ttl属性。假设JDK的安装目录是C:\jdk1.6,那么java.security文件位于c:\jdk1.6\jre\lib\security目录中。打开这个文件,找到networkaddress.cache.ttl属性,并将这个属性值设为相应的缓存超时(单位:秒)。
如果将networkaddress.cache.ttl属性值设为-1,那么DNS缓存数据将永远不会释放。下面的代码演示了使用和不使用DNS缓存所产生效果:
package
mynet;
import
java.net.
*
;
public
class
MyDNS
{
public
static
void
main(String[] args)
throws
Exception
{
//
args[0]: 本机名 args[1]:缓冲时间
if
(args.length
<
2
)
return
;
java.security.Security.setProperty(
"
networkaddress.cache.ttl
"
, args[
1
]);
long
time
=
System.currentTimeMillis();
InetAddress addresses1[]
=
InetAddress.getAllByName(args[
0
]);
System.out.println(
"
addresses1:
"
+
String.valueOf(System.currentTimeMillis()
-
time)
+
"
毫秒
"
);
for
(InetAddress address : addresses1)
System.out.println(address);
System.out.print(
"
按任意键继续
"
);
System.in.read();
time
=
System.currentTimeMillis();
InetAddress addresses2[]
=
InetAddress.getAllByName(args[
0
]);
System.out.println(
"
addresses2:
"
+
String.valueOf(System.currentTimeMillis()
-
time)
+
"
毫秒
"
);
for
(InetAddress address : addresses2)
System.out.println(address);
}
}
在上面的代码中设置了DNS缓存超时(通过args[1]参数),用户可以通过命令行参数将这个值传入MyDNS中。这个程序首先使用getAllByName建立一个InetAddress数组,然后通过System.in.read使程序暂停。当用户等待一段时间后,可以按任意键继续,并使用同一个域名(args[0])再建立一个InetAddress数组。如果用户等待的这段时间比DNS缓存超时小,那么无论情况如何变化,addresses2和addresses1数组中的元素是一样的,并且创建addresses2数组所花费的时间一般为0毫秒(小于1毫秒后,Java无法获得更精确的时间)。
测试1:
执行如下命令(将DNS缓存超时设为5秒):
java mynet.MyDNS www. 126 .com 5
运行结果1(在5秒之内按任意键):
addresses1: 344毫秒
www
.126
.com/
202.108.9.77
按任意键继续
addresses2: 0毫秒
www
.126
.com/
202.108.9.77
运行结果2(在5秒后按任意键):
addresses1: 344毫秒
www
.126
.com/
202.108.9.77
按任意键继续
addresses2: 484毫秒
www
.126
.com/
202.108.9.77
在上面的测试中可能出现两个运行结果。如果在出现“按任意键继续…”后,在5秒之内按任意键继续后,就会得到运行结果1,从这个结果可以看出,addresses2所用的时间为0毫秒,也就是说,addresses2并未真正访问DNS服务器,而是直接从内存中的DNS缓存得到的数据。当在5秒后按任意键继续后,就会得到运行结果2,这时,内存中的DNS缓存中的数据已经释放,所以addresses2还得再访问DNS服务器,因此,addresses2的时间是484毫秒(addresses1和addresses2后面的毫秒数可能在不同的环境下的值不一样,但一般情况下,运行结果1的addresses2的值为0或是一个接近0的数,如5.运行结果2的addresses2的值一般会和addresses1的值很接近,或是一个远比0大的数,如1200)。