Java

Java ClassLoader 解析

2018-08-09  本文已影响1人  Little丶Jerry
问:ClassLoader 的 defineClass、loadClass、findClass 方法分别有什么区别?

答:ClassLoader 用来加载 Java 类到 Java 虚拟机中(也就是将 class 文件加载成运行时的 Class 实例),所以问题中的几个方法其实就是负责这个加载过程中不同职责的定义。其中

问:简单说说你对 ClassLoader 的理解?

答:ClassLoader 的作用是根据一个指定的类名称找到或者生成其对应的字节代码,然后把字节码转换成一个 Java 类(即 java.lang.Class 实例),除此之外还负责加载 Java 应用所需的资源、Native lib 库等。

Java 的类加载器大致可以分成系统类加载器和应用开发自定义类加载器。系统类加载器主要有如下几个:

除了引导类加载器之外,所有的其他类加载器都有一个父类加载器(可以通过 ClassLoadergetParent() 方法得到)。系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器,开发自定义的类加载器的父类加载器是加载此类加载器的 Java 类的类加载器。所以类加载器在尝试自己去加载某个类时会先通过 getParent() 代理给其父类加载器,由父类加载器先去尝试加载这个类,依次类推,从而形成了双亲委派模式。类加载机制是通过 loadClass 方法触发的,查找类有没有被加载和该代理给哪个层级的加载器加载是由 findClass 方法实现的,而真正完成类加载工作是 defineClass 方法实现的。

问:Java 虚拟机是如何判断两个 Class 类是相同的?

答:Java 虚拟机不仅要看类的全名是否相同(含包名路径),还要看加载此类的类加载器是否一样,只有两者都相同的情况下才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类也是不同的,譬如一个 Java 类 cn.yan.Test 在编译后生成了字节码文件 Test.class,两个不同的类加载器 ClassLoaderA 和 ClassLoaderB 分别读取了这个 Test.class 文件,然后各自定义出一个 java.lang.Class 类的实例来表示这个类,这两个实例是不相同的,因为对于 Java 虚拟机来说它们是不同的类,这时候如果试图对这两个类的对象进行相互赋值则会抛出 ClassCastException 运行时异常。这在做插件化动态加载中要尤其注意。

本文参考自 ClassLoader 必知重点题目解析

上一篇下一篇

猜你喜欢

热点阅读