Java动态替换InetAddress中DNS的做法简单分析1

在java.net包描述中, 简要说明了一些关键的接口. 其中负责networking identifiers的是Addresses. 这个类的具体实现类是InetAddress, 底层封装了Inet4Address与Inet6Address的异同, 可以看成一个Facade工具类.

  1. A Low Level API, which deals with the following abstractions:

  2. Addresses, which are networking identifiers, like IP addresses.
  3. Sockets, which are basic bidirectional data communication mechanisms.
  4. Interfaces, which describe network interfaces.

复制代码

在OpenJDK的InetAddress源码中, 根据dns或hostname解析IP的代码部分:

  1. private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)

  2. throws UnknownHostException  {
  3. /* If it gets here it is presumed to be a hostname */

  4. /* Cache.get can return: null, unknownAddress, or InetAddress[] */
  5. /* make sure the connection to the host is allowed, before we

  6. * give out a hostname
  7. */
  8. if (check) {
  9. SecurityManager security = System.getSecurityManager();
  10. if (security != null) {
  11. security.checkConnect(host, -1);
  12. }
  13. }
  14. InetAddress[] addresses = getCachedAddresses(host);

  15. /* If no entry in cache, then do the host lookup */

  16. if (addresses == null) {
  17. addresses = getAddressesFromNameService(host, reqAddr);
  18. }
  19. if (addresses == unknown_array)

  20. throw new UnknownHostException(host);
  21. return addresses.clone();

  22. }

复制代码

关键的二个方法是:
getCachedAddresses(host);
getAddressesFromNameService(host, reqAddr);
前者从addressCache, 或negativeCache根据dns/hostname解析缓存的IP.
后者从遍历nameServices,调用每个NameService的lookupAllHostAddr(host)查找IP, 然后将host:IP缓存到前面的cache中.
根据上述, 实现动态解析DNS, 有二种方式:
1. 反射addressCache, 或negativeCache, 将host:IP通过Cache的put()方法放入.
2. 反射nameServices,将代理的NameService实例放入.
二种做法的难处:
1. addressCache, 或negativeCache都是 java.net.InetAddress.Cache, 其内部的CacheEntry受二组JVM选项影响:
networkaddress.cache.ttl
networkaddress.cache.negative.ttl
在ttl后, CacheEntry的get()只会返回null.
2. nameServices只是OpenJDK的实现. 换言之,只是SUN一家的. 其他JDK不用此属性名.
写段代码看看Jrockit与IBM JVM中InetAddress内部的属性:

  1. Class<InetAddress> type = InetAddress.class;

  2. Field[] fields = type.getDeclaredFields();

  3. for (Field f : fields) {

  4. System.out.println(f.getName() + ":" + f.getType());
  5. }

复制代码

OpenJDK:

  1. IPv4

  2. IPv6
  3. preferIPv6Address
  4. holder
  5. nameServices
  6. canonicalHostName
  7. serialVersionUID
  8. addressCache
  9. negativeCache
  10. addressCacheInit
  11. unknown_array
  12. impl
  13. lookupTable
  14. cachedLocalHost
  15. cacheTime
  16. maxCacheTime
  17. cacheLock
  18. FIELDS_OFFSET
  19. UNSAFE
  20. serialPersistentFields
  21. $assertionsDisabled

复制代码

JRockit:

  1. IPv4

  2. IPv6
  3. preferIPv6Address
  4. hostName
  5. address
  6. family
  7. nameService
  8. canonicalHostName
  9. serialVersionUID
  10. addressCache
  11. negativeCache
  12. addressCacheInit
  13. unknown_array
  14. impl
  15. lookupTable
  16. $assertionsDisabled

复制代码

