如何理解"Every Class object contains a reference to the ClassLoader that defined it. "?
How to understand "Every Class object contains a reference to the ClassLoader that defined it. "?
我知道我可以通过以下方式获得 class 的 classloader
xxxclass.class.getClassLoader()
,但是 xxxclass
到底在哪里
保留其 classloader 的引用,谁定义了它?
例如
public class ClassA {
System.out.println("I am class A");
}
我在 ClassA
中没有看到任何关于 classloader 参考的线索。然而,
我可以使用 ClassA
的 classloader
ClassA.class.getClassLoader()
.
ClassA.class.getClassLoader()
是如何工作的?
如果您查看 java.lang.Class 的源代码,您会发现它委托给了一个名为 getClassLoader0 的本机方法。因此,实现细节取决于 JVM。
我不是这方面的专家,但我想这可能允许垃圾收集通过在 Java 中没有引用循环来工作。
如果这样写:
public class Ball {
private Person thrower;
public Ball(Person thrower) {
this.thrower = thrower;
}
public Person getThrower() {return thrower;}
}
那么每个 Ball
对象都包含对抛出它的 Person
的引用,对吗?
类似地,Class
class 有这样的东西:(尽管我没有展示 classLoader
是如何分配的)
public class Class {
... other stuff ...
private ClassLoader classLoader;
public ClassLoader getClassLoader() {return classLoader;}
... other stuff ...
}
因此每个 Class
对象都有一个对加载它的 ClassLoader
的引用。
在您的示例中,ClassA
不是 Class
对象,因此该语句不适用于它。它适用于ClassA.class
,是一个Class
对象(或至少指一个对象)。
出现在 ClassLoader
文档中的句子是:
Every Class
object contains a reference to the ClassLoader that defined it.
注意到两个 link 了吗?他们告诉你的是文档指的是 Class
对象,而不是 class ClassA
.
的普通对象
您在 Java 中定义的每个 class 都有一个与之关联的 Class
对象,这使您可以在元级别中查看该 class。也就是说,将 class 本身视为一个对象,将其作为参数传递,对其使用反射等
如您所见,访问 Class
对象的一种方法是使用 ClassA.class
。如果您引用了 ClassA
:
类型的对象
ClassA myObj = new ClassA();
然后你可以使用myObj.getClass()
获得Class
对象。
因此 myObj
对象中没有对 ClassLoader
的引用,仅在其关联的 Class
对象中。
现在,另一个 link 告诉您如何在拥有 Class
对象后获取对 ClassLoader
对象的引用 - 通过 getClassLoader()
方法。
现在,如果您查看 Class
class 的源代码,您将看到:
@CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
所以它调用 getClassLoader0()
来获取 class 加载程序。它的来源是:
native ClassLoader getClassLoader0();
即class加载器引用实际上是这个Javaclass的原生结构的一部分,使用Java语言是看不到的工具。然而,它存在于那里,并且可以通过上述方法使用。
事实上,在这种情况下并没有那么简单。
(或者至少,它 是 没那么简单,直到最近的更新)
Java 是一种非常高级的语言,而 JVM 是相当复杂的野兽,它(幸运的是!)隐藏了许多您在使用高级语言时不想关心的细节级,面向对象的语言。
正如其他答案中已经指出的那样,Class#getClassLoader()
方法委托给 private native
方法 getClassLoader0()
。通常,您根本不知道(也不应该关心)私有 native
方法的作用。
但感谢开源 JDK,可以追踪此方法调用的路径(这里,对于 JDK8 的最新版本):
Class
is bound to JVM_GetClassLoader
的原生getClassLoader0
方法
JVM_GetClassLoader
方法最终calls Klass::class_loader()
- 仅
Klass::class_loader()
方法returns the result of ClassLoaderData::class_loader()
ClassLoaderData::class_loader()
方法终于returns the field that you are looking for
但是,请注意 this has changed in a recent commit of the JDK9:现在,ClassLoader
作为私有实例字段存储在 Class
class 中,以提高性能。
我知道我可以通过以下方式获得 class 的 classloader
xxxclass.class.getClassLoader()
,但是xxxclass
到底在哪里 保留其 classloader 的引用,谁定义了它? 例如public class ClassA { System.out.println("I am class A"); }
我在
ClassA
中没有看到任何关于 classloader 参考的线索。然而, 我可以使用ClassA
的 classloaderClassA.class.getClassLoader()
.ClassA.class.getClassLoader()
是如何工作的?
如果您查看 java.lang.Class 的源代码,您会发现它委托给了一个名为 getClassLoader0 的本机方法。因此,实现细节取决于 JVM。
我不是这方面的专家,但我想这可能允许垃圾收集通过在 Java 中没有引用循环来工作。
如果这样写:
public class Ball {
private Person thrower;
public Ball(Person thrower) {
this.thrower = thrower;
}
public Person getThrower() {return thrower;}
}
那么每个 Ball
对象都包含对抛出它的 Person
的引用,对吗?
类似地,Class
class 有这样的东西:(尽管我没有展示 classLoader
是如何分配的)
public class Class {
... other stuff ...
private ClassLoader classLoader;
public ClassLoader getClassLoader() {return classLoader;}
... other stuff ...
}
因此每个 Class
对象都有一个对加载它的 ClassLoader
的引用。
在您的示例中,ClassA
不是 Class
对象,因此该语句不适用于它。它适用于ClassA.class
,是一个Class
对象(或至少指一个对象)。
出现在 ClassLoader
文档中的句子是:
Every
Class
object contains a reference to the ClassLoader that defined it.
注意到两个 link 了吗?他们告诉你的是文档指的是 Class
对象,而不是 class ClassA
.
您在 Java 中定义的每个 class 都有一个与之关联的 Class
对象,这使您可以在元级别中查看该 class。也就是说,将 class 本身视为一个对象,将其作为参数传递,对其使用反射等
如您所见,访问 Class
对象的一种方法是使用 ClassA.class
。如果您引用了 ClassA
:
ClassA myObj = new ClassA();
然后你可以使用myObj.getClass()
获得Class
对象。
因此 myObj
对象中没有对 ClassLoader
的引用,仅在其关联的 Class
对象中。
现在,另一个 link 告诉您如何在拥有 Class
对象后获取对 ClassLoader
对象的引用 - 通过 getClassLoader()
方法。
现在,如果您查看 Class
class 的源代码,您将看到:
@CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
所以它调用 getClassLoader0()
来获取 class 加载程序。它的来源是:
native ClassLoader getClassLoader0();
即class加载器引用实际上是这个Javaclass的原生结构的一部分,使用Java语言是看不到的工具。然而,它存在于那里,并且可以通过上述方法使用。
事实上,在这种情况下并没有那么简单。
(或者至少,它 是 没那么简单,直到最近的更新)
Java 是一种非常高级的语言,而 JVM 是相当复杂的野兽,它(幸运的是!)隐藏了许多您在使用高级语言时不想关心的细节级,面向对象的语言。
正如其他答案中已经指出的那样,Class#getClassLoader()
方法委托给 private native
方法 getClassLoader0()
。通常,您根本不知道(也不应该关心)私有 native
方法的作用。
但感谢开源 JDK,可以追踪此方法调用的路径(这里,对于 JDK8 的最新版本):
Class
is bound toJVM_GetClassLoader
的原生JVM_GetClassLoader
方法最终callsKlass::class_loader()
- 仅
Klass::class_loader()
方法returns the result ofClassLoaderData::class_loader()
ClassLoaderData::class_loader()
方法终于returns the field that you are looking for
getClassLoader0
方法
但是,请注意 this has changed in a recent commit of the JDK9:现在,ClassLoader
作为私有实例字段存储在 Class
class 中,以提高性能。