1. Java 类加载机制的强大之处
- 在于我们可以创建自定义的
ClassLoader
- 自定义
ClassLoader
是 Tomcat 实现应用隔离、支持 JSP、OSGI 实现动态模块化的基础
2. 怎样自定义 ClassLoader
- 一般而言,继承类
ClassLoader
,重写findClass()
方法就可以了 - 实现
findClass()
方法- 使用自己的逻辑寻找 class 文件字节码的字节形式
- 找到后,使用如下方法转换为
Class
对象:protected final Class<?> defineClass(String name, byte[] b, int off, int len)
name
表示类名,b
是存放字节码数据的字节数组,有效数据从off
开始,长度为len
3. 写一个自定义 ClassLoader
的 Demo
1 | public class MyClassLoader extends ClassLoader { |
4. 接上题,自定义的 MyClassLoader
有什么用呢
MyClassLoader
没有指定父ClassLoader
,默认是系统类加载器- 即
ClassLoader.getSystemClassLoader()
的返回值 - 不过,
ClassLoader
有一个可重写的构造方法,可以指定父ClassLoader
:protected ClassLoader(ClassLoader parent)
- 即
确实可以将
BASE_DIR
加到classpath
中,但从 Web 服务器、数据库和缓存服务器获取byte
数组,这就不是系统类加载器能做到的了使用自定义的
MyClassLoader
还有一个好处,就是可以创建多个MyClassLoader
。对同一个类,每个MyClassLoader
都可以加载一次,得到同一个类的不同对象。这样的好处是- 可以实现隔离。一个复杂的程序,内部可能按模块组织,不同模块可能使用同一个类,但使用的是不同的版本,如果使用同一个类加载器,它们是无法共存的。不同模块使用不同的类加载器就可以实现隔离,Tomcat 使用它隔离不同的 Web 应用,OSGI 使用它隔离不同模块
- 可以实现热部署。使用同一个
ClassLoader
,类只会被加载一次。加载后,即使 class 文件已经变了,再次加载,得到的也还是原来的Class
对象。而使用MyClassLoader
,则可以创建一个新的ClassLoader
,再用它加载Class
,得到的Class
对象就是新的,从而实现动态更新