难道对象的.class属性总是返回同一个实例?(Does .class property of an

2019-10-20 02:25发布

我是否同步在同一个对象实例在下面的代码? 我能做到安全?

Class Sync {}

Class A implements Runnable {
  void run() {
    synchronized(Sync.class) {
      System.out.println("I am synchronized");
    }
  }
}

Class B implements Runnable {
  void run() {
    synchronized(Sync.class) {
      System.out.println("I too am synchronized");
    }
  }
}

Answer 1:

你必须做的加载之间的区别Class解析 Class

文字类和特殊方法Class.forName(…)比的方法不同ClassLoader.loadClass(…) 虽然ClassLoader有可能实现以奇怪的方式,例如通过在每个调用返回不同的情况下后者,JVM将解决每个班级每个上下文一次,以及记住结果。

重要的一点是, 如果一个符号引用的决议可以被重定向,一个static final变量将没有帮助。 如果你有相同的两个实例Class在JVM中,两个不同版本的的static final字段会存在的。

有一个接一个一个之间的映射Class实例和每个类数据的JVM。


举出几个官员的话:

JVMSpec§5.3.2。 载入使用用户定义的类装载器

...首先,Java虚拟机确定是否L具有已被记录为N.表示如果是这样的类或接口的初始化加载器,这个类或接口是C,且无类的创建是必要的。 ...

...

JVMSpec§5.3.5。 从一个类文件表示派生一个类

下面的步骤被用于导出一类对象使用装载机L从在类文件格式声称的表示由N个表示的非数组类或接口℃。

(1)首先,Java虚拟机确定是否已经记录了L是由N表示的类或接口的初始化加载器。如果是这样,这个创作的尝试是无效的,并装载抛出的LinkageError类。

...

(5)Java虚拟机标记C作为具有L-作为其限定类加载器和记录,L是C的初始化加载器(§5.3.4)。

如§5.3.5指出,最重要的一点是,每一个ClassLoader可以定义每个独特的符号名称最多一个班。 它可能会通过委托给不同的装载机返回不同的实例,但那么他们将被铭记为定义加载器。 和解决从引用时,JVM会要求定义加载Class到另一个Class 。 或跳过要求它作为§当5.3.2状态Class对于给定的名称和装载机已经存在。



Answer 2:

根据JLS 8.4.3.6上同步Class.forName("name")因此, .class是做正确的事情,它会工作-在同一个班级,至少。 此外,所有静态synchronized方法是在同步.class 。 由于它在JLS说,下面几乎是相同的:

class Test {
    int count;
    synchronized void bump() {
        count++;
    }
    static int classCount;
    static synchronized void classBump() {
        classCount++;
    }
}

class Test {
    int count;
    void bump() {
        synchronized (this) { count++; }
    }
    static int classCount;
    static void classBump() {
        try {
            synchronized (Class.forName("Test")) {
                classCount++;
            }
        } catch (ClassNotFoundException e) {}
    }
}

然而,随着JLS 12.2状态,现在还不能确定时.class由不同类调用,因为此调用依赖于类装载器:

乖巧的类加载器维护这些属性:

由于相同的名字,一个良好的类加载器应该总是返回相同的类对象。

如果一个类C的类装载程序L1代表装载到另一个加载器L2,则对于发生的直接超类或C中的一个直接超接口,或作为现场的在C型,或作为一个类型的任何类型T在C语言的方法或构造的形式参数,或在C的方法的返回类型,L1和L2应返回相同类的对象。

一个恶意的类加载器可能违反这些属性。 但是,它不能破坏类型系统的安全性,因为对这种Java虚拟机警卫。

所以,如果你使用的是标准的Java类加载器 - 你应该罚款。 如果您使用的是一些自定义的类装载器,但是,你应该注意的错误。



Answer 3:

只有当它们具有相同的类加载器。

如果你有一个根类加载器和两个子类加载器的两个子类加载器(即的URLClassLoader)加载的.class每一个classloader一次,他们将工作异步。

加载Sync根类加载器将被保存。



文章来源: Does .class property of an object always return the same instance?