静态变量的多个实例

2022-09-04 21:13:52

我正在尝试使用不同的类装入器来加载特定的类,并查看该类中的静态变量是否可以具有不同的实例。

基本上,我正在尝试为Stephen C在这个答案中提到的内容编写代码。

这是我的课程:

CustomClassLoader.java

class CustomClassLoader extends ClassLoader
{
    public Class loadClass(String classname)  throws ClassNotFoundException {
        return super.loadClass(classname, true);
    }
}

测试.java(包含驱动程序)

class Test {
        public static void main(String[] args) throws Exception {
                CustomClassLoader c1 = new CustomClassLoader();
                CustomClassLoader  c2 = new CustomClassLoader();
                Class m1, m2;

                m1 = c1.loadClass("A");
                m2 = c2.loadClass("A");

                m1.getField("b").set(null, 10);

                System.out.println(m1.getField("b").get(null));
                System.out.println(m2.getField("b").get(null));
        }

}

A.java(包含静态变量)

class A {
        public static int b = 5;
}

当我运行 Test 类时,我得到以下输出:

$ java Test
10
10

我预计输出是 10 和 5。如何使代码创建静态变量的两个实例?

注意:我这样做只是为了实验和学习 - 但我有兴趣知道是否有任何现实世界的应用。


答案 1

看起来类“A”是由父类装入器而不是由 CustomClassLoader 装入的(因为您调用 super.loadClass)。

以下未经测试的修正应允许您使用自己的类装入器定义“A”类(同时将其他所有内容委托给父装入器)。

为可怕的bodge道歉,我假设单个inputStream.read()将读取所有内容!但你可以希望明白我的意思。

    public Class loadClass(String classname)  throws ClassNotFoundException {
    if (classname.equals("A")) {
        InputStream is = getResourceAsStream("A.class");
        byte[] bodge = new byte[8192];  // Should read until EOF
        try {
            int len = is.read(bodge);
            return defineClass("A", bodge, 0, len);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return super.loadClass(classname, true);
}

然后你可能会得到ClasscastExceptions或类似的东西......


答案 2

您的问题是创建了一个类装入器,该类装入器将尝试将装入类委托给系统类装入器 - 并且对于两个实例都是相同的。您甚至无法自己加载类。尝试使用 和 传递 作为父级。new CustomClassLoader()CustomClassLoaderURLClassLoadernull

至于现实世界的应用程序:对于Java Web容器和应用程序服务器来说,允许不同的应用程序彼此完全隔离,即使它们可能使用许多相同的类,这一点至关重要。


推荐