为什么ClassLoader的缓存是按升序检查的?
Why is ClassLoader's cache checked in ascending sequence?
为什么ClassLoader的缓存是从小到大检查的,而class-加载是从大到小的?
Java 中的类加载器基于三个原则工作:委托、可见性和唯一性。委托原则将 class 加载请求转发给父级 class 加载器,并且仅在父级无法找到或加载 class 时才加载 class。可见性原则让child class loader可以看到parent ClassLoader加载的所有classes,但是parent class loader看不到child加载的classes。唯一性原则允许只加载一次class,这基本上是通过委托实现的,并确保子类加载器不会重新加载已由父类加载的class。
换句话说here:
The class loaders in Java are organized in a tree. By request a class
loader determines if the class has already been loaded in the past,
looking up in its own cache. If the class is present in the cache the
CL returns the class, if not, it delegates the request to the parent.
If the parent is not set (is Null) or can not load the class and
throws a ClassNotFoundException the classloader tries to load the
class itself and searches its own path for the class file. If the
class can be loaded it is returned, otherwise a ClassNotFoundException
is thrown. The cache lookup goes on recursively from child to
parent, until the tree root is reached or a class is found in cache.
If the root is reached the class loaders try to load the class and
unfold the recursion from parent to child. Summarizing that we have
following order:
- Cache
- Parent
- Self
This mechanism ensures that classes tending to be loaded by class loaders nearest to the root.
这纯粹是效率问题。如果您忘记了缓存,class 加载顺序可确保 Java 系统 classes 始终优先于应用程序 classes 并且 class 可以只能由链中的一个 classloader 加载。所以没有 class 存在于多个缓存中,因此搜索缓存的顺序没有任何功能差异。
换句话说,您可以搜索引导加载程序缓存,然后是扩展 classloader 缓存,然后是系统 classloader 缓存,然后开始尝试加载 classes最终结果将完全相同。这样做将需要额外的 API 来搜索已加载的 class,并且不会带来什么好处,因为搜索缓存是一项非常快速的操作。
请注意,classes 可以由多个 classloader 加载,但如果它们位于 loader->parent 链中则不能。
为什么ClassLoader的缓存是从小到大检查的,而class-加载是从大到小的?
Java 中的类加载器基于三个原则工作:委托、可见性和唯一性。委托原则将 class 加载请求转发给父级 class 加载器,并且仅在父级无法找到或加载 class 时才加载 class。可见性原则让child class loader可以看到parent ClassLoader加载的所有classes,但是parent class loader看不到child加载的classes。唯一性原则允许只加载一次class,这基本上是通过委托实现的,并确保子类加载器不会重新加载已由父类加载的class。
换句话说here:
The class loaders in Java are organized in a tree. By request a class loader determines if the class has already been loaded in the past, looking up in its own cache. If the class is present in the cache the CL returns the class, if not, it delegates the request to the parent. If the parent is not set (is Null) or can not load the class and throws a ClassNotFoundException the classloader tries to load the class itself and searches its own path for the class file. If the class can be loaded it is returned, otherwise a ClassNotFoundException is thrown. The cache lookup goes on recursively from child to parent, until the tree root is reached or a class is found in cache. If the root is reached the class loaders try to load the class and unfold the recursion from parent to child. Summarizing that we have following order:
- Cache
- Parent
- Self
This mechanism ensures that classes tending to be loaded by class loaders nearest to the root.
这纯粹是效率问题。如果您忘记了缓存,class 加载顺序可确保 Java 系统 classes 始终优先于应用程序 classes 并且 class 可以只能由链中的一个 classloader 加载。所以没有 class 存在于多个缓存中,因此搜索缓存的顺序没有任何功能差异。
换句话说,您可以搜索引导加载程序缓存,然后是扩展 classloader 缓存,然后是系统 classloader 缓存,然后开始尝试加载 classes最终结果将完全相同。这样做将需要额外的 API 来搜索已加载的 class,并且不会带来什么好处,因为搜索缓存是一项非常快速的操作。
请注意,classes 可以由多个 classloader 加载,但如果它们位于 loader->parent 链中则不能。