类加载器
- 一个负责加载类的对象,用于实现类加载过程中的加载这一步(加载 .class 文件)。
- JVM 按需加载,内存友好
- 全类名相同且加载器相同的类认定是一样的,只会被加载一次
- 每个 Java 类都有一个引用指向加载它的
ClassLoader。 - 数组类不是通过
ClassLoader创建的(数组类没有对应的二进制字节流),是由 JVM 直接生成的。 - 可以自定义类加载器满足特殊需求,比如对一些字节码加密,定义可以解密的加载器
- 顶级类加载器是 C++ 实现,无对应的类,其他都是 Java 实现
- 通过 getParent() 可以获取父类加载器,如果返回 null,表示直接是顶级类加载器直接加载
双亲委派模型
- 要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。
- 一般通过组合实现而不是继承
ClassLoader实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。- 只有父加载器无法完成才会自己加载,如果自己也无法加载,抛出
ClassNotFoundException异常。 - 不强制,只是 JDK 推荐
- 可以避免重复加载,否则如果每个加载器自己加载,父类可能也加载过,由于加载器不同,认定不同的类,重复加载
- 如果自己写了 java.lang 包同名的类,由于父加载器加载了 lang 包中的,就不会加载自己写的,避免核心 API 不被篡改
- 只有父加载器无法完成才会自己加载,如果自己也无法加载,抛出
- 加载器常用方法:
- findClass:根据类的二进制名称来查找类,默认实现是空方法。自定义的会实现并制定特定的路径(正常路径父加载器可以加载完成)
- loadClass:加载指定二进制名称的类,实现了双亲委派机制(先调用父类 loadClass 方法,再调用自己的) 。如果想要打破双亲委派机制,重写这个方法(先调用自己的,再调用父类的)
- TomCat 服务器就是通过打破双亲委派机制实现 Web 应用之间类的隔离
