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包等内容,希望对大家有所帮助。

相关推荐
tqs_123451 小时前
MySQL RR隔离级别死锁|Gap间隙锁、临键锁,订单并发范围查询死锁根因方案
java
逆境不可逃1 小时前
Pi Agent 学习笔记:多个工具怎样并行执行
java
GreenTea2 小时前
7000 万 QPS、500 PB:OpenAI 如何用一个 Python 存储平台撑住 10 亿用户
后端·架构
Flynt2 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet2 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
GreenTea2 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持2 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
niucloud-admin2 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
海宇AI4 小时前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化车抵贷核保网关
java·人工智能·架构·自动化
Bs_MoneyMagnet5 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计