Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用自定义类装入器进行静态变量隔离_Java - Fatal编程技术网

Java 使用自定义类装入器进行静态变量隔离

Java 使用自定义类装入器进行静态变量隔离,java,Java,我有这个密码 MyClassloader loader = new MyClassloader(); Class c = loader.loadClass(classToLoad); Thread.currentThread().setContextClassLoader(loader); MyClass myClass = (MyClass) c.newInstance(); 类加载器代码是 public MyClassload

我有这个密码

        MyClassloader loader = new MyClassloader();
        Class c = loader.loadClass(classToLoad);
        Thread.currentThread().setContextClassLoader(loader);
        MyClass myClass = (MyClass) c.newInstance();
类加载器代码是

public MyClassloader) throws IOException {
    super(Thread.currentThread().getContextClassLoader());
}
类加载工作正常问题在于静态变量没有被隔离,因此如果在
MyClass
中设置了一个静态变量,那么所有其他
MyClass
实例都会得到相同的值


在什么情况下可以隔离静态变量?

您将委托给同一类加载器。所以你看不出有什么不同

你该怎么办在类加载器中实现类加载,不要只是委托。例如,从URLClassLoader继承类加载器,并正确初始化它(这意味着,为类加载器提供一个有效的类路径来初始化它)。然后,您将看到,您的类加载器加载的类与标准类加载器加载的类并不相同,因此,它们的静态成员将不同

通常,上下文类加载器是从URLClassLoader继承的,因此您不必花费太多时间为其配置类路径。相反,要初始化类加载器,可以重用上下文类加载器的URL,如下所示:

public class MyIndependentClassLoader extends URLClassLoader {
  public MyIndependentClassLoader(){
    super(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs());
  }
}
现在可以使用类加载器检查静态成员

这种方法和最初的方法有什么区别

你知道类也是对象(特殊类型):它们有自己的成员变量,
name,serialVersionId,annotationData等,还有自己的方法,
newInstance(),getFields(),getMethods(),

Class c = loader.loadClass("com.my.package.MyClassX");
您将获得
c
,这是一个描述加载的类“some class name”的对象。这个
c
不仅允许创建实例,还可以保存所有静态成员

在代码中:类加载器不会直接加载类。相反,它将委托给上下文类加载器。这就是为什么要比较两个加载的类

Class c = loader.loadClass("com.my.package.MyClassX");
Class ct = Thread.currentThread().getContextClassLoader().loadClass("com.my.package.MyClassX");
您将看到,
c
ct
是同一个对象。如果您调用
c.equals(ct)
,它将为您提供
true
。如果你调用
c==ct
,它也会给你
true
。这意味着,这是同一个类实例。这就是为什么——当然——如果你检查静态变量,它们将是相同的。如果在一个类中更改静态变量,它也将在另一个类中更改,反之亦然

在我的代码中:本质上的区别是,类加载器自己加载类。它不会将其委托给其他类加载器。我建议从
URLClassLoader
扩展它,以简化我们的实现(否则您必须从头开始实现处理类路径、目录、jar、可见性、缓存等)。为了避免一步一步地添加每个类路径元素,我建议使用相同的类路径(相同的目录列表、JAR等)作为上下文类装入器。因此,我们的类加载器将能够找到与上下文类加载器相同的类。 现在检查这个类加载器加载的类。让我们称之为
ci

Class ci = new MyIndependentClassLoader().loadClass("com.my.package.MyClassX");

如果比较这些类,您将看到
c.equals(ci)
给出
false
。也就是说,它们是不同的。这就是为什么他们也有独立的静态成员。如果在一个类中更改静态成员,
ct
,则在另一个类中它不会更改,
ci
,反之亦然。

可能重复@MohammedHousseynTaleb该问题与此问题相反。在您的示例中,执行
扩展类加载器
扩展URLClassLoader
有什么区别?原因是简化类的加载。当然,不需要使用URLClassLoader就可以做到这一点。然后你必须实现类的解析/加载(你的类加载器将如何加载X类的字节码?)我的意思是我不明白你的代码和我的代码在“静态变量隔离”方面有什么区别?简单地说:你的类加载器返回与上下文类加载器相同的类实例。没有隔离,因为这是同一个类实例:内存中的同一个位置、相同的静态成员等。要实现隔离,不要委托给另一个类装入器,而是“亲自”直接装入类。然后您将得到两个不同的类实例,它们具有完全独立的静态成员。我在上面的回答中添加了更多细节。您的类加载器只是上下文类加载器的“捷径”。它提供与上下文类加载器完全相同的结果。我实际的类加载器代码是
公共类MyClassloader Extendes类加载器{public MyClassloader()抛出IOException{super(Thread.currentThread().getContextClassLoader());}
,您能指出这与您的示例有什么不同吗?与你的例子相反,这不是授权。