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
仅供参考
分享到:
相关推荐
在Java编程中,DNS(Domain Name System)域名解析是将人类可读的域名转换成IP地址的过程。这个过程可以通过Java的内置类`InetAddress`来实现。以下是一个使用Java进行DNS域名解析的简单示例: ```java import java...
InetAddress域名解析
在实际应用中,`InetAddress`和`Socket`经常与其他类结合使用,如`BufferedReader`和`PrintWriter`进行数据读写,或者`SocketChannel`和`Selector`进行非阻塞I/O。这些组合可以帮助我们构建高效、可扩展的网络服务。...
InetAddress类中DNS解析后域名、IP清空 InetAddress类在进行域名解析后,会将域名和IP保存在私有成员变量map中,以便下次解析时可以快速返回结果。但是在某些场景下,这种机制会带来问题,例如在Android应用开发中...
Java地址解析和反向地址解析是网络编程中的关键概念,主要涉及到网络通信中IP地址与域名之间的转换。本文将深入探讨这两个主题,并提供相关的实践应用示例。 **一、地址解析** 地址解析,通常指的是DNS(Domain ...
在使用`InetAddress`进行域名解析时,可能会遇到`UnknownHostException`。这通常是因为DNS服务器无法找到对应的IP地址,或者输入的域名格式不正确。因此,需要捕获并处理这种异常。 5. **性能优化**: 在实际应用...
Java解析域名是网络编程中的一个基础任务,它涉及到DNS(Domain Name System)系统,这是一个用于将人类可读的域名转换为计算机可识别的IP地址的全球分布式数据库。在这个过程中,Java程序员可以使用内置的`java.net...
在Java编程中,`InetAddress`类是用来处理网络上的主机名和对应的IP地址的。当你通过`InetAddress`获取IP地址时,返回的结果通常是一个`InetAddress`对象,但如果你需要处理IP地址的原始字节表示,你可以调用`...
Java网络编程是开发分布式应用程序的关键部分,InetAddress和URL类在其中扮演了核心角色。这两个类都是Java.net包中的核心组件,它们提供了处理网络地址和定位网络资源的能力。 首先,让我们深入了解InetAddress类...
1. **Java的InetAddress类**:可以尝试将字符串转换为IP地址,如果转换成功则说明该字符串是一个有效的域名。例如: ```java try { InetAddress.getByName("example.com"); } catch (UnknownHostException e) { ...
InetAddress类在java.net包中,它是Java提供用来处理IP地址和域名的工具类。通过InetAddress,我们可以获取域名对应的IP地址,或者根据IP地址获取其对应的域名。具体方法包括: 1. `getByName(String s)`:此方法...
Java 实现清理DNS Cache的方法是解决网络应用中DNS解析问题的关键步骤,尤其是在开发和调试阶段,确保每次请求都能获取最新的IP地址。DNS(Domain Name System)缓存是为了提高域名解析速度而存储的,但有时可能需要...
`URL`类也位于`java.net`包中,提供了多种方法来解析和访问网络资源,例如: - **创建`URL`对象**:使用`URL(String url)`构造函数,其中`url`参数是资源的完整路径。 - 示例代码: ```java URL url = new URL(...
总的来说,Java提供了丰富的工具和类库来处理域名和IP地址,无论是简单的名称解析还是复杂的网络通信,都能游刃有余。在开发过程中,正确理解和运用这些知识将有助于构建高效、稳定的网络应用。
总的来说,`InetAddress`类是Java中处理网络通信的重要工具,它提供了丰富的功能,包括但不限于获取本地主机信息、解析主机名到IP地址、以及创建基于已知IP地址的对象。这些功能对于网络程序设计和分布式系统开发来...
Java的DNS解析器会在内存中缓存解析结果一段时间,以提高性能。但有时我们可能需要更新缓存,例如在DNS记录改变后。这时,可以使用`InetAddress`的静态方法`flushLocalCache`和`flushDefaultResolverCache`来清空...
Java编程中的InetAddress类是进行网络编程的重要工具,主要用于封装IP地址和对应的域名信息。它提供了多种方法,帮助开发者处理和识别不同的IP地址类型。以下是对InetAddress类及其相关方法的详细说明: 1. **...
在网络编程中,`InetAddress` 类是Java标准库中用于处理互联网地址的核心类之一。它主要用于封装和操作IP地址,并提供了一系列方法来获取和处理IP地址相关的数据。下面将详细介绍`InetAddress`类的基本用法及其相关...
在Java中,`InetAddress`的`getCanonicalHostName()`方法可以用来获取主机的完整域名,包括顶级域名。例如: ```java String canonicalHostname = inetAddress.getCanonicalHostName(); System.out.println("完全...
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....