jvm添加自定义dns实现过程示例
作者:supermassive
这篇文章主要为大家介绍了jvm添加自定义dns实现过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
引言
有一个常见的场景, 我们在开发过程中,要配置很多的本地host,以实现测试环境一些资源的访问,那么其它人参与进来开发的话,也得在自己电脑上配置,这样既麻烦,又容易出错。那么能不能把这些配置,写到project中去实现呢, 这样每个人本地的/etc/hosts文件中会很干净,可以随时clone启动调试而不需任何配置。答案是肯定的,那么接下来我们就使用java反射的方式来实现。
操作对象 java.net.InetAddress
我们主要操作的对象就是java.net.InetAddress,可以从源码中看到, 该类中有两个核心的变量cache和expirySet。
// mapping from host name to Addresses - either NameServiceAddresses (while // still being looked-up by NameService(s)) or CachedAddresses when cached private static final ConcurrentMap<String, Addresses> cache = new ConcurrentHashMap<>(); // CachedAddresses that have to expire are kept ordered in this NavigableSet // which is scanned on each access private static final NavigableSet<CachedAddresses> expirySet = new ConcurrentSkipListSet<>();
这里会有个疑问, 为啥还有个expirySet,这个问题也可以通过源码得到解决,即为了删除失效的条目。
解析
具体含义可以通过阅读注释进行理解。
// remove expired addresses from cache - expirySet keeps them ordered // by expiry time so we only need to iterate the prefix of the NavigableSet... long now = System.nanoTime(); for (CachedAddresses caddrs : expirySet) { // compare difference of time instants rather than // time instants directly, to avoid possible overflow. // (see System.nanoTime() recommendations...) if ((caddrs.expiryTime - now) < 0L) { // ConcurrentSkipListSet uses weakly consistent iterator, // so removing while iterating is OK... if (expirySet.remove(caddrs)) { // ... remove from cache cache.remove(caddrs.host, caddrs); } } else { // we encountered 1st element that expires in future break; } }
如何实现反射添加dns条目
接下来就是如何来实现反射添加dns条目了,本例中基于java17实现,其它版本会有相应的变化。
Class<?> cachedAddresses_Class = Class.forName("java.net.InetAddress$CachedAddresses"); Constructor<?> constructor = cachedAddresses_Class.getDeclaredConstructors()[0]; constructor.setAccessible(true); Object o = constructor.newInstance(host, toInetAddressArray(host, ip), Long.MAX_VALUE); Field cacheField = InetAddress.class.getDeclaredField("cache"); cacheField.setAccessible(true); ConcurrentMap<String, Object> cm = (ConcurrentMap<String, Object>) cacheField.get(null); cm.put(host, o); Field expirySetField = InetAddress.class.getDeclaredField("expirySet"); expirySetField.setAccessible(true); ConcurrentSkipListSet<Object> cs = (ConcurrentSkipListSet<Object>) expirySetField.get(null); cs.add(o);
这样的话, 就可以自己封装一下,比如dns条目都写在一个文件中, 编译打包的时候, 按profile配置决定是否加载。
以上就是jvm添加自定义dns实现过程示例的详细内容,更多关于jvm添加自定义dns的资料请关注脚本之家其它相关文章!