当前位置: 首页 > article >正文

根据jvm源码剖析类加载机制

根据jvm源码剖析类加载机制

java Test.class之后的大致流程

java Test.class ----> 对于windows操作系统

----> java.exe调用jvm.dll文件创建JVM,

----> 在创建JVM中先由C++的代码创建Boostarp(引导)类加载器,

----> C++代码会创建sun.misc.Launcher.getLauncher()生成Launcher实例(JVM启动器实例)

----> 引导类加载器首先加载sun.misc.Launcher类,

----> 在初始化时执行静态代码块new Launcher(),

----> new的过程中调用Launcher类的构造方法,

----> 在Launcher类的构造方法中,创建ExtClassLoader和AppClassLoader,

----> 并维护三个类加载器的父子关系,将AppClassLoader赋给当前线程的ClassLoader属性和Launcher对象的ClassLoader属性。

----> jvm默认使用sun.misc.Launcher.getClassLoader()返回Launcher对象的ClassLoader对象(AppClassLoader)加载我们程序的类

类的加载过程

加载—校验—准备—解析—初始化—使用—卸载

加载:从磁盘中以IO流的方式读取class文件的字节码

校验:验证class文件合法性,如文件头

准备:为静态变量分配内存,并赋默认值,如boolean类型赋false、int类型赋0

解析:静态链接:将符号引用替换为直接引用,把静态方法替换为指向内存的地址或句柄!!!

初始化:对类的静态变量设置指定的值、执行静态代码块

在这里插入图片描述

类加载器
种类

bootstrapClassLoader(启动/引导)类加载器:由C++创建,负责加载jre/lib下的核心类库

ExtClassLoader扩展类加载器:负责加载jre/lib/ext目录下的类

AppClassLoader应用程序类加载器:负责加载用户自定义路径下的类

