目录

前言

类加载过程

类加载

执行过程

加载阶段

连接阶段

初始化阶段

类加载器

BootstrapClassLoader

ExtClassLoader

AppClassLoader

类加载器之间的关系

双亲委派机制

核心思想

好处

源码分析

类加载器之间的父子层级关系

双亲委派的体现


前言

上文中提到,Java源文件通过前端编译器生成.class字节码文件,字节码文件通过JVM中的类加载系统加载进内存再交由执行引擎处理,本文主要介绍类加载系统

类加载过程

类加载

当JVM需要用到某个类时,会加载它的.class文件,加载之后会创建对应的Class对象

执行过程

整个执行过程分为阶段:加载阶段、连接阶段、初始化阶段

加载阶段

通过完全限定名查找class文件二进制数据并加载进内存的过程,可以划分为三步

  1. 通过完全限定名定位到.class文件,并获取其二进制字节流数据
  2. 字节流的静态存储结构变为运行时数据结构
  3. 堆空间中创建一个Class对象,作为程序访问其数据的入口

连接阶段

分为验证、准备、解析三步,其中解析可能会在初始化之后执行

  1. 验证:检测class字节流数据是否符合虚拟机的要求,确保不会危害虚拟机自身的安全
  2. 准备:为类中声明的静态变量分配内存空间,并将其初始化为默认值
  3. 解析:把类中对常量池内的符号引用转化为直接引用的过程

初始化阶段

执行<clinit>(),对类的静态变量赋予指定的值(声明时指定的值或静态代码块赋予的值)

类加载器

JVM提供了三种类加载器,分别为BootstrapClassLoader、ExtClassLoader、AppClassLoader;当然也可以自定义实现类加载器

BootstrapClassLoader

是用C++实现的一种类加载器,是JVM的一部分,负责将如下两种位置下的类库加载到内存

  1. <JAVA_HOME>\lib
  2. -Xbootclasspath 指定

ExtClassLoader

是由sun公司实现的,位于sun.misc.Launcher中的一个静态内部类

package sun.misc;
// ...public class Launcher {// ...// 扩展类加载器ExtClassLoaderstatic class ExtClassLoader extends URLClassLoader {// ...}// ...
}

负责将如下两种位置下的类库加载到内存

  1. <JAVA_HOME>\lib\ext
  2. -Djava.ext.dir 指定

AppClassLoader

也是由sun公司实现,位于sun.misc.Launcher中的一个静态内部类,负责将类路径下的类库加载到内存

package sun.misc;
// ...public class Launcher {// ...// 应用程序类加载器AppClassLoaderstatic class AppClassLoader extends URLClassLoader {// ...}// ...
}

类加载器之间的关系

BootstrapClassLoader是在JVM启动时初始化的,负责加载ExtClassLoader,并将ExtClassLoader的父加载器设置为BootstrapClassLoader;接着BootstrapClassLoader加载AppClassLoader,并将AppClassLoader的父加载器设置为ExtClassLoader,自定义类加载器的父加载器为AppClassLoader

package classloader;public class CustomClassLoader extends ClassLoader {public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader();System.out.println("自定义类加载器:" + customClassLoader);ClassLoader loader = customClassLoader.getParent();System.out.println("自定义类加载器的父加载器:" + loader);loader = loader.getParent();System.out.println("AppClassLoader的父加载器:" + loader);loader = loader.getParent();System.out.println("ExtClassLoader的父加载器:" + loader);}
}

BootstrapClassLoader是由C++实现的,所以获取的是null

双亲委派机制

核心思想

类加载器从上至下为:BootstrapClassLoader -> ExtClassLoader -> AppClassLoader

  • 自下而上检查类是否已经被加载
  • 从上至下尝试加载类

好处

  1. 避免一个类在不同层级的类加载器重复加载
  2. 保障Java核心类的安全性,如通过网络传输一个java.lang.String类,需要被加载时,通过双亲委派机制最终找到BootstrapClassLoader后,发现该类已经被加载从而不会加载传输过来的java.lang.String类,直接返回BootstrapClassLoader加载的String.class,有效防止Java核心API被篡改

源码分析

类加载器之间的父子层级关系

类加载器之间的父子层级关系体现在Launcher类的无参构造器