IBM JDK

  1. IPv4:int

  2. IPv6:int
  3. preferIPv6Address
  4. hostName:class java.lang.String
  5. address:int
  6. family:int
  7. nameService:interface sun.net.spi.nameservice.NameService
  8. canonicalHostName:class java.lang.String
  9. serialVersionUID:long
  10. addressCache:class java.net.InetAddress$Cache
  11. negativeCache:class java.net.InetAddress$Cache
  12. localHostName:class java.lang.String
  13. localHostNameLock:class java.lang.Object
  14. cacheLocalHost:boolean
  15. addressCacheInit:boolean
  16. unknown_array:class [Ljava.net.InetAddress;
  17. impl:interface java.net.InetAddressImpl
  18. lookupTable:class java.util.HashMap
  19. $assertionsDisabled:boolean

复制代码

看到这里, 知道蛋疼了吧. 三种JDK中,
OpenJDK中是nameservices是个List<NameService>,
Jrockit与IBM JVM中却是nameservice, 只是单独的NameService实例.
所以要用第2种做法, 你至少要满足这三种主流JDK的需求.
简单实现二种做法:
做法1, 动态替换AddressCache.
做法2, 动态代理NameService.
源码如下

  1. 长度限制, 源码查看回贴.

复制代码

暂时测试到这吧, 有兴趣的同学可以一起完善. 争取同时满足OpenJDK, Jrockit, IBM JDK三种主流环境的DNS动态解析类.

时间: 2024-11-05 12:09:20

Java动态替换InetAddress中DNS的做法简单分析1的相关文章

Java动态替换InetAddress中DNS的做法简单分析2

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.InetAddress;

WebRTC中的AppRTCDemo.apk简单分析

以前一直在QQ空间记录一些简单的关于webrtc的笔记.博说不如发布CSDN,想想也可以,解决了一些小问题,也可以帮助一下其它碰到该同样问题的人. 上周试着将WebRTC中的PeerConnection_client进行改写,拿 掉了PeerConnection_Server端,改用openfire服务器,信令采用xmpp,主要代码来源于call.主要还是将http请求用xmpp重写了,原理上很简单,合并后,效果还可以. 现在开始看android版本的peerconnection,也就是标题的A

java程序替换word2007中的图片

1.新建word2007文档h2do.docx: 2.QQ截图粘贴到文档,添加些文字: 3.用winrar打开(修改扩展名docx为rar或右键->打开方式->选择winrar程序),目录结构如下: . │  [Content_Types].xml │ ├─docProps │      app.xml │      core.xml │ ├─word │  │  comments.xml │  │  document.xml │  │  endnotes.xml │  │  fontTabl

maven项目动态替换配置中的值

为何一些maven项目可以替换配置文件中的变量? 比如说一个log4j.properties文件中: logFolder=${log4j.folder} BufferedIO=${log4j.bufferedIO} ImmediateFlush=${log4j.immediateFlush} # 根日志(没有指定自定义logger的会使用此配置) 日志等级阀门在此 #debug log4j.rootLogger=info,commonLog,errorLog 变量${log4j.folder}?

java.util.ComparableTimSort中的sort()方法简单分析

TimSort算法是一种起源于归并排序和插入排序的混合排序算法,设计初衷是为了在真实世界中的各种数据中能够有较好的性能. 该算法最初是由Tim Peters于2002年在Python语言中提出的. TimSort 是一个归并排序做了大量优化的版本号. 对归并排序排在已经反向排好序的输入时表现O(n2)的特点做了特别优化.对已经正向排好序的输入降低回溯.对两种情况混合(一会升序.一会降序)的输入处理比較好. 在jdk1.7之后.Arrays类中的sort方法有一个分支推断,当LegacyMerge

【Flume】flume中通道channel的简单分析梳理

Channels are the repositories where the events are staged on a agent. Source adds the events and Sink removes it. 通道就是事件暂存的地方,source负责往通道中添加event,sink负责从通道中移出event flume1.5.2内置的通道有:内存,文件,jdbc 1.内存通道memory-channel 时间存储在内存队列中,对于性能要求高且能接受agent失败时数据丢失的情况

java动态代理实现与原理详细分析

一.代理模式代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途.在后面我会 解释这种间

Java动态代理原理

关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.简单的说就是

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