You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:55:37