package sun.misc;public class Launcher {// ...private ClassLoader loader;// ...// 无参构造器public Launcher() {ExtClassLoader var1;try {// 实例化ExtClassLoadervar1 = Launcher.ExtClassLoader.getExtClassLoader();} catch (IOException var10) {throw new InternalError("Could not create extension class loader", var10);}try {// 实例化AppClassLoader,并将ExtClassLoader作为其父加载器this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);} catch (IOException var9) {throw new InternalError("Could not create application class loader", var9);}// 将AppClassLoader作为线程上下文类加载器Thread.currentThread().setContextClassLoader(this.loader);// ...}static class AppClassLoader extends URLClassLoader {final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {// ...// 传过来的var0作为parentreturn new AppClassLoader(var1x, var0);}});}AppClassLoader(URL[] var1, ClassLoader var2) {// var2作为parentsuper(var1, var2, Launcher.factory);this.ucp.initLookupCache(this);}// ...}// ExtClassLoader,单例模式的体现static class ExtClassLoader extends URLClassLoader {private static volatile ExtClassLoader instance;public static ExtClassLoader getExtClassLoader() throws IOException {if (instance == null) {Class var0 = ExtClassLoader.class;synchronized(ExtClassLoader.class) {if (instance == null) {instance = createExtClassLoader();}}}return instance;}private static ExtClassLoader createExtClassLoader() throws IOException {try {return (ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<ExtClassLoader>() {public ExtClassLoader run() throws IOException {File[] var1 = Launcher.ExtClassLoader.getExtDirs();int var2 = var1.length;for(int var3 = 0; var3 < var2; ++var3) {MetaIndex.registerDirectory(var1[var3]);}return new ExtClassLoader(var1);}});} catch (PrivilegedActionException var1) {throw (IOException)var1.getException();}}// ...}
}

双亲委派的体现

双亲委派模型体现在ClassLoader类中的loadClass方法

