在ClassLoader
上调用loadClass()
时,ClassLoader
是否首先检查该类是否已加载,还是立即将此检查委派给其父ClassLoader
?
Java API说:
当请求查找类或资源时,ClassLoader实例会在尝试查找类或资源本身之前,将对类或资源的搜索委托给其父类加载器。
但是在 Java Reflection in Action 一书中有关于类加载器的特定章节,其中说:
类加载器调用findLoadedClass来检查类是否已经加载。如果类加载器没有找到加载的类,则在父类加载器上调用loadClass。
哪个是对的?
答案 0 :(得分:17)
正确的类加载器实现将:
ClassLoader.loadClass的默认实现类似于:
protected synchronized Class<?> loadClass(String name, boolean resolve) {
// First, check if this class loader has directly defined the class or if the
// JVM has initiated the class load with this class loader.
Class<?> result = findLoadedClass(name);
if (result == null) {
try {
// Next, delegate to the parent.
result = getParent().loadClass(name);
} catch (ClassNotFoundException ex) {
// Finally, search locally if the parent could not find the class.
result = findClass(ex);
}
}
// As a remnant of J2SE 1.0.2, link the class if a subclass of the class
// loader class requested it (the JVM never calls the method,
// loadClass(String) passes false, and the protected access modifier prevents
// callers from passing true).
if (resolve) {
resolveClass(result);
}
return result;
}
某些类加载器实现将委托给其他非父类加载器(OSGi,例如,根据包委托给类加载器的图形),并且一些类加载器实现将在委派之前在本地类路径中查找类
答案 1 :(得分:2)
Java API是正确的。
当要求找到一个班级或 资源,一个ClassLoader实例 委托搜索课程或 资源到其父类加载器 在尝试找到班级之前 资源本身。
来自Java Classloading Mechanism -
在加载类时,类加载器首先将对类的搜索“委托”到其父类加载器,然后再尝试查找类本身。
答案 2 :(得分:2)
这两个陈述并非完全相互排斥。如果父ClassLoader以前未能找到Class,则Class将仅存在于当前ClassLoader的已加载类集中。所以,
当要求查找(描述的外部数据)类或 资源,一个ClassLoader实例 委托搜索(描述的外部数据)类或 资源到其父类加载器 在尝试查找(描述的外部数据)类或 资源本身。
如果它知道它的父节点找不到类但它可以(如先前加载类所示)
,它不会阻止它发生短路答案 3 :(得分:1)
这基本上是它的工作原理。你输入
Foo f = new Foo();
此时,类加载器将确定是否已加载Foo()
,即它在memory / perm gen中的位。如果已加载,则使用它。否则将其委托给父类加载器以尝试解析该类。从磁盘读取该类的位,然后加载到内存中。在下一个new Foo()
,现在可以在内存/已加载中找到该类。
答案 4 :(得分:0)
为了同意斯里兰卡的答案,它将始终委托给父母,而api是正确的。如果你正在玩类加载,这可能会让事情变得有点棘手,或者达到你想要的效果。我建议用最小的类路径启动jvm,然后使用自定义类加载器加载所有类,最简单的方法是使用URLClassloader或包装URLClassloader的复合对象,这样你就可以跟踪哪个类加载时和。
另外值得注意的是,如果C和D不是同一个类加载器 - 父子层次结构的一部分,则由类加载器C加载的类A!=由类加载器C加载的类A.
答案 5 :(得分:0)
在这种情况下还应该注意另外一个问题。 API文档说:
。的方法和构造 由类加载器创建的对象可以 参考其他课程。确定 提到的类,Java 虚拟机调用loadClass 类加载器的方法 最初创建了这个类。
意味着引用类的网络由同一个类加载器加载。