jdk的InetAddress有一个特性,就是当系统访问过一个域名的时候,InetAddress就会通过其私有变量addressCache把域名对应的ip地址缓存起来.
虽然缓存起来能极大的提高系统性能,但有时候会给系统带来很大的麻烦.例如,当对方改动了ip地址后,系统就不能再访问到新的ip地址了,这个时候最直接的方案就是:重启jvm!!!这对于需要7*24小时服务的系统来说,是不可忍受的.
下面一段代码可以重现这个现象(但需要你在运行的时候是在调试模式):
public void testDnsCachePolicy() throws Exception {
InetAddress addr1 = InetAddress.getByName("www.baidu.com");
System.out.println(addr1.getHostAddress());
//在下一行设置断点.
int i = 0;
InetAddress addr2 = InetAddress.getByName("www.baidu.com");
System.out.println(addr2.getHostAddress());
}
具体测试方式是:
1.修改c:/windows/system32/drivers/etc/hosts文件,在文件末尾加入:64.233.189.104 www.baidu.com
这个ip地址是google的ip
2.运行代码到断点处
这时候打印出的ip地址是64.233.189.104
3.修改hosts文件,把"64.233.189.104 www.baidu.com"这行注释掉,"#64.233.189.104 www.baidu.com"
4.继续运行代码到结束
这时候打印出的ip地址还是64.233.189.104,并没有更改为baidu的ip地址.
那么应该怎么来解决这个问题呢?
查了下网上的解决方案,一般是在启动jvm的时候,指定jvm参数:networkaddress.cache.ttl和networkaddress.cache.negative.ttl,具体的含义你可以查看InetAddress的源代码.
这种方法的缺点是在JVM启动的时候就固定了dns的缓存策略.如果不缓存的话,对系统性能的影响是很大的,那么能不能动态的修改这个缓存的值呢?
正好前段时间写了篇文章:怎么通过反射修改类的私有字段值.正好有了用武之地!
下面是测试代码:
//方法中的字符串常量policy,cache,addressCache请参考InetAddress源代码.
public void testDnsCachePolicy() throws Exception {
InetAddress addr1 = InetAddress.getByName("www.baidu.com");
System.out.println(addr1.getHostAddress());
//在下一行设置断点.
int i = 0;
//修改缓存数据开始
Class inetAddressClass = java.net.InetAddress.class;
final Field cacheField = inetAddressClass.getDeclaredField("addressCache");
cacheField.setAccessible(true);
final Object obj = cacheField.get(inetAddressClass);
Class cacheClazz = obj.getClass();
final Field cachePolicyField = cacheClazz.getDeclaredField("policy");
final Field cacheMapField = cacheClazz.getDeclaredField("cache");
cachePolicyField.setAccessible(true);
cacheMapField.setAccessible(true);
final Map cacheMap = (Map)cacheMapField.get(obj);
cacheMap.remove("www.baidu.com");
//修改缓存数据结束
InetAddress addr2 = InetAddress.getByName("www.baidu.com");
System.out.println(addr2.getHostAddress());
}
重新按照上面的测试方法测试一次,第2次已经能够拿到正确的ip地址了.
如果在用apache的httpclient,那么,在把缓存中的数据清除后,需要重新创建GetMethod/PostMethod对象.
例如:
HttpClient client = new HttpClient();
GetMethod m1 = new GetMethod("http://www.baidu.com");
client.executeMethod(m1);
String content = m1.getResponseBodyAsString();
........//通过上面的反射方法清楚缓存
//重新执行m1,仍然不会得到正确的结果
client.executeMethod(m1);
String content = m1.getResponseBodyAsString();
//重新创建GetMethod,才能得到正确的结果
GetMethod m2 = new GetMethod("http://www.baidu.com");
client.executeMethod(m2);
content = m2.getResponseBodyAsString();
转自:http://www.blogjava.net/jjwwhmm/archive/2008/07/09/213685.html
仅供参考
分享到:
相关推荐
InetAddress域名解析
NULL 博文链接:https://hnzhoujunmei.iteye.com/blog/784338
InetAddress 类进行域名解析后,域名和ip会保存,如何清除。本资源娓娓道来。
由于byte被认为是unsigned byte,所以最高位的1将会被解释为符号位,另外Java中存储是按照补码存储,所以1000 0111会被认为是补码形式,转换成原码便是1111 0001,转换成十进制数便是-121
Java网络编程基础-InetAddress类与URL类
InetAddress简单使用例程。网上现有InetAddress例程老是闪退,这是自己重整理后可以使用的完整工程。
主要介绍了Java中的IP地址和InetAddress类使用详解,是Java入门学习中的基础知识,需要的朋友可以参考下
java.net.InetAddress 类包装器。 用法 获取主机的 IP 地址,给定主机名: => (by-name "github.com") # 获取本地主机地址: => (localhost) # 检查地址地址是否可达: => (reachable? (by-name "server-in-...
主要介绍了Java编程中利用InetAddress类确定特殊IP地址的方法,InetAddress类是Java网络编程中一个相当实用的类,需要的朋友可以参考下
InetAddress的用法1 java视频 马克java社区 马克towin
网络编程 InetAddress 的使用
InetAddress的用法2---马克-to-win Java视频 马克Java社区
import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.sql.Time; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing....
import java.net.InetAddress; import java.net.UnknownHostException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java....
InetAddress类的代码,用来获取主机名和IP地址
InetAddress表示ip地址,也就是主机,没有构造方法,只能通过一些get方法获取实例。如果通过主机名来获取InetAddress实例会调用本地的dns服务。
// 通过域名获得InetAddress对象 InetAddress addr = InetAddress.getByName(""); String domainName = addr.getHostName();// 获得主机名 String IPName = addr.getHostAddress();// 获得IP地址 System.out.println...
获取计算机的mac地址和ip地址,mac地址返回的是一个list,ip地址是string
Java网络编程基础 InetAddress类的使用.doc Java网络编程基础 ServerSocket类使用.doc 《JAVA编程规范》.doc Java基础 三步学会Java Socket编程(一) .doc Java基础 三步学会Java Socket编程(二) .doc Java基础 三步...
Java和ColdFusion库可从IP地址查找国家代码和语言。 它使用WHOIS数据库的本地副本来执行快速,准确的国家代码查询。 对于日志分析,国际化,地理位置定位等有用。