Java动态替换InetAddress中DNS的做法简单分析1
在java.net包描述中, 简要说明了一些关键的接口. 其中负责networking identifiers的是Addresses. 这个类的具体实现类是InetAddress, 底层封装了Inet4Address与Inet6Address的异同, 可以看成一个Facade工具类.
- A Low Level API, which deals with the following abstractions:
- Addresses, which are networking identifiers, like IP addresses.
- Sockets, which are basic bidirectional data communication mechanisms.
- Interfaces, which describe network interfaces.
复制代码
在OpenJDK的InetAddress源码中, 根据dns或hostname解析IP的代码部分:
- private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
- throws UnknownHostException {
- /* If it gets here it is presumed to be a hostname */
- /* Cache.get can return: null, unknownAddress, or InetAddress[] */
- /* make sure the connection to the host is allowed, before we
- * give out a hostname
- */
- if (check) {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkConnect(host, -1);
- }
- }
- InetAddress[] addresses = getCachedAddresses(host);
- /* If no entry in cache, then do the host lookup */
- if (addresses == null) {
- addresses = getAddressesFromNameService(host, reqAddr);
- }
- if (addresses == unknown_array)
- throw new UnknownHostException(host);
- return addresses.clone();
- }
复制代码
关键的二个方法是:
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内部的属性:
- Class<InetAddress> type = InetAddress.class;
- Field[] fields = type.getDeclaredFields();
- for (Field f : fields) {
- System.out.println(f.getName() + ":" + f.getType());
- }
复制代码
OpenJDK:
- IPv4
- IPv6
- preferIPv6Address
- holder
- nameServices
- canonicalHostName
- serialVersionUID
- addressCache
- negativeCache
- addressCacheInit
- unknown_array
- impl
- lookupTable
- cachedLocalHost
- cacheTime
- maxCacheTime
- cacheLock
- FIELDS_OFFSET
- UNSAFE
- serialPersistentFields
- $assertionsDisabled
复制代码
JRockit:
- IPv4
- IPv6
- preferIPv6Address
- hostName
- address
- family
- nameService
- canonicalHostName
- serialVersionUID
- addressCache
- negativeCache
- addressCacheInit
- unknown_array
- impl
- lookupTable
- $assertionsDisabled
复制代码
IBM JDK
- IPv4:int
- IPv6:int
- preferIPv6Address
- hostName:class java.lang.String
- address:int
- family:int
- nameService:interface sun.net.spi.nameservice.NameService
- canonicalHostName:class java.lang.String
- serialVersionUID:long
- addressCache:class java.net.InetAddress$Cache
- negativeCache:class java.net.InetAddress$Cache
- localHostName:class java.lang.String
- localHostNameLock:class java.lang.Object
- cacheLocalHost:boolean
- addressCacheInit:boolean
- unknown_array:class [Ljava.net.InetAddress;
- impl:interface java.net.InetAddressImpl
- lookupTable:class java.util.HashMap
- $assertionsDisabled:boolean
复制代码
看到这里, 知道蛋疼了吧. 三种JDK中,
OpenJDK中是nameservices是个List<NameService>,
Jrockit与IBM JVM中却是nameservice, 只是单独的NameService实例.
所以要用第2种做法, 你至少要满足这三种主流JDK的需求.
简单实现二种做法:
做法1, 动态替换AddressCache.
做法2, 动态代理NameService.
源码如下
- 长度限制, 源码查看回贴.
复制代码
暂时测试到这吧, 有兴趣的同学可以一起完善. 争取同时满足OpenJDK, Jrockit, IBM JDK三种主流环境的DNS动态解析类.
Java动态替换InetAddress中DNS的做法简单分析1的更多相关文章
- Java动态替换InetAddress中DNS的做法简单分析2
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...
- java itext替换PDF中的文本
itext没有提供直接替换PDF文本的接口,我们可以通过在原有的文本区域覆盖一个遮挡层,再在上面加上文本来实现. 所需jar包: 1.先在PDF需要替换的位置覆盖一个白色遮挡层(颜色可根据PDF文字背 ...
- Java动态代理——框架中的应用场景和基本原理
前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...
- MessageFormat的用法,java动态替换String字符串中的占位符
import java.text.MessageFormat; import java.util.GregorianCalendar; import java.util.Locale; public ...
- 【Android】通过Java代码替换TabHost中的drawableTop资源
在博客 http://blog.csdn.net/jueblog/article/details/11837445 中的Tab选项卡中, 点击相应的Tab选项,图标没有发生改变. 这些资源图片也没有尽 ...
- Java动态调用类中方法
在Java中,调用类的方法有两种方式:对于静态方法可以直接使用类名调用,对于非静态方法必须使用类的对象调用.反射机制提供了比较另类的调用方式,可以根据需要指定要调用的方法,而不必在编程时确定.调用的方 ...
- Java 动态向 JTable 中添加数据
import java.awt.Toolkit; import javax.swing.SwingUtilities; import javax.swing.UIManager; import jav ...
- java.util.ComparableTimSort中的sort()方法简单分析
TimSort算法是一种起源于归并排序和插入排序的混合排序算法,设计初衷是为了在真实世界中的各种数据中能够有较好的性能. 该算法最初是由Tim Peters于2002年在Python语言中提出的. T ...
- java获取properties配置文件中某个属性最简单方法
假如我想获取src目录下sysConfig.properties中的uploadpath属性的值 方法如下所示: private static final ResourceBundle bundle ...
随机推荐
- JAR包
1, 使用JAR文件 jar文件的全称是Java Archive File,意思就是Java档案文件,通常jar文件是一种压缩文件,与常见的ZIP压缩文件兼容,通常也被称为jar包,j ...
- Lotus防病毒与数据备份案例
Lotus防病毒与数据备份案例 上文(http://chenguang.blog.51cto.com/350944/1334595)中我们已安装好了Domino服务器,这节里我们需要考虑安全解决方案, ...
- Duilib扩展《01》— 双击、右键消息扩展
用过duilib的可能会发现,duilib中有些控件没能很好的区分左键.右键等消息.所以根据实际需要,我们需要进行相关区分处理,或者自行扩展. 一. 左键.右键消息区分 我们以CListUI控件来分析 ...
- I/O系统,多线程、图形用户界面编程
多线程 进程与线程区别: 进程需要分配独立的内存空间:线程在同一内存空间中工作,可以共享同一块内存和系统资源 与Java相关的API: 1)Thread类 方法:start()启动: urn() : ...
- b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释
继续上篇,上篇里忘记了也很重要的前端部分,今天的网站基本上是以一个启示页,然后少量的整页切换,大量的浏览器后台调用web服务局部.动态更新页面显示状态这种方式在运作的,从若干年前简单的ajax流行起来 ...
- Bypass pattern lock on Sony Xperia Z2 and backup all data
Yesterday she came to me with a Sony Xperia Z2 D6503. Guess what? She forgot the pattern so she coul ...
- 1Android系统移植与驱动开发概述
1.Android系统架构分为四层,从下至上依次为Linux内核层,C/C++代码库.Android SDK API.应用程序,要熟悉每一层的内容以及功能: 2.Android移植分为应用移植和系统移 ...
- EasyUI datagrid 复杂表头处理
1:表头固定(前台写) 参照官方:http://www.jeasyui.net/demo/334.html 效果图: 源代码如下: <!DOCTYPE html> <html> ...
- 3D模型文件读写.Net SDK
AnyCAD .Net/C++ SDK支持多种3D/2D文件格式,比如BREP.STEP.IGES.STL.DXF.3DS.OBJ.FBX.SKP.IFC.DAE……等,根据使用场景提供不同的API. ...
- Hive[2] 基础介绍
2.3 Hive 内部介绍: P44 $HIVE_HOME/lib 下的 jar 文件是具体的功能部分:(CLI模块) 其它组件,Thrift 服务,可以远程访问其他进程功能:也有使用 JDBC 和 ...