目录
一、什么是类加载器
JVM的类加载器(Class Loader)是JVM的一个重要组成部分,它负责将Java字节码文件(.class文件)从磁盘或网络中加载到内存中,并转换成JVM能够识别和执行的Java类型。在Java应用程序启动时,JVM会自动创建三个类加载器:
-
Bootstrap ClassLoader:也称为引导类加载器,负责加载JRE核心类库(例如java.lang、java.util等),通常使用C++语言实现,是JVM的一部分。
-
Extension ClassLoader:也称为扩展类加载器,负责加载JRE扩展目录(jre/lib/ext/)下的jar包。
-
System ClassLoader:也称为应用类加载器,负责加载classpath路径下的类。
此外,开发人员还可以自定义类加载器,在运行时动态地加载所需的类。自定义类加载器可以继承ClassLoader类,重写findClass()方法以实现自己的逻辑。
类加载器采用“双亲委派”机制,即当一个类加载器收到加载请求时,它首先会将请求委派给其父类加载器处理,直到委派到Bootstrap ClassLoader为止。只有当父类加载器无法加载该类时,子类加载器才会尝试加载该类。这种机制可以保证类的唯一性,避免出现多个同名的类。
二、引导类加载器
JVM的引导类加载器(Bootstrap ClassLoader)是Java虚拟机自身的一部分,负责在JVM启动时加载核心Java类库,例如java.lang、java.util等。引导类加载器使用原生代码实现,不是Java语言编写的,并且无法被Java程序直接引用。
引导类加载器是JVM中最顶层的类加载器,它没有父类加载器。这是为了避免由于类加载器之间的依赖关系而导致死循环或者栈溢出等问题。因此,在引导类加载器加载的类中,不能通过传统的双亲委派机制来加载其他类。
引导类加载器通常加载的类都是JVM运行时必需的类,是JVM整个生命周期内唯一的类加载器。它加载的类从JVM规范的角度来看是“系统级”的核心类,是和操作系统相关的,不同的JVM实现可能加载不同的类库。
总之,引导类加载器是JVM中最基础的一个组成部分,是所有Java程序的起点,也是Java虚拟机保证Java语言可移植性的重要手段之一。
三、扩展类加载器
JVM的扩展类加载器(Extension ClassLoader)是JVM自带的一个类加载器,它负责加载JRE扩展目录(jre/lib/ext/)下的jar包。在Java应用程序启动时,JVM会自动创建三个类加载器:Bootstrap ClassLoader、Extension ClassLoader和System ClassLoader。
Extension ClassLoader是由sun.misc.Launcher$ExtClassLoader类实现的,它继承自ClassLoader类,具有双亲委派机制。当Extension ClassLoader收到加载请求时,它会先将请求委派给其父类加载器Bootstrap ClassLoader处理,只有当Bootstrap ClassLoader无法加载该类时,Extension ClassLoader才会尝试加载该类。
Extension ClassLoader主要负责加载JRE扩展目录下的jar包,这些jar包通常包含一些Java标准扩展库,例如Java Cryptography Extension(JCE)和Java Database Connectivity(JDBC)等,也可以加载用户自定义的扩展库。
使用扩展类加载器可以使Java应用程序更加灵活,开发人员可以根据需要自行添加或删除扩展库,从而满足不同的业务需求。
四、应用类加载器
JVM的应用类加载器(Application Classloader),也称为系统类加载器(System Classloader),是JVM中三种默认的类加载器之一,负责加载应用程序classpath路径下的所有类。
在Java应用程序启动时,JVM会自动创建一个Application Classloader实例,并将其设置为系统类加载器。当应用程序需要使用某个类时,Application Classloader会首先尝试从缓存中查找该类是否已经被加载过,如果没有则从classpath路径下查找该类所在的JAR包或目录,并将其加载到内存中。如果还无法找到该类,则抛出ClassNotFoundException异常。
应用程序可以通过ClassLoader.getSystemClassLoader()方法获取当前线程的Application Classloader实例,并使用它来加载所需的类。此外,开发人员还可以通过自定义ClassLoader的方式来实现更灵活、个性化的类加载机制。
总之,Application Classloader是JVM中非常重要的一个组成部分,它负责将应用程序所需的类加载到内存中,是Java应用程序正常运行的关键之一。
五、自定义加载器
JVM的自定义加载器(Custom ClassLoader)是JVM提供的一种机制,可以在运行时动态地加载Java类。开发人员可以通过自定义加载器实现一些特殊的加载方式,例如从数据库、网络或其他非标准位置中加载类。
自定义加载器需要继承java.lang.ClassLoader类,并重写findClass()方法,该方法负责查找并加载指定名称的类。在实现findClass()方法时,开发人员通常需要遵循以下规则:
-
首先尝试使用双亲委派机制委派给父类加载器进行加载,只有在父类加载器无法加载该类时才执行自定义加载逻辑。
-
在实现类加载过程时,需要调用defineClass()方法来定义类,该方法会将字节数组形式的Java类数据转换成Class对象。
-
加载的类不能与JDK类库或其他已经被加载的类重名,否则会出现ClassNotFoundException等异常。
-
为防止类似反射攻击的安全问题,需要在加载之前对类的字节码进行合法性检查。
自定义加载器可以实现一些特殊的业务需求,例如热部署、插件化等,但也需要开发人员谨慎使用,避免出现安全问题和内存泄漏等情况。