类加载器负责将 .class 文件(可能在磁盘上,可能在网络上)加载到内存中,并为之生成对应的 java.lang.Class 对象。
本文包含:
- 类加载器简介
- 类加载机制
- 创建并使用自定义的类加载器
- URLClassLoader 类
1. 类加载器简介
类加载器负责加载所有的类,系统为所有被载入内存的类生成一个 java.lang.Class 实例。一旦一个类被载入 JVM 中,同一个类就不会被再次载入了。
当 JVM 启动时,会形成由三个类加载器组成的初始类加载器层次结构。
编译上面程序,可以看到如下结果:
2. 类加载机制
JVM 的类加载机制主要有以下三种:
类加载器之间的父子关系不是类继承上的父子关系,而类加载器实例之间的关系。
除了可以使用 Java 提供的类加载器之外,开发者也可以实现自己的类加载器,自定义的类加载器通过继承 ClassLoader 来实现。JVM 中这四种类加载器的层次结构如图所示:
下面程序示范了访问 JVM 的类加载器
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190713152702181.png?x-oss-process=image/w
JVM 的根类加载器并不是 Java 实现的,而且由于晨曦通常无法访问根类加载器,因此访问扩展类加载器的父类加载时返回 null。
类加载器加载 Class 大致要经过如下 8 个步骤:
3. 创建并使用自定义的类加载器
JVM 中除根类加载器之外的所有类加载器都是 ClassLoader 子类的实例,开发者可以通过扩展 ClassLoader 的子类,并重写该 ClassLoader 所包含的方法来实现 自定义的类加载器。
ClassLoader 类有如下两个关键方法:
如果需要实现自定义的 ClassLoader,则可以通过重写以上两个方法来实现,通常推荐重写 findClass() 方法,而不是重写 loadClass() 方法。
LoadClass() 方法的执行步骤如下:
从上面步骤可以看出,重写 findClass() 方法可以避免覆盖默认类加载器的父类委托、缓冲机制两种策略;如果重写 loadClass() 方法,则实现逻辑更为复杂。
此外,ClassLoader 里还包含如下一些普通方法:
使用自定义的类加载器,可以实现如下常见功能:
4. URLClassLoader 类
URLClassLoader 实现类是系统类加载器和扩展类生成器的父类(父类指类与类之间的继承关系)。它就可以从本地文件系统获取二进制文件来加载类,也可以从远程主机获取二进制文件来加载类。
在应用程序中可以直接使用URLClassLoader ,URLClassLoader 类提供了如下两个构造器: