我知道我可以得到一个类的类加载器
xxxclass.class.getClassLoader()
,但xxxclass
到底在哪里
持有定义它的类加载器的引用?
例如
public class ClassA {
System.out.println("I am class A");
}
我在ClassA
中没有看到任何关于类加载器引用的线索。然而,
我可以通过使用获得ClassA
的类加载器
ClassA.class.getClassLoader()
。
ClassA.class.getClassLoader()
如何运作?
答案 0 :(得分:3)
ClassLoader
文档中出现的句子是:
请注意这两个链接?他们告诉你的是文档引用了Class
对象,而不是类ClassA
的普通对象。
您在Java中定义的每个类都有一个与之关联的Class
对象,它允许您在元级别中查看该类。也就是说,将类本身视为一个对象,将其作为参数传递,对其使用反射等。
正如您所注意到的,访问Class
对象的一种方法是使用ClassA.class
。如果您引用了ClassA
类型的对象:
ClassA myObj = new ClassA();
然后,您可以使用Class
获取myObj.getClass()
对象。
因此,ClassLoader
对象中没有对myObj
的引用,仅在其关联的Class
对象中。
现在,另一个链接告诉您如何通过ClassLoader
方法获得Class
对象后getClassLoader()
对象的引用。
现在,如果你查看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()
来获取类加载器。它的来源是:
native ClassLoader getClassLoader0();
也就是说,类加载器引用实际上是此Java类的本机结构的一部分,并且无法使用Java语言工具。然而,它存在于那里,并可通过上述方法获得。
答案 1 :(得分:1)
如果你这样写:
public class Ball {
private Person thrower;
public Ball(Person thrower) {
this.thrower = thrower;
}
public Person getThrower() {return thrower;}
}
然后每个Ball
对象都包含对投放它的Person
的引用,对吗?
同样,Class
类也有类似内容:(虽然我没有说明如何分配classLoader
)
public class Class {
... other stuff ...
private ClassLoader classLoader;
public ClassLoader getClassLoader() {return classLoader;}
... other stuff ...
}
所以每个Class
对象都引用了加载它的ClassLoader
。
在您的示例中,ClassA
不是Class
对象,因此该语句不适用于它。它 适用于ClassA.class
一个Class
对象(或至少指一个)。
答案 2 :(得分:1)
事实上,在这种情况下并不是那么简单。
(或至少, 并非如此简单,直到最近的更新)
Java是一种非常高级的语言,JVM是一个相当复杂的野兽,幸运的是,它隐藏了许多你不想在使用高级,面向对象时需要关注的细节。语言。
正如其他答案中已经指出的那样,Class#getClassLoader()
方法委托给private native
方法getClassLoader0()
。通常,您根本不知道(并且不应该关心)私有native
方法的作用。
但是由于开源JDK,人们可以跟踪这个方法调用的路径(这里是最新版本的JDK8):
getClassLoader0
is bound to JVM_GetClassLoader
Class
方法
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
类中的私有实例字段,以提高性能。
答案 3 :(得分:0)
如果查看java.lang.Class的源代码,它似乎委托给一个名为getClassLoader0的本机方法。因此,实现细节归结为JVM。
我不是这方面的专家,但我想这可能会让垃圾收集工作,因为没有Java中的参考周期。