在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动态解析类.

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

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

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  2. java itext替换PDF中的文本

    itext没有提供直接替换PDF文本的接口,我们可以通过在原有的文本区域覆盖一个遮挡层,再在上面加上文本来实现. 所需jar包: 1.先在PDF需要替换的位置覆盖一个白色遮挡层(颜色可根据PDF文字背 ...

  3. Java动态代理——框架中的应用场景和基本原理

    前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...

  4. MessageFormat的用法,java动态替换String字符串中的占位符

    import java.text.MessageFormat; import java.util.GregorianCalendar; import java.util.Locale; public ...

  5. 【Android】通过Java代码替换TabHost中的drawableTop资源

    在博客 http://blog.csdn.net/jueblog/article/details/11837445 中的Tab选项卡中, 点击相应的Tab选项,图标没有发生改变. 这些资源图片也没有尽 ...

  6. Java动态调用类中方法

    在Java中,调用类的方法有两种方式:对于静态方法可以直接使用类名调用,对于非静态方法必须使用类的对象调用.反射机制提供了比较另类的调用方式,可以根据需要指定要调用的方法,而不必在编程时确定.调用的方 ...

  7. Java 动态向 JTable 中添加数据

    import java.awt.Toolkit; import javax.swing.SwingUtilities; import javax.swing.UIManager; import jav ...

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

    TimSort算法是一种起源于归并排序和插入排序的混合排序算法,设计初衷是为了在真实世界中的各种数据中能够有较好的性能. 该算法最初是由Tim Peters于2002年在Python语言中提出的. T ...

  9. java获取properties配置文件中某个属性最简单方法

    假如我想获取src目录下sysConfig.properties中的uploadpath属性的值 方法如下所示: private static final ResourceBundle bundle ...

随机推荐

  1. gem5 运行x86全系统仿真

    使用gem5可以启动Linux内核,称为全系统模拟,启动之后,可以通过telent连接,进行访问,但四telent有时不稳定,gem5推荐使用m5term进行连接访问,整个步骤如下: (1)打开终端, ...

  2. .NET本质论(4)应用程序对象HttpApplication

    当HttpContext对象创建之后,HttpRuntime将随后创建一个用于处理请求的对象,这个对象的类型为HttpApplication.  在ASP.NET内部,HttpRuntime管理一个定 ...

  3. javascript设计模式-观察者模式

    观察者模式定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己. UML示意图: 其中的角色: Subject:主 ...

  4. python 标准库获取网络信息

    c语言ioctl定义的常量 /usr/include/x86_64-linux-gnu/bits/ioctls.h /* Copyright (C) 1996-2015 Free Software F ...

  5. dell N1500 安全配置

    http://www.dell.com/Support/Article/us/en/19/HOW10832 Setting a management IP address A reachable IP ...

  6. 【MySQL】MySQL回滚工具

    1.mysqlbinlog把事务从binlog中导出 2.从导出的binlog中找到要回滚的事务,去掉第一个DML语句前和最后一个DML语句后与DML无关的binlog信息 3.在目录中新建一个tab ...

  7. EasyUI学习笔记

    1,tabs获得被选中的标题 var tabTitle = $('#tabs').tabs('getSelected').panel('options').title;//获得被选中的标题 2.当设置 ...

  8. Unieap3.5Java端常用公用方法

    String OrgId = McssComMethod.getDimensionID(); Date systemDate =  DataStoreUtil.getOracleSystemDate( ...

  9. Android开发教程大全介绍

    Android是由谷歌在2007年推出的一个开放系统平台,主要针对移动设备市场,目前版本为Android 4.0.Android基于Linux,开发者可以使用Java或C/C++开发Android应用 ...

  10. CentOS-6.4无线上网命令行配置

      参考:http://www.vfeelit.com/504.html 待连接的WIFI的ssid为“thm”,密码为12345678,认证方式为WPA2-PSK   1. 检查无线网卡驱动是否安装 ...