多个静态变量实例

问题描述 投票:12回答:4

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

基本上,我正在尝试编写Stephen C在this answer中提到的代码。

这是我的课程:

custom class loader.Java

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

Test.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.如何让代码创建我的静态变量的两个实例?

注意:我这样做只是为了实验和学习 - 但我很想知道是否可以有任何真实的应用。

java reflection static classloader
4个回答
7
投票

看起来类似“A”类是由父类加载器加载的,而不是你的CustomClassLoader(因为你调用了super.loadClass)。

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

为可怕的小屋道歉,我假设单个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或类似的东西......


6
投票

你的问题是new CustomClassLoader()创建了一个类加载器,它将尝试将加载类委托给系统类加载器 - 对于这两个实例来说都是一样的。您的CustomClassLoader甚至无法加载类本身。尝试使用URLClassLoader并传递null作为父母。

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


0
投票

如果你查看ClassLoader源甚至是javadoc,你会发现默认情况下ClassLoader委托给默认的系统ClassLoader,它实际上是在实例之间共享的。


0
投票

我有同样的问题(集成测试)并尝试使用@Michael Borgwardt方法。这里有一些示例代码:

URLClassLoader classLoader1 = new URLClassLoader(new URL[]{new URL("file:///path/to/jar/my-classes.jar")}, null);
URLClassLoader classLoader2 = new URLClassLoader(new URL[]{new URL("file:///path/to/jar/my-classes.jar")}, null);

// Load with classLoader1
Class<?> myClass1 = classLoader1.loadClass("MyClass");
Constructor<?> constructor1 = myClass1.getConstructor();
Object instance1 = constructor1.newInstance();

// Load with classLoader2
Class<?> myClass2 = classLoader2.loadClass("MyClass");
Constructor<?> constructor2 = myClass2.getConstructor();
Object instance2 = constructor2.newInstance();

// Load with system classloader
MyClass myClass = new MyClass();

// ...
© www.soinside.com 2019 - 2024. All rights reserved.