import sun.misc.Launcher;
import java.net.URL;public class TestJDKClassLoader {public static void main(String[] args) {//jre/lib下的核心类由启动类加载器加载System.out.println(String.class.getClassLoader());//jre/lib/ext下的类由扩展类加载器加载System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName());//用户类路径下的类由应用程序类加载器加载System.out.println(TestJDKClassLoader.class.getClassLoader().getClass().getName());System.out.println();//获取当前应用程序类加载器ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();ClassLoader extClassloader = appClassLoader.getParent();ClassLoader bootstrapLoader = extClassloader.getParent();System.out.println("the bootstrapLoader : " + bootstrapLoader);System.out.println("the extClassloader : " + extClassloader);System.out.println("the appClassLoader : " + appClassLoader);System.out.println();System.out.println("bootstrapLoader加载以下文件:");//获取引导类加载器加载的jar包路径URL[] urls = Launcher.getBootstrapClassPath().getURLs();for (int i = 0; i < urls.length; i++) {System.out.println(urls[i]);}System.out.println();System.out.println("extClassloader加载以下文件:");System.out.println(System.getProperty("java.ext.dirs"));System.out.println();System.out.println("appClassLoader加载以下文件:");System.out.println(System.getProperty("java.class.path"));}
}
双亲委派原则

在这里插入图片描述

双亲委派机制:当类加载器加载某个类时,先判断类是否已加载,如果没有则委派父类加载器加载,父类加载器判断类是否已加载,如果没有则委派父类加载器加载;如果到引导类加载器(bootstrapClassloader)判断类尚未加载,将尝试加载类,如果加载不到,则指派子类加载器加载。

源码:

​ 在java.lang.ClassLoader.loadClass()方法实现的双亲委派机制:

    //name是加载的全类名,如com.example.demo.Testprotected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded//1、判断该类是否已经被加载过Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {//2、如果找不到委派父类加载器加载if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();//3、如果父类加载器没有加载到,子类加载器尝试加载c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
设计双亲委派机制的目的

沙箱安全机制:用户自定义的与核心类同名的类不会被加载,而加载的仍是jre定义的类,防止核心库的类和API被篡改;

防止类被重复加载:如果父类加载器已经加过某个类了,子类加载器就不会二次加载了。

自定义类加载器和打破双亲委派原则

自定义类加载器只需要继承 java.lang.ClassLoader 类,该类有两个核心方法:

一个是loadClass(String, boolean),实现了双亲委派机制,若要打破双亲委派原则重写loadClass()方法

一个是findClass,默认实现是空方法,实现了根据全类名加载字节码并返回Class对象,所以我们自定义类加载器主要是重写findClass方法

public class MyClassLoader extends ClassLoader {private String classPath;public MyClassLoader(String classPath) {this.classPath = classPath;}//    @Override
//    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
//        //自己的包进行加载的时候打破双亲委派原则
//        if(name.contains("com.example.demo")){
//            return findClass(name);
//        }
//
//        //核心包依然由父的类加载器加载
//        return super.loadClass(name, resolve);
//    }@Overrideprotected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException {synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();//指定的类路径下的包 ,不在委托父类加载器进行加载,直接由该类加载器加载if (name.contains("com.example.demo")) {c = findClass(name);} else {c = this.getParent().loadClass(name);}// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}if (resolve) {resolveClass(c);}return c;}}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] data = loadByte(name);//defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字数组。return defineClass(name, data, 0, data.length);} catch (IOException e) {throw new ClassNotFoundException();}}private byte[] loadByte(String name) throws IOException {name = name.replaceAll("\\.", "/");FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");int len = fis.available();byte[] data = new byte[len];fis.read(data);fis.close();return data;}public static void main(String args[]) throws Exception {//初始化自定义类加载器,会先初始化父类ClassLoader,其中会把自定义类加载器的父加载设置为应用程序类加载器AppClassLoaderMyClassLoader classLoader = new MyClassLoader("D:/test");//D盘创建 com/example/demo几级目录,将Test类的复制类Test.class丢入该目录Class clazz = classLoader.loadClass("com.example.demo.Test");Object obj = clazz.newInstance();Method method = clazz.getDeclaredMethod("test", null);method.invoke(obj, null);System.out.println(clazz.getClassLoader().getClass().getName());}
}

注意:自定义类加载器的父类加载器是AppClassLoader。

因为,在new MyClassLoader时,会执行MyClassLoader的父类ClassLoader的无参构造方法,调用getSystemClassLoader(),会返回sun.misc.Launcher类的loader属性,该属性的值就是AppClassLoader对象,在ClassLoader构造方法中将AppClassLoader对象赋值到MyClassLoader的parent属性。

Tomcat打破了双亲委派原则

Tomcat是web容器,所以:

1、会部署多个服务,但每个服务的同一个类路径一样,但版本可能不一样;

2、部署在同一web容器的服务可以共享同一个类,防止同一个类重复加载多次;

3、web容器自己的依赖不能与web应用程序的类混淆,基于安全考虑;

4、web容器支持jsp热更新,通过卸载类加载器重新更新的方式。

所以,tomcat要打破双亲委派原则。

相关文章:

根据jvm源码剖析类加载机制

根据jvm源码剖析类加载机制 java Test.class之后的大致流程 java Test.class ----> 对于windows操作系统 ----> java.exe调用jvm.dll文件创建JVM&#xff0c; ----> 在创建JVM中先由C的代码创建Boostarp&#xff08;引导&#xff09;类加载器&#xff0c; ----&g…...

Mixly1.0/2.0/3.0 (windows系统) 安装教程及使用常见问题解决

大家好&#xff01;长期以来&#xff0c;不少用户在使用 Mixly 软件过程中遇到了各类问题。为了帮助大家更顺畅地使用该软件&#xff0c;齐护机器人工程师结合自身丰富经验&#xff0c;精心总结并推出了本期教程。在本教程中&#xff0c;我们将从 Mixly 图形化编程软件的安装步…...

DDS通信中间件——DDS-TSN规范

DDS通信中间件——DDS-TSN规范 做了十年DDS通信中间件产品的程序员和大家分享一下对DDS这套规范的个人理解。预期本系列文章将包括以下内容陆续更新&#xff1a; DDS规范概述DCPS规范解读 & QoS策略XTypes规范解读RTPS规范解读DDS安全规范解读DDS-RPC规范解读&#xff08…...

JWT安全:弱签名测试.【实现越权绕过.】

JWT安全&#xff1a;假密钥【签名随便写实现越权绕过.】 JSON Web 令牌 (JWT)是一种在系统之间发送加密签名 JSON 数据的标准化格式。理论上&#xff0c;它们可以包含任何类型的数据&#xff0c;但最常用于在身份验证、会话处理和访问控制机制中发送有关用户的信息(“声明”)。…...

MATLAB实现井字棋

一、智能决策系统与博弈游戏概述 &#xff08;一&#xff09;智能决策系统核心概念 智能决策系统&#xff08;Intelligent Decision System, IDS&#xff09;是通过数据驱动和算法模型模拟人类决策过程的计算机系统&#xff0c;核心目标是在复杂环境中自动生成最优策略&#…...

Baklib知识中台加速企业服务智能化实践

知识中台架构体系构建 Baklib 通过构建多层级架构体系实现知识中台的底层支撑&#xff0c;其核心包含数据采集层、知识加工层、服务输出层及智能应用层。在数据采集端&#xff0c;系统支持对接CRM、ERP等业务系统&#xff0c;结合NLP技术实现非结构化数据的自动抽取&#xff1…...

在AIX环境下修改oracle 11g rac的IP地址

0、当前环境 由于机房网络变更&#xff0c;客户要修改现在RAC的网络地址&#xff0c;这里记录一下。 主机操作系统&#xff1a;AIX 7.2 数据库版本&#xff1a;11.2.0.4 rac 数据库实例名&#xff1a;orcl1/orcl2 当前hosts文件配置 192.168.56.10 rac1 192.168.56.11 …...

VMware Tools 手动编译安装版

OWASPBWA安装VMware tools 安装时&#xff0c;显示如下提示 官方安装手册参考&#xff1a;https://knowledge.broadcom.com/external/article?legacyId1014294 按照提示&#xff0c;下载linux.iso文件&#xff0c;并连接到虚拟机的CDROM里&#xff0c;状态勾选已连接&#x…...

android平台驱动开发(六)--Makefile和Kconfig简介

Makefile&#xff1a; 1.编译进内核&#xff0c;还是以模块方式加载 模块方式编译成ko,通常是自己添加脚本方式insmod ,android 平台通常默认有modprobe加载&#xff0c;不需要额外添加insmod脚本 lsmod |grep test 可以查看是否安装成功 rmmod test-m.ko 可以删除ko 2.多…...

【手写系列】手写线程池

PS&#xff1a;本文的线程池为演示 Demo&#xff0c;皆在理解线程池的工作原理&#xff0c;并没有解决线程安全问题。 最简单一版的线程池 public class MyThreadPool {// 存放线程&#xff0c;复用已创建的线程List<Thread> threadList new ArrayList<>();publ…...

python学习打卡day40

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#…...

redis高并发问题

Redlock原理和存在的问题 Redlock 基于以下假设&#xff1a; 有多个&#xff08;一般建议是 5 个&#xff09;彼此独立的 Redis 实例&#xff08;不是主从复制&#xff0c;也不是集群模式&#xff09;&#xff0c;它们之间没有数据同步。客户端可以与所有 Redis 实例通信。 …...

Live Helper Chat 安装部署

Live Helper Chat(LHC)是一款开源的实时客服聊天系统,适用于网站和应用,帮助企业与访问者即时沟通。它功能丰富、灵活、可自托管,常被用于在线客户支持、销售咨询以及技术支持场景。 🧰 系统要求 安装要求 您提供的链接指向 Live Helper Chat 的官方安装指南页面,详细…...

ARXML解析与可视化工具

随着汽车电子行业的快速发展,AUTOSAR标准在车辆软件架构中发挥着越来越重要的作用。然而,传统的ARXML文件处理工具往往存在高昂的许可费用、封闭的数据格式和复杂的使用门槛等问题。本文介绍一种基于TXT格式输出的ARXML解析方案,为开发团队提供了一个高效的替代解决方案。 …...

PnP(Perspective-n-Point)算法 | 用于求解已知n个3D点及其对应2D投影点的相机位姿

什么是PnP算法&#xff1f; PnP 全称是 Perspective-n-Point&#xff0c;中文叫“n点透视问题”。它的目标是&#xff1a; 已知一些空间中已知3D点的位置&#xff08;世界坐标&#xff09;和它们对应的2D图像像素坐标&#xff0c;求解摄像机的姿态&#xff08;位置和平移&…...

LeetCode 热题 100 208. 实现 Trie (前缀树)

LeetCode 热题 100 | 208. 实现 Trie (前缀树) 大家好&#xff01;今天我们来解决一道经典的算法题——实现 Trie (前缀树)。Trie&#xff08;发音类似 “try”&#xff09;是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构在自动补全和拼…...

python爬虫:RoboBrowser 的详细使用

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、RoboBrowser概述1.1 RoboBrowser 介绍1.2 安装 RoboBrowser1.3 与类似工具比较二、基本用法2.1 创建浏览器对象并访问网页2.2 查找元素2.3 填写和提交表单三、高级功能3.1 处理文件上传3.2 处理JavaScript重定向3.3…...

在日常管理服务器中如何防止SQL注入与XSS攻击?

在日常管理服务器时&#xff0c;防止SQL注入&#xff08;Structured Query Language Injection&#xff09;和XSS&#xff08;Cross-Site Scripting&#xff09;攻击是至关重要的&#xff0c;这些攻击可能会导致数据泄露、系统崩溃和信息泄露。以下是一份技术文章&#xff0c;介…...

Wkhtmltopdf使用

Wkhtmltopdf使用 1.windows本地使用2.golangwindows环境使用3.golangdocker容器中使用 1.windows本地使用 官网地址 https://wkhtmltopdf.org/&#xff0c;直接去里面下载自己想要的版本&#xff0c;这里以windows版本为例2.golangwindows环境使用 1.安装扩展go get -u githu…...

ArcGIS Pro 创建渔网格网过大,只有几个格网的解决方案

之前用ArcGIS Pro创建渔网的时候&#xff0c;发现创建出来格网过大&#xff0c;只有几个格网。 后来查阅资料&#xff0c;发现是坐标不对&#xff0c;导致设置格网大小时单位为度&#xff0c;而不是米&#xff0c;因此需要进行坐标系转换&#xff0c;网上有很多资料讲了ArcGIS …...

重学计算机网络之以太网

一&#xff1a;历史发展进程 DIX EtherNet V2 战胜IEEE802.3成为主流版本。总线型交换机拓扑机构代替集线器星型拓扑机构 1990年IEEE制定出星形以太网10BASE-T的标准**802.3i**。“10”代表10 Mbit/s 的数据率&#xff0c;BASE表示连接线上的信号是基带信号&#xff0c;T代表…...

《深度解构现代云原生微服务架构的七大支柱》

☁️《深度解构现代云原生微服务架构的七大支柱》 一线架构师实战总结&#xff0c;系统性拆解现代微服务架构中最核心的 7 大支柱模块&#xff0c;涵盖通信协议、容器编排、服务网格、弹性伸缩、安全治理、可观测性、CI/CD 等。文内附架构图、实操路径与真实案例&#xff0c;适…...

使用SCSS实现随机大小的方块在页面滚动

目录 一、scss中的插值语法 二、方块在界面上滚动的动画 一、scss中的插值语法 插值语法 #{}‌ 是一种动态注入变量或表达式到选择器、属性名、属性值等位置的机制 .类名:nth-child(n) 表示需同时满足为父元素的第n个元素且类名为给定条件 效果图&#xff1a; <div class…...

AI 眼镜新纪元:贴片式TF卡与 SOC 芯片的黄金组合破局智能穿戴

目录 一、SD NAND&#xff1a;智能眼镜的“记忆中枢”突破空间限制的存储革命性能与可靠性的双重保障 二、SOC芯片&#xff1a;AI眼镜的“智慧大脑”从性能到能效的全面跃升多模态交互的底层支撑 三、SD NANDSOC&#xff1a;11&#xff1e;2的协同效应数据流水线的高效协同成本…...

论文阅读(六)Open Set Video HOI detection from Action-centric Chain-of-Look Prompting

论文来源&#xff1a;ICCV&#xff08;2023&#xff09; 项目地址&#xff1a;https://github.com/southnx/ACoLP 1.研究背景与问题 开放集场景下的泛化性&#xff1a;传统 HOI 检测假设训练集包含所有测试类别&#xff0c;但现实中存在大量未见过的 HOI 类别&#xff08;如…...

算法学习--持续更新

算法 2025年5月24日 完成&#xff1a;快速排序、快速排序基数优化、尾递归优化 快排 public class QuickSort {public void sort(int[] nums, int left, int right) {if(left>right){return;}int partiton quickSort(nums,left,right);sort(nums,left,partiton-1);sort(nu…...

Postman 发送 SOAP 请求步骤 归档

0.来源 https://apifox.com/apiskills/sending-soap-requests-with-postman/?utm_sourceopr&utm_mediuma2bobzhang&utm_contentpostman 再加上自己一点实践经验 1. 创建一个新的POST请求 postman 创建一个post请求, 请求url 怎么来的可以看第三步 2. post请求设…...

Python Day39 学习(复习日志Day4)

复习Day4日志内容 浙大疏锦行 补充: 关于“类”和“类的实例”的通俗易懂的例子 补充&#xff1a;如何判断是用“众数”还是“中位数”填补空缺值&#xff1f; 今日复习了日志Day4的内容&#xff0c;感觉还是得在纸上写一写印象更深刻&#xff0c;接下来几日都采取“纸质化复…...

[Python] Python自动化:PyAutoGUI的基本操作

初次学习&#xff0c;如有错误还请指正 目录 PyAutoGUI介绍 PyAutoGUI安装 鼠标相关操作 鼠标移动 鼠标偏移 获取屏幕分辨率 获取鼠标位置 案例&#xff1a;实时获取鼠标位置 鼠标点击 左键单击 点击次数 多次有时间间隔的点击 右键/中键点击 移动时间 总结 鼠…...

课程介绍:《ReactNative基础与实战指南2025》

学习如何使用 ReactJS 构建适用于 iOS 和 Android 的 React Native 移动应用&#xff0c;无需 ReactJS 经验。无需掌握 Swift、Objective-C 或 Java/Android&#xff0c;也能开发跨平台&#xff08;iOS 和 Android&#xff09;移动应用。 全面掌握 React Native 的核心与进阶内…...