::我的理解

类加载器,主要是类在加载阶段,将class文件加载到JVM内存的过程,最终会在内存中生成一个代表这个类的java.lang.Class对象。
那存在的意义呢?能想到的有几点,不一定对。

  1. 为了对class的处理方式,如class来源于网络、class加密等
  2. 为了对加载的路径优先级问题,比如同一个类,在系统也有,用户目录也有,怎么处理?这就涉及到了类加载器的双亲委派机制

分类

  1. 启动类加载器(引导类加载器,Bootstrap ClassLoader)
  • 这个类加载使用C/C++ 语言实现,嵌套在JVM 内部
  • 它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jarresource.jarsun.boot.class.path路径下的内容),用于提供JVM自身需要的类
  • 并不继承自 java.lang.ClassLoader,没有父加载器
  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
  • 出于安全考虑,Boostrap 启动类加载器只加载名为java、Javax、sun等开头的类
  1. 扩展类加载器(Extension ClassLoader)
  • java语言编写,由sun.misc.Launcher$ExtClassLoader实现
  • 派生于 ClassLoader
  • 父类加载器为启动类加载器
  • java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext 子目录(扩展目录)下加载类库。如果用户创建的JAR 放在此目录下,也会自动由扩展类加载器加载
  1. 应用程序类加载器(也叫系统类加载器,AppClassLoader)
  • java语言编写,由 sun.misc.Lanucher$AppClassLoader 实现
  • 派生于 ClassLoader
  • 父类加载器为扩展类加载器
  • 它负责加载环境变量classpath或系统属性java.class.path 指定路径下的类库
  • 该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载的
  • 通过 ClassLoader#getSystemClassLoader() 方法可以获取到该类加载器
  1. 自定义类加载器
    4.1 为什么要自定义类加载器?
    • 隔离加载类
    • 修改类加载的方式
    • 扩展加载源(可以从数据库、云端等指定来源加载类)
    • 防止源码泄露(Java代码容易被反编译,如果加密后,自定义加载器加载类的时候就可以先解密,再加载)
      4.2 用户自定义加载器实现步骤
    • 开发人员可以通过继承抽象类 java.lang.ClassLoader 类的方式,实现自己的类加载器,以满足一些特殊的需求
    • 在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loadClass()方法,从而实现自定义的类加载类,但是JDK1.2之后已经不建议用户去覆盖loadClass()方式,而是建议把自定义的类加载逻辑写在findClass()方法中
    • 编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findClass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁
      4.3 如何自定义类加载器
    • 需要保留双亲委派模型:extends ClassLoader,重写 findClass()
    • 破坏双亲委派模型:直接重写 loadClass() 代码热替换