多个静态变量实例

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

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

这是我的课程:

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

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

看起来类“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或类似的东西……

您的问题是new CustomClassLoader()创建了一个类加载器,它将尝试将加载类委托给系统类加载器 – 这对于两个实例都是相同的。 您的CustomClassLoader甚至无法自行加载类。 尝试使用URLClassLoader并将null作为父级传递。

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

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

我有同样的问题(集成测试)并尝试使用@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(); // ...