1.使用序列化反序列化破坏单例模式
//先写一个静态内部类的方式,然后用序列化来破解
import java.io.Serializable;
public class Singleton implements Serializable {
private Singleton(){}
private static class SingletonHolder{
private static final Singleton INTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INTANCE;
}
}
破解方法,主旨思想就是先把类的对象写到文件中,然后读两次,发现一个问题就是两次读到的对象不一样,说明生成了多个不一样的对象,单例模式被破坏了。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//利用序列化来破坏单例模式
public class Client {
public static void main(String[] args) throws Exception {
// writeObject2File();
readObjectFromFile();
readObjectFromFile();
}
// 实现两个方法
// 1.写,向指定文件写入数据(也就是单例的对象)要传输对象文件就要先对对象的所属类序列化 在这里就要先给Singleton类先加上implement Serializable
public static void writeObject2File() throws Exception {
// 先获取到单例的对象
Singleton singleton = Singleton.getInstance();
// 然后创建输出流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\1\\a.txt"));
// 文件写出
oos.writeObject(singleton);
// 释放资源
oos.close();
}
// 2.写 从文件中读取对象
public static void readObjectFromFile()throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\1\\a.txt"));
Singleton singleton = (Singleton) ois.readObject();
System.out.println(singleton);
ois.close();
}
}
结果
2.使用反射破坏单例模式
//测试使用反射破坏单例模式
public class Client {
public static void main(String[] args) throws Exception {
// 先获取Singleton的字节码对象
Class clazz = Singleton.class;
// 获取无参构造方法
Constructor cons = clazz.getDeclaredConstructor();
// 取消访问检查
cons.setAccessible(true);
// 创建Singleton对象
Singleton s1 = (Singleton) cons.newInstance();
Singleton s2 = (Singleton) cons.newInstance();
System.out.println(s1==s2);
}
}
3.反序列化的解决办法就是在Singleton类中添加readResolve()方法,在反序列化时被反射调用,如果定义了这个方法,就返回这个方法的值,如果没有定义,就返回新new出来的对象。
//先写一个静态内部类的方式,然后用序列化来破解他
import java.io.Serializable;
public class Singleton implements Serializable {
private Singleton(){}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
public Object readResolve(){
return SingletonHolder.INSTANCE;
}
}
4.反射破解单例的解决办法
//写一个静态内部类的方式的单例 然后用反射来破解
public class Singleton {
private static boolean flag= false;
// 首先私有化构造函数
private Singleton(){
synchronized (Singleton.class){
if(flag){
throw new RuntimeException("不能创建多个对象");
}
flag = true;
}
}
// 定义一个静态内部类
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
// 给出访问对象的方法
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}