对象的.class属性总是返回相同的实例吗? [英] Does .class property of an object always return the same instance?

查看:182
本文介绍了对象的.class属性总是返回相同的实例吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面的代码中在同一对象实例上同步?我可以安全吗?

  Class Sync {} 

A类实现Runnable {
void run(){
synchronized(Sync.class){
System.out.println(I am synchronized);
}
}
}

B类实现Runnable {
void run(){
synchronized(Sync.class){
System.out.println(I too am synchronize);
}
}
}


解决方案>

您必须区分加载 > 类 c

$ <$ p> $ <$ p $>不同于方法 ClassLoader.loadClass(...)。而 ClassLoader 可能以奇怪的方式实现后者,例如。通过在每次调用时返回不同的实例,JVM将根据上下文每次解析每个类,并记住结果。



重要的是, 如果符号引用的分辨率可以重定向, static final 变量也不会有帮助。如果在JVM中有两个相同的 Class 实例,它们的 static final 字段会有两个不同的版本



Class 实例和每个类数据的JVM之间存在一个一对一的映射。






列举几个官方词汇:


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



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



...



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



以下步骤用于为nonarray类或接口C派生一个Class对象,使用loader L



(1)首先,Java虚拟机确定它是否已经记录了L是类或接口的初始加载器如果是,则此创建尝试无效,并且加载会抛出LinkageError。



...



5)Java虚拟机将C标记为具有L作为其定义类加载器,并记录L是C的启动加载器(§5.3.4)。


§5.3.5指出的重要一点是每个 ClassLoader 可以每个唯一的符号定义最多一个类名称。它可能通过委托给不同的装载器返回不同的实例,但是它们将被记住为定义装载器。当解析从 Class 到另一个 Class 的引用时,JVM会询问 。或者跳过请求它作为§5.3.2状态,当给定的名称和加载程序已经存在 Class 时。


Am I synchronizing on the same object instance in the following code? Can I do it safely?

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");
    }
  }
}

解决方案

You have to make a distinction between Loading of a Class and Resolving a Class.

Class literals and the special method Class.forName(…) are different than the method ClassLoader.loadClass(…). While a ClassLoader might implement the latter in strange ways, e.g. by returning different instances on each call, the JVM will resolve each class exactly once per context and remember the result.

The important point is, if the resolution of a symbolic reference could be redirected, a static final variable would not help either. If you have two instances of the same Class in your JVM, two different version of their static final fields would exist as well.

There is a one-by-one mapping between a Class instance and the JVM per class data.


To cite a few official words:

JVMSpec § 5.3.2. Loading Using a User-defined Class Loader

… First, the Java Virtual Machine determines whether L has already been recorded as an initiating loader of a class or interface denoted by N. If so, this class or interface is C, and no class creation is necessary. …

JVMSpec § 5.3.5. Deriving a Class from a class File Representation

The following steps are used to derive a Class object for the nonarray class or interface C denoted by N using loader L from a purported representation in class file format.

(1) First, the Java Virtual Machine determines whether it has already recorded that L is an initiating loader of a class or interface denoted by N. If so, this creation attempt is invalid and loading throws a LinkageError.

(5) The Java Virtual Machine marks C as having L as its defining class loader and records that L is an initiating loader of C (§5.3.4).

The important point as pointed out by § 5.3.5 is that each ClassLoader can define at most one class per unique symbolic name. It might return different instances by delegating to different loaders but then they would be remembered as the defining loader. And the JVM will ask the defining loader when resolving references from a Class to another Class. Or skip asking it as § 5.3.2 states when a Class for a given name and loader already exists.

这篇关于对象的.class属性总是返回相同的实例吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