[英]Does .class property of an object always return the same instance?
我是否在以下代码中对同一对象实例进行同步? 我可以安全吗?
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");
}
}
}
根据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
是何时由不同的类调用的,因为此调用取决于类加载器:
行为良好的类加载器保留以下属性:
给定相同的名称,好的类加载器应始终返回相同的类对象。
如果类加载器L1将类C的加载委托给另一个加载器L2,则对于任何类型T,它作为C的直接超类或直接超接口,或C中的字段类型或a的类型出现C中方法或构造函数的形式参数,或C中方法的返回类型,L1和L2应该返回相同的Class对象。
恶意的类加载器可能会违反这些属性。 但是,它不能破坏类型系统的安全性,因为Java虚拟机对此有所防范。
因此,如果您使用的是标准Java类加载器,则应该没问题。 但是,如果使用某些自定义类加载器,则应注意错误。
您必须在加载 Class
和解决 Class
之间进行区分。
类文字和特殊方法Class.forName(…)
与方法ClassLoader.loadClass(…)
。 虽然ClassLoader
可能以奇怪的方式实现后者,例如,通过在每次调用中返回不同的实例,但JVM将为每个上下文准确地解析每个类,并记住结果。
重要的一点是, 如果可以重定向符号引用的分辨率, 则 static final
变量也无济于事。 如果您的JVM中有两个相同Class
实例,那么它们的static final
字段也将存在两个不同的版本。
每个类数据在Class
实例和JVM之间存在一对一的映射。
引用一些官方用语:
JVMSpec第5.3.2节。 使用用户定义的类加载器加载
…首先,Java虚拟机确定L是否已被记录为由N表示的类或接口的启动加载器。如果是,则该类或接口为C,并且不需要创建类。 …
…
JVMSpec第5.3.5节。 从类文件表示形式派生一个类
以下步骤用于使用加载程序L从类文件格式的所谓表示中派生N表示的非数组类或接口C的Class对象。
(1)首先,Java虚拟机确定它是否已经记录了L是由N表示的类或接口的启动加载器。如果是,则此创建尝试无效,并且加载引发LinkageError。
…
(5)Java虚拟机将C标记为具有L作为其定义类加载器,并记录L是C的初始加载器(第5.3.4节)。
§5.3.5指出的重点是,每个ClassLoader
可以为每个唯一的符号名称最多定义一个类。 它可能通过委派给不同的加载程序来返回不同的实例,但是它们将被记住为定义加载程序。 并且,当从一个Class
到另一个Class
引用解析时,JVM将询问定义的加载器。 或跳过要求它作为§当5.3.2状态Class
对于给定的名称和装载机已经存在。
仅当它们具有相同的类加载器时。
如果您有一个根类加载器和两个子类加载器,则两个子类加载器(即URLClassLoader)每个类加载器都会加载一次.class,它们将异步工作。
根类加载器中的“加载Sync
”将被保存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.