JVM工作原理与实战(九):类加载器-启动类加载器

前言

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了启动类加载器、通过启动类加载器去加载用户jar包等内容。


在Java虚拟机(JVM)中,类加载器负责将类的字节码文件加载到内存中,并生成对应的Class对象。类加载器是Java虚拟机中的重要组成部分,而启动类加载器(Bootstrap ClassLoader)则是其中最核心的类加载器。

一、启动类加载器

启动类加载器是由Hotspot虚拟机提供的,使用C++编写,是Java类加载器中的顶级类加载器。它的主要职责是加载Java的核心类库,如rt.jar、resources.jar和tools.jar等。这些核心类库包含了Java语言的核心类,如String等。

默认加载的是Java安装目录/jre/lib下的类文件:

在实际应用中,程序员通常会使用ClassLoader来动态加载第三方类库,或者实现自己的类加载器来满足特定的需求。ClassLoader提供了许多方法来动态加载类,如loadClass()、defineClass()等。这些方法允许程序员在运行时动态地加载类的字节码文件,并生成对应的Class对象。

但是由于启动类加载器位于虚拟机的环境中,而不是在应用程序的代码中,因此程序员无法直接获取到启动类加载器。这是出于安全性的考虑,因为启动类加载器是Java核心类库的加载器,如果允许应用程序代码获取到启动类加载器的引用,可能会被恶意代码利用来加载或修改Java核心类库,导致安全风险。因此,程序员无法在代码中获取到启动类加载器,也无法对其进行操作,这也是为了保证Java虚拟机的安全性和稳定性。

案例:

尝试获取启动类加载器(String类位于JDK下rt.jar包中):

arduino 复制代码
public class BootstrapClassLoaderDemo {
    public static void main(String[] args) throws IOException {
        ClassLoader classLoader = String.class.getClassLoader();
        System.out.println(classLoader);
    }
}

运行结果(无法获取该启动类加载器):

二、通过启动类加载器去加载用户jar包

在JDK中,类加载器是负责动态加载Java类到JVM中的机制。启动类加载器作为类加载器层次结构的最顶层,负责加载包括java.lang包在内的核心API类。当开发者需要添加或扩展核心类时,必须通过特定的方式来进行。

1.放入jre/lib目录进行扩展

一种直接的方法是将所需的jar包放入JRE/Lib目录下,让启动类加载器能够加载到这个jar包中的类,然而,这种方法并不推荐。主要原因在于,对JDK安装目录中的内容进行更改可能导致不稳定性以及其他未预期的问题。其次,可能会出现因为文件名不匹配而导致无法正常加载的情况发生。

2.使用参数进行扩展

为了更加灵活和可控地扩展JDK,推荐使用命令行参数进行配置。具体来说,可以使用-Xbootclasspath/a:jar包目录/jar包名来指定额外的jar包供启动类加载器加载。这种方式的好处在于,它允许开发者在不更改JDK安装内容的情况下进行扩展,从而保持JDK环境的稳定性。

bash 复制代码
-Xbootclasspath/a:jar包目录/jar包名

案例:

csharp 复制代码
public class Test {
    static {
        System.out.println("Test初始化");
    }
}

将该项目打成jar包:

运行结果:

放到目录下:

添加-Xbootclasspath/a:jar包目录/jar包名参数:

bash 复制代码
-Xbootclasspath/a:jar包目录/jar包名

加载jar包:

arduino 复制代码
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.rye.test.Test");
        System.out.println(aClass);
    }
}

运行结果:

获取该类的类加载器:

ini 复制代码
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.rye.test.Test");
        System.out.println(aClass);
        ClassLoader classLoader = aClass.getClassLoader();
        System.out.println(classLoader);
    }
}

获取结果(无法获取启动类加载器):

对于需要进行核心类扩展的情况,推荐使用命令行参数的方式进行配置,而不是直接修改JDK安装目录的内容。这样可以确保环境的稳定性和避免潜在的类加载问题。


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了启动类加载器、通过启动类加载器去加载用户jar包等内容,希望对大家有所帮助。

相关推荐
钢铁男儿2 分钟前
C# 类和继承(扩展方法)
java·servlet·c#
饮长安千年月9 分钟前
JavaSec-SpringBoot框架
java·spring boot·后端·计算机网络·安全·web安全·网络安全
移动开发者1号10 分钟前
Android 大文件分块上传实战:突破表单数据限制的完整方案
android·java·kotlin
代码匠心10 分钟前
从零开始学Flink:揭开实时计算的神秘面纱
java·大数据·后端·flink
jie1889457586625 分钟前
C++ 中的 const 知识点详解,c++和c语言区别
java·c语言·c++
Livingbody29 分钟前
Transformers Pipeline 加载whisper模型实现语音识别ASR
后端
网安INF30 分钟前
RSA加密算法:非对称密码学的基石
java·开发语言·密码学
蔡蓝36 分钟前
设计模式-观察着模式
java·开发语言·设计模式
异常君1 小时前
@Bean 在@Configuration 中和普通类中的本质区别
java·spring·面试
jackson凌1 小时前
【Java学习笔记】Math方法
java·笔记·学习