gpt4 book ai didi

java - 为什么第一次调用loadClass方法时这个引用是AppClassLoader而不是MyClassLoader

转载 作者:太空宇宙 更新时间:2023-11-04 11:55:11 25 4
gpt4 key购买 nike

我通过扩展classLoader编写myOwnClassLoader并重写其findClass方法。并遇到一个有趣的问题:

这是代码段:

public class MyClassLoader extends ClassLoader {
@Override
public Class<?> findClass(String name) {
byte[] bt = loadClassData(name);
return defineClass(name, bt, 0, bt.length);
}

private byte[] loadClassData(String className) {
...
}

public static void main(String[] args) throws ClassNotFoundException{
MyClassLoader myClassLoader = new MyClassLoader();
//Class<?> clazz = myClassLoader.findClass("com.classLoader.BMW");
Class<?> clazz = myClassLoader.loadClass("com.classLoader.BMW");
System.out.println(clazz.getClassLoader());//////////////////
}
}

执行时

Class<?> clazz = myClassLoader.findClass("com.classLoader.BMW");

输出符合我的期望:输出:

com.classLoader.MyClassLoader@xxxxxx

但是执行时

Class<?> clazz = myClassLoader.loadClass("com.classLoader.BMW");

输出超出了我的想象:输出:

sun.misc.Launcher$AppClassLoader@xxxx

预期输出

com.classLoader.MyClassLoader@xxxxxx

这是ClassLoaderloadClass方法的代码段

 Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
.....

我调试它并发现当我们在第一次时调用loadClass时,父级是sun.misc.Launcher$ExtClassLoader@6aa8ceb6,也就是说this引用是sun.misc.Launcher$AppClassLoader而不是com.classLoader.MyClassLoader@xxxxxx

<小时/>

我通过互联网和博客进行搜索define own classLoader告诉你

it will set AppClassLoader as parent of MyClassLoader in default constructor.

我检查了

System.out.println(myClassLoader.getParent());

找到MyClassLoader的父类确实是AppClassLoader它是如何实现这一点的,我的默认构造函数什么都不做,并且这是在其父类ClassLoader构造函数方法中实现的吗?我读了它的父构造函数,但仍然无法弄清楚。

无论如何,这似乎无法解释为什么当我们第一次调用 loadClass 方法时,thisAppClassLoader 而不是 MyClassLoader。我猜这是因为 *MyClassLoader 的 classLoader 是 AppClassLoader 但这只是我的直觉,我没有要点。


一切都会受到赞赏。

最佳答案

嗯,这一切都记录在案了:

ClassLoader() constructor :

Creates a new class loader using the ClassLoader returned by the method getSystemClassLoader() as the parent class loader.

loadClass(String) :

Loads the class with the specified binary name. … Invoking this method is equivalent to invoking loadClass(name, false).

loadClass(String,boolean-) :

Loads the class with the specified binary name. The default implementation of this method searches for classes in the following order:

  1. Invoke findLoadedClass(String) to check if the class has already been loaded.
  2. Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
  3. Invoke the findClass(String) method to find the class.

If the class was found using the above steps, and the resolve flag is true, this method will then invoke the resolveClass(Class) method on the resulting Class object.

Subclasses of ClassLoader are encouraged to override findClass(String), rather than this method.

class documentation of ClassLoader中也提到了这一点:

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.

此逻辑确保干净的作用域,即父作用域的类不会引用子作用域的类,并且具有相同限定名称但由不同类加载器定义的类之间不存在冲突。此类类可能仍然存在于不同的作用域中,但不存在于嵌套作用域中。但类加载器并不强制遵循此规则。委托(delegate)模型是随 Java 2 引入的。

关于java - 为什么第一次调用loadClass方法时这个引用是AppClassLoader而不是MyClassLoader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41436531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com