如何用ClassLoader破坏单例模式?求多类加载器生成实例示例
多类加载器破坏单例模式的实现示例
你当前的代码无法创建多个单例实例,核心原因是自定义类加载器默认会委托父类加载器(系统类加载器)加载类,所以cl1和cl2最终拿到的是同一个SingletonObject类对象,自然只能得到一个单例实例。
要实现多类加载器破坏单例,必须让自定义类加载器不委托父类,自行加载类的字节码,这样每个类加载器都会生成独立的Class对象,每个Class对象的静态变量ref都是独立的,从而创建多个实例。
1. 修改后的自定义类加载器
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; public class CustomClassLoader extends ClassLoader { // 类文件的根路径,需根据实际编译后的class文件路径调整 private String classPath; public CustomClassLoader(String classPath) { this.classPath = classPath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { try { // 将类名转换为class文件路径 String fileName = name.replace(".", "/") + ".class"; // 读取类文件字节码 FileInputStream fis = new FileInputStream(classPath + fileName); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { bos.write(buffer, 0, len); } byte[] classBytes = bos.toByteArray(); fis.close(); bos.close(); // 定义类并生成Class对象 return defineClass(name, classBytes, 0, classBytes.length); } catch (IOException e) { throw new ClassNotFoundException(name, e); } } }
2. 单例类(保持原有逻辑不变)
public class SingletonObject { private static SingletonObject ref; private SingletonObject() {} public static SingletonObject getSingletonObject() { if (ref == null) { ref = new SingletonObject(); System.out.println("创建新实例: " + ref); } else { System.out.println("返回已有实例: " + ref); } return ref; } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }
3. 测试主类
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws Exception { // 编译后的class文件所在根路径,例如项目的target/classes目录 String classPath = "target/classes/"; CustomClassLoader cl1 = new CustomClassLoader(classPath); CustomClassLoader cl2 = new CustomClassLoader(classPath); Class<?> singClass1 = cl1.loadClass("SingletonObject"); Class<?> singClass2 = cl2.loadClass("SingletonObject"); // 验证两个Class对象是否独立 System.out.println("singClass1 和 singClass2 是否为同一对象: " + (singClass1 == singClass2)); Method getInstance1 = singClass1.getDeclaredMethod("getSingletonObject"); Method getInstance2 = singClass2.getDeclaredMethod("getSingletonObject"); Object singleton1 = getInstance1.invoke(null); Object singleton2 = getInstance2.invoke(null); // 验证两个实例是否独立 System.out.println("singleton1 和 singleton2 是否为同一对象: " + (singleton1 == singleton2)); } }
运行结果说明
运行后会输出类似内容:
singClass1 和 singClass2 是否为同一对象: false 创建新实例: SingletonObject@6d06d69c 创建新实例: SingletonObject@7852e922 singleton1 和 singleton2 是否为同一对象: false
这证明两个类加载器加载了独立的SingletonObject类,各自创建了独立的单例实例,成功破坏了单例模式。
内容的提问来源于stack exchange,提问作者Jenny Lian
相关产品推荐
相关产品推荐

