- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我通过扩展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
这是ClassLoader
中loadClass方法的代码段
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 ofMyClassLoader
in default constructor.
我检查了
System.out.println(myClassLoader.getParent());
找到MyClassLoader的父类确实是AppClassLoader它是如何实现这一点的,我的默认构造函数什么都不做,并且这是在其父类ClassLoader的构造函数方法中实现的吗?我读了它的父构造函数,但仍然无法弄清楚。
无论如何,这似乎无法解释为什么当我们第一次调用 loadClass 方法时,this 是 AppClassLoader 而不是 MyClassLoader。我猜这是因为 *MyClassLoader 的 classLoader 是 AppClassLoader
但这只是我的直觉,我没有要点。
一切都会受到赞赏。
最佳答案
嗯,这一切都记录在案了:
ClassLoader()
constructor :
Creates a new class loader using the
ClassLoader
returned by the methodgetSystemClassLoader()
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:
- Invoke
findLoadedClass(String)
to check if the class has already been loaded.- Invoke the
loadClass
method on the parent class loader. If the parent isnull
the class loader built-in to the virtual machine is used, instead.- 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 theresolveClass(Class)
method on the resultingClass
object.Subclasses of
ClassLoader
are encouraged to overridefindClass(String)
, rather than this method.
class documentation of ClassLoader
中也提到了这一点:
The
ClassLoader
class uses a delegation model to search for classes and resources. Each instance ofClassLoader
has an associated parent class loader. When requested to find a class or resource, aClassLoader
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 aClassLoader
instance.
此逻辑确保干净的作用域,即父作用域的类不会引用子作用域的类,并且具有相同限定名称但由不同类加载器定义的类之间不存在冲突。此类类可能仍然存在于不同的作用域中,但不存在于嵌套作用域中。但类加载器并不强制遵循此规则。委托(delegate)模型是随 Java 2 引入的。
关于java - 为什么第一次调用loadClass方法时这个引用是AppClassLoader而不是MyClassLoader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41436531/
我尝试扩展类加载器。我的 ClassLoader.loadClass 是: protected synchronized Class loadClass(String name, boolean r
我已成功将 Spring Boot 项目(在 prod env 中运行)从 JDK8 迁移到 JDK11。 我可以构建、测试、打包、安装、部署等等。 从我的 IDE 启动项目后,我的日志中有以下警告,
我是一名优秀的程序员,十分优秀!