zoukankan      html  css  js  c++  java
  • 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动态解析类.

  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/zolo/p/5849242.html
Copyright © 2011-2022 走看看