面试题解,JVM中的“类加载”剖析

一、JVM类加载机制说一下

其中,从加载到初始化就是我们的类加载阶段,我们逐一来分析

加载

“加载 loading”是整个类加载(class loading)过程的一个阶段,加载阶段JVM需要完成以下 3 件事情:

  • 1)通过一个类的全限定名来获取定义此类的二进制字节流。
  • 2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(Class,Field,Method)。
  • 3)在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。

注意:

  • 加载的字节码来源,不一定非得是class文件,可以是符合字节码规范的任意地方,甚至二进制流等
  • 从字节码到内存,是由加载器(ClassLoader)完成的

验证

  • 1、文件格式验证(版本号,是不是CAFEBABYE开头,..........
  • 2、元数据验证(验证属性、字段、类关系、方法等是否合规)
  • 3、字节码验证
  • 4、符号引用验证
  • 等等...

准备

为class中定义的各种类变量(静态变量)分配内存,并赋初始值,注意是对应类型的初始值,赋具体值在后面的初始化阶段。注意!即便是static变量,它在这个阶段初始化进内存的依然是该类型的初始值(零默认值等)!而不是用户代码里的初始值。

举例:

//类变量:在准备阶段为它开辟内存空间,但是它是int的初始值,也就是 0,而真正123的赋值,是在下面的初始化阶段 
public static int a = 123; //类成员变量(实例变量)的赋值是在类对象被构造时才会赋值 
public String address = "北京" //final修饰的类变量,编译成字节码后,是一个ConstantValue类型,在准备阶段,直接给定值123,后期也没有二次初始化一说 
public static final int b = 123;

解析

将常量池内的符号引用替换为直接引用的过程。

符号引用是以一组描述符(如类名、字段名和方法签名等)来表示的,而直接引用则是可以直接指向目标实体(如类、字段或方法)的具体内存地址或偏移量。

初始化

类加载的最后一个步骤,经过这个步骤后,类信息完全进入了jvm内存,直到它被垃圾回收器回收

前面几个阶段都是JVM来搞定的。我们也干涉不了,从代码上只能遵从它的语法要求。而这个阶段,是初始化赋值,java虚拟机才真正开始执行类中编写的java程序代码,将主导权移交给应用程序。

所以在这个阶段是执行类中和static相关的所有事,比如静态代码块,静态变量赋值等

那么这些事都会经过javac编译器自动将这些事情编到<clinit>函数

<clinit> 函数是由编译器自动收集类中的所有静态变量的赋值动作和静态语句块( static 代码块)中的语句合并产生的。

<clinit> 函数与类的构造函数(虚拟机视角的 <init> 函数)是不同的, <init> 函数是在运行期创建对象时才执行,而 <clinit> 在类加载的时候就执行了。

虚拟机能保障父类的 <clinit> 函数优先于子类 <clinit> 函数的执行

在 <clinit> 函数中会对类变量赋具体的值,也就是我们说的:

public static int a = 123; 1

这行代码的123才真正赋值完成。

二、双亲委派机制的过程及作用,三种类加载器,加载过程,双亲委派机制能打破吗?

三种类加载器

先来说一下三种类加载器,类加载器做的事情就是上面 5 个步骤的事(加载、验证、准备、解析、初始化),java提供了3个系统加载器,分别是 Bootstrap ClassLoader、ExtClassLoader 、AppClassLoader

每个类加载器加载不同路径下的类

Bootstrp加载器是用 C++ 语言写的,它在Java虚拟机启动后初始化,它主要负责加载以下路径的文件:

  • %JAVA_HOME%/jre/lib/*.jar
  • %JAVA_HOME%/jre/classes/*
  • -Xbootclasspath 参数指定的路径

ExtClassLoader 是用 Java 写的,具体来说就是sun.misc.Launcher$ExtClassLoader,主要加载:

  • %JAVA_HOME%/jre/lib/ext/*
  • ext 下的所有 classes 目录
  • java.ext.dirs 系统变量指定的路径中类库

AppClassLoader 也是用Java写成的,它的实现类是sun.misc.Launcher$AppClassLoader ,另外我们知道 ClassLoader 中有个getSystemClassLoader 方法,此方法返回的就是它。

  • 负责加载 -classpath 所指定的位置的类或者是jar文档
  • 也是Java程序默认的类加载器

双亲委派模型

双亲委派模型的核心就是,当前类加载器在加载一个类时,先委派给其父加载器,如果父加载器已经加载过了,那么自己就不再加载了。

具体一点来说:

        类加载器加载某个类的时候,因为有多个加载器,甚至可以有各种自定义的,他们呈父子关系。这给人一种印象,子类的加载会覆盖父类,其实恰恰相反!

        与普通类继承属性不同,类加载器会优先调父类的 loadClass 方法,如果父类能加载,直接用父类的,否则最后一步才是自己尝试加载,从源代码上可以验证。

那为什么这么设计呢?

双亲委派模型作用

避免重复加载、 核心类篡改

        采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父加载器已经加载了该类时,就没有必要子加载器再加载一次。

        其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为 java.lang.Integer 的类,通过双亲委派模型传递到启动类加载器,而启动类加载器发现这个名字的类,发现该类已被加载,就不会重新加载网络传递过来的 java.lang.Integer ,而直接返回已加载过的Integer.class ,这样便可以防止核心API库被随意篡改。

双亲委派能否打破

比如:Tomcat的 webappClassLoader 加载web应用下的class文件,不会传递给父类加载器,

问题:tomcat的类加载器为什么要打破该模型?

首先一个tomcat启动后是会起一个jvm进程的,它支持多个web应用部署到同一个tomcat里,为此

  • 1、对于不同的web应用中的class和外部jar包,需要相互隔离,不能因为不同的web应用引用了相同的jar或者有相同的class导致一个加载成功了另一个加载不了。
  • 2、web容器支持jsp文件修改后不用重启,jsp文件也是要编译成.class文件的,每一个jsp文件对应一个JspClassLoader,它的加载范围仅仅是这个jsp文件所编译出来的那一个.class文件,当Web容器检测到jsp文件被修改时,会替换掉目前JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的热部署功能。

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

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

相关文章

腾讯云AI代码助手编程挑战赛-古诗词学习

一、作品介绍 在科技与文化深度交融的当下&#xff0c;“腾讯云 AI 代码助手编程挑战赛 - 每日古诗词” 宛如一颗璀璨的新星&#xff0c;闪耀登场。它绝非一场普通的赛事&#xff0c;而是一座连接编程智慧与古典诗词韵味的桥梁。 这项挑战赛以独特的视角&#xff0c;将每日古…

GelSight Mini视触觉传感器凝胶触头升级:增加40%耐用性,拓展机器人与触觉AI 应用边界

马萨诸塞州沃尔瑟姆-2025年1月6日-触觉智能技术领军企业Gelsight宣布&#xff0c;旗下Gelsight Mini视触觉传感器迎来凝胶触头的更新。经内部测试&#xff0c;新Gel凝胶触头耐用性提升40%&#xff0c;外观与触感与原凝胶触头保持一致。此次升级有效满足了客户在机器人应用中对设…

【C++入门】详解(上)

目录 &#x1f495;1.C中main函数内部———变量的访问顺序 &#x1f495;2.命名空间域namespace &#x1f495;3.命名空间域&#xff08;代码示例&#xff09;&#xff08;不要跳&#xff09; &#x1f495;4.多个命名空间域的内部重名 &#x1f495;5.命名空间域的展开 …

Ungoogled Chromium127 编译指南 MacOS篇(八)- 开始编译

1. 引言 完成了所有依赖包的安装后&#xff0c;我们终于来到了最关键的编译阶段。在开始编译之前&#xff0c;有一些重要的配置信息需要了解。本文将指导您完成整个编译过程。 2. 签名相关说明 虽然在我们的测试编译中不需要进行签名操作&#xff0c;但了解官方的签名要求仍…

使用uniapp 微信小程序一些好用的插件分享

总结一下自己在开发中遇见的一问题&#xff0c;通过引入组件可以快速的解决 1.zxz-uni-data-select 下拉框选择器(添加下拉框检索&#xff0c;多选功能&#xff0c;多选搜索功能&#xff0c;自定义 下拉框插件&#xff0c;使用这个的原因是因为 uniui uview 组件库下拉框太…

腾讯云AI代码助手编程挑战赛-有趣的冷知识分享

作品简介 有趣的冷知识这一编程主要用于对于小朋友的探索力的开发&#xff0c;让小朋友在一开始就对学习具有探索精神。在信息化时代下&#xff0c;会主动去学习自己认知以外的知识&#xff0c;同时丰富了眼界&#xff0c;开拓了新的知识。 技术架构 使用python语言的TK库…

使用 SQL 和表格数据进行问答和 RAG(7)—将表格数据(CSV 或 Excel 文件)加载到向量数据库(ChromaDB)中

将表格数据&#xff08;CSV 或 Excel 文件&#xff09;加载到向量数据库&#xff08;ChromaDB&#xff09;中。这里定义的类 PrepareVectorDBFromTabularData&#xff0c;它的主要功能是读取表格数据文件到DataFrame中、生成嵌入向量、并将这些数据存储在向量数据库的集合中&am…

攻防世界 wtf.sh-150

点进去&#xff0c;发现是一个类似于论坛的网站&#xff0c;并且对报错等做了处理 用御剑扫描一下 ​ 发现是php形式的文件&#xff0c;但点进去访问不了。看看wp&#xff0c;发现此题存在路径穿越漏洞&#xff0c;就是&#xff08;如果应用程序使用用户可控制的数据&#xff0…

【Spring】Redis缓存+ehcache

文章目录 基于Spring的RedisehcacheRedis 缓存配置Cacheable 注解CacheEvict 注解缓存配置 基于Spring的Redisehcache Redis 缓存配置 在项目中添加 Redis 的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot…

UE5 打包要点

------------------------- 1、需要环境 win sdk &#xff0c;大约3G VS&#xff0c;大约10G 不安装就无法打包&#xff0c;就是这么简单。 ----------------------- 2、打包设置 编译类型&#xff0c;开发、调试、发行 项目设置-地图和模式&#xff0c;默认地图 项目…

小程序textarea组件键盘弹起会遮挡住输入框

<textarea value"{{remark}}" input"handleInputRemark" ></textarea> 如下会有遮挡&#xff1a; 一行代码搞定 cursor-spacing160 修改后代码 <textarea value"{{remark}}" input"handleInputRemark" cursor-spacin…

git的rebase和merge的区别?

B分支从A分支拉出 1.git merge 处于A分支执行&#xff0c;git merge B分支:相当于将commit X、commit Y两次提交&#xff0c;作为了新的commit Z提交到了A分支上。能溯源它真正提交的信息。 2.git rebase 处于B分支&#xff0c;执行git rebase A分支&#xff0c;B分支那边复…

Cadence——virtuous生成的symbol其端口自动添加注释

新换的工艺库&#xff0c;环境变量也会发生变化&#xff0c;毕竟每一家PDK下的.cdsinit 和 .cdsenv文件不尽相同。 这次新换的PDK&#xff0c;搭建完Schcematic之后&#xff0c;再生成的Symbol&#xff0c;发现其pin口&#xff0c;也就是端口没有自动生成注释&#xff0c;我就…

CClinkIEfield Basic转Modbus TCP网关模块连接三菱FX5U PLC

捷米特JM-CCLKIE-TCP是自主研发的一款CCLINK IE FB从站功能的通讯网关。该产品主要功能是将各种 MODBUS-TCP 设备接入到 CCLINK IE FB网络中。 捷米特JM-CCLKIE-TCP网关连接到CCLINK IE FB总线中做为从站使用&#xff0c;连接到 MODBUS-TCP 总线中做为主站或从站使用。 为了打破…

《分布式光纤测温:解锁楼宇安全的 “高精度密码”》

在楼宇建筑中&#xff0c;因其内部空间庞大&#xff0c;各类电器设施众多&#xff0c;如何以一种既高效又稳定&#xff0c;兼具低成本与高覆盖特性的方式&#xff0c;为那些关键线路节点开展温度监测&#xff0c;是目前在安全监测领域一项重点研究项目&#xff0c;而无锡布里渊…

开关电源设计中的穿越频率选取

摘要 在开关电源设计之中&#xff0c;穿越频率是一个相当重要的指标。在文中从就开关电源设计中的环路反馈控制方法、环路增益作用进行了阐述。并在此基础上就穿越频率选取的限制条件进行分析&#xff0c;为开关电源设计中的穿越频率选取提供借鉴。 开关电源设计过程中&#x…

探索 INFINI Console:提升 Elasticsearch 管理效率的新利器

1、常见的 Elasticsearch 可视化客户端介绍 1.1 Head 插件 这是一个非常老牌的 Elasticsearch 可视化插件&#xff08;现在改名了 Multi Elasticsearch Heads&#xff09;&#xff0c;通常以 Chrome 插件或网页形式存在&#xff0c;用来查看集群的节点状态、索引元数据&#x…

黄仁勋CES 2025演讲重点内容

黄仁勋CES 2025演讲重点内容 硬件产品发布 GeForce RTX 50系列GPU&#xff1a; 架构与性能提升&#xff1a;正式发布的新一代GeForce RTX 50系列GPU采用英伟达旗舰的Blackwell架构&#xff0c;这是自25年前引入可编程着色技术以来计算机图形领域最重大的创新。该系列显卡在图形…

【Redis】简介|优点|使用场景|为什么Redis快

目录 一、简介 二、特性&#xff08;优点&#xff09; 三、使用场景 一、简介 内存中存储数据的中间件&#xff0c;用于数据库&#xff0c;数据缓存&#xff0c;在分布式系统中能够大展拳脚 中间件&#xff1a;应用程序可以直接从 Redis 中获取数据&#xff0c;而不必频繁地…

UI自动化测试框架playwright--初级入门

一、背景&#xff1a;UI自动化的痛点&#xff1a; 1、设计脚本耗时&#xff1a; 需要思考要如何模拟用户的操作&#xff0c;如何触发页面的事件&#xff0c;还要思考如何设计脚本&#xff0c;定位和操作要交互的元素、路径、位置&#xff0c;再编写代码逻辑&#xff0c;往复循…