Skip to content

什么是类加载器?类加载器负责运行时查找和装入Class文件

类加载器有几种类型?

JVM在运行时会产生三个ClassLoader:Bootstrap (启动类加载器)、ExtensionClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。

Bootstrap(启动类加载器)

启动类加载器从系统属性sun.boot.class.path所指定的目录中加载类库,该加载器没有父加载器。它负责加载虚拟机的核心类库,如java.lang.*等。

启动类加载器的实现依赖于底层操作系统,属于虚拟机的实现的一部分(本质由C++实现),它并没有继承java.lang.ClassLoader类。

ExtensionClassLoader(扩展类装载器)

扩展类加载器从java.ext.dirs系属性所指定的目录中加载类库,扩展类加载器是纯Java类,是java.lang.ClassLoader类的子类。

AppClassLoader(系统类装载器)

由sum.misc.Launcher$AppClassLoader类实现,称为系统类加载器或应用程序类加载器。负责加载用户类路径(ClassPath)上所指定的类库,系统类加载器javg.class.path 所指定的目录中加载类,它是用户自定义的类加载器的默认父加载器。

例如你自己引入的第三方jar包,例如spring jar等等;系统类加载器是纯Java类,是java.lang.ClassLoader类的子类。

自定义类加载器

上述3个是JVM在运行时会产生三个类加载器,除此之外还有第四种就是自定义类加载器,那么为什么需要自定义类加载器?又在什么情况下用到?

用户在需要的情况下,可以实现自己的自定义类加载器,一般而言,在以下几种情况下需要自定义类加载器:

  1. 隔离加载类:某些框架为了实现中间件和应用程序的模块的隔离,就需要中间件和应用程序使用不同的类加载器,例如Tomcat,Tomcat可以运行多个应用程序,每个应用程序之间是相互隔离的。
  2. 修改类加载的方式:类加载的双亲委派模型并不是强制的,用户可以根据需要在某个时间点动态加载类;
  3. 扩展类加载源:例如从数据库、网络进行类加载;
  4. 防止源代码泄露:Java代码很容易被反编译和篡改,为了防止源码泄露,可以对类的字节码文件进行加密,并编写自定义的类加载器来加载自己的应用程序的类。

实现自定义类加载器

若要实现自定义类加载器,只需要继承 java.lang.ClassLoader 类,并且重写其findClass()方法即可。

java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称, 找到或者生成其对应的字节代码,然后从这些字节代码中生成一个java.lang.Class 实例。ClassLoader的核心方法如下:

  1. getParent():返回该类加载器的父类加载器。
  2. loadClass(String name):加载名称为二进制名称为name的类,返回的结果是java.lang.Class类的实例。
  3. findClass(String name):查找名称为name的类,返回的结果是java.lang.Class类的实例。
  4. findLoadedClass(String name):查找名称为name的已经被加载过的类,返回的结果是java.lang.Class类的实例。