package java.lang;public abstract class ClassLoader {// ...protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 通过完全限定名查看自己是否已经加载过Class<?> c = findLoadedClass(name);// 如果自己没有加载过if (c == null) {long t0 = System.nanoTime();try {// 如果父加载器不为空,就将类加载请求委托给父加载器if (parent != null) {c = parent.loadClass(name, false);} else {// 父加载器为空就代表当前类加载器为ExtClassLoader,就将类加载请求委托给BootstrapClassLoaderc = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// ...// 父加载器加载失败时,调用该方法完成类加载c = findClass(name);// ...}}// 加载时是否需要解析if (resolve) {resolveClass(c);}// 返回加载后生成的Class对象return c;}}// ...// 该方法是留给子类重写的protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);}// ...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920028.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920028.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920028.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【 限流技术 | 从四大限流算法到Redisson令牌桶实践 】

引言&#xff1a;为什么需要限流&#xff1f;在现代分布式系统中&#xff0c;服务的稳定性是至关重要的。在遇到突发的请求量激增&#xff0c;恶意的用户访问&#xff0c;亦或是请求频率过高给下游服务带来较大压力时&#xff0c;我们常常需要通过缓存、限流、熔断降级、负载均…

深入解析Java NIO多路复用原理与性能优化实践指南

深入解析Java NIO多路复用原理与性能优化实践指南 技术背景与应用场景 在高并发网络编程中&#xff0c;传统的阻塞 I/O 模型往往因每个连接都占用一个线程或一个系统调用而导致线程资源浪费、线程切换开销剧增等问题&#xff0c;难以满足数万甚至数十万并发连接的负载要求。Jav…

目标检测数据集 第006期-基于yolo标注格式的汽车事故检测数据集(含免费分享)

目录 目标检测数据集 第006期-基于yolo标注格式的汽车事故检测数据集(含免费分享) 超实用汽车事故检测数据集分享&#xff0c;助力计算机视觉研究&#xff01; 1、背景 2、数据详情 数据集基本信息 结构组成 标注格式与示例 类标签说明 数据增强情况 3、应用场景 4、…

应用密码学(书籍学习笔记、基础知识) 一

本博客为读《应用密码学》所得笔记 文章目录一、 加密与解密1.2 秘钥Key1.2.1 引入秘钥K1.2.2 加密秘钥K1&#xff0c;解密秘钥K2二、对称算法 VS 公开密钥算法**① 对称算法** - 传统密码算法 **(Symmetric Algorithm) &#x1f511;****② 非对称算法特点** - 公开秘钥算法 *…

【攻防世界】Web_php_include

1.信息收集题目&#xff1a;Web_php_include &#xff1a;PHP文件包含漏洞2.思路&#xff1a;1.代码审计&#xff1a;<?php show_source(__FILE__); echo $_GET[hello]; $page$_GET[page]; while (strstr($page, "php://")) { //在一个字符串中查…

cmake--CPack/deb

deb包的需求 怎么使用cmake把项目的依赖想打包为deb包,把项目的可执行文件和依赖文件打包为deb包,又怎么样配置apt源,让项目在jenkins构建之后,可以通过sudo apt install 下载deb包和安装到任意主机上? 整体流程概览 使用CMake构建项目:确保你的项目可以被CMake正确编译…

七十五、【Linux数据库】部署Redis服务 、 部署LNMP+Redis

Redis 与 LNMP 集成功能概述 Redis 核心功能 内存数据存储:高速读写性能 数据结构丰富:字符串、哈希、列表、集合等 持久化支持:RDB快照和AOF日志 发布订阅:消息队列功能 高可用:主从复制、哨兵模式、集群 LNMP+Redis 集成价值 会话共享:多Web服务器共享Session 数据缓存…

从YOLOv5到RKNN:零冲突转换YOLOv5模型至RK3588 NPU全指南

从YOLOv5到RKNN&#xff1a;零冲突转换YOLOv5模型至RK3588 NPU全指南 在嵌入式AI领域&#xff0c;将训练好的深度学习模型高效部署到边缘设备的NPU&#xff08;神经网络处理器&#xff09;上是提升性能的关键。本文将详细介绍如何在Ubuntu 20.04环境下&#xff0c;将YOLOv5l模型…

DNS的解析过程是怎样的?它基于传输层的什么协议?

问题DNS的解析过程是怎样的&#xff1f;它基于传输层的什么协议&#xff1f;我的回答&#xff1a;DNS解析过程是将域名转换为IP地址的一系列步骤。这个过程涉及多级缓存和查询&#xff1a;首先是浏览器缓存&#xff0c;浏览器会先检查自己的DNS缓存是否有记录。接着是操作系统缓…

模拟互联网大厂Java面试:电商场景下的技术探讨

模拟互联网大厂Java面试&#xff1a;电商场景下的技术探讨 场景概述 在这场模拟面试中&#xff0c;我们设定了一位互联网大厂的面试官与候选人小C之间的对话。面试官严肃专业&#xff0c;而小C则是搞笑的“水货程序员”。通过三轮问答&#xff0c;我们探索了Java技术栈在电商场…

遥感机器学习入门实战教程|Sklearn案例⑤:集成学习方法全览

在机器学习的实际应用中&#xff0c;单一分类器往往存在局限&#xff1a;比如决策树容易过拟合&#xff0c;kNN 对噪声敏感&#xff0c;逻辑回归在高维数据下收敛慢。为了提升整体效果&#xff0c;我们通常会采用 集成学习&#xff08;Ensemble Learning&#xff09;。 这篇文章…

大模型在垂直场景中的创新应用:搜索、推荐、营销与客服的新玩法

1. 引言 背景介绍:简述大模型(如GPT、BERT等)的发展历程及其在AI领域的核心作用,强调其在垂直场景中的潜力。 主题聚焦:说明本文将深入探讨搜索、推荐、营销、客服四大场景,分析大模型带来的创新开发方式。 目的与意义:阐述新玩法如何提升效率、增强用户体验,并推动行业…

华为仓颉语言的class(类)初步

华为仓颉语言的class&#xff08;类&#xff09;初步 class 概念 【官方文档 https://cangjie-lang.cn/docs?url%2F1.0.0%2Fuser_manual%2Fsource_zh_cn%2Fclass_and_interface%2Fclass.html 】 class 是仓颉面向对象体系的核心&#xff0c;用来描述“引用类型”对象。与 s…

健康常识查询系统|基于java和小程序的健康常识查询系统设计与实现(源码+数据库+文档)

健康常识查询系统 目录 基于java和小程序的健康常识查询系统设计与实现 一、前言 二、系统设计 三、系统功能设计 小程序功能设计 后台功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xf…

MySQL的高可用+MHA

即MySQL 主从复制高可用架构&#xff0c;是一套优秀的MySQL 高可用解决方案&#xff0c;由日本 DeNA 公司 youshimaton 开发&#xff0c;主要用于保障 MySQL 数据库在主服务器出现故障时&#xff0c;能快速进行主从切换&#xff0c;减少数据库服务中断时间。其核心特点包括&…

淘宝pc端首页做了哪些性能优化?

淘宝PC端首页作为中国电商领域流量最大的页面之一&#xff0c;其性能优化手段可以说是业界标杆&#xff0c;非常全面和深入。这些优化不是单一技术&#xff0c;而是一个完整的体系。 我们可以从以下几个层面来分析和理解淘宝首页所做的性能优化&#xff1a; 一、核心指标与整体…

让医学数据更直观——MedCalc 23.1.7 最新版使用体验

软件介绍 MedCalc 23.1.7是一款功能强大的生物医学研究统计软件&#xff0c;专为医学科研人员和医疗保健专家设计。它提供了丰富的统计分析工具和方法&#xff0c;旨在帮助用户更好地分析和解释医学数据。以下是该软件的一些主要特点&#xff1a; 一、数据导入和管理 支持导…

Text2SQL、ChatBI简介

概述 传统BI的三大核心瓶颈&#xff1a; 问数之难&#xff1a;不同用户往往存在个性化的分析逻辑&#xff0c;尽管企业内部已经创建大量报表和看板&#xff0c;但仍然无法完全满足业务部门对数据的个性化需求。但传统BI门槛较高&#xff0c;非技术人员在统一培训前&#xff0…

神经网络中 标量求导和向量求导

0. 引出问题 在神经网络反向传播过程中 loss [loss₁,loss₂, loss₃]&#xff0c;为什么 ∂loss/∂w ∂loss₁/∂w ∂loss₂/∂w ∂loss₃/∂w ∂loss₁/∂w 和 loss 维度一样都是三位向量 &#xff0c;[∂loss₁/∂w, ∂loss₂/∂w, ∂loss₃/∂w] 就变成3*3的矩阵 如下所…

tcpdump命令打印抓包信息

tcpdump命令打印抓包信息 下面是在服务器抓取打印服务端7701端口打印 rootgb:/home/gb# ifconfig -a eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 10.250.251.197 netmask 255.255.255.0 broadcast 10.250.251.255inet6 fe80::76fe:48ff:fe94:5a5 …