1. 从JDK源码级别彻底刨析JVM类加载机制

news/2024/11/30 2:32:04/

JVM性能调优

  • 1. 类加载的运行全过程
    • 1.1 加载
    • 1.2 验证
    • 1.3 准备
    • 1.4 解析

本文是按照自己的理解进行笔记总结,如有不正确的地方,还望大佬多多指点纠正,勿喷。

课程内容:

1、从java.exe开始讲透Java类加载运行全过程

2、从JDK源码级别剖析JVM核心类加载器

3、从JDK源码级别剖析类加载双亲委派机制

4、手写自定义类加载器打破双亲委派机制

5、Tomcat类加载机制深度剖析

6、手写Tomcat类加载器实现多版本代码共存隔离

1. 类加载的运行全过程

当我们用java命令运行某个类的main函数的启动程序时,首先需要通过类加载器把主类加载到JVM中。

public class Math {public static final int initData = 666;public static User user = new User();public int compute() { //一个方法对应一块栈帧内存区域 int a = 1;int b = 2;int c = (a + b) * 10;return c;}public static void main(String[] args) {Math math = new Math();math.compute();}
}

通过Java命令执行代码的类加载全过程

在这里插入图片描述

其中loadClass的类加载过程有以下几步:

加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> 使用 >> 卸载

  • 加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等,在加载阶段会在内存区域生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
  • 验证:校验字节码文件的准确性;
  • 准备:给类的静态变量分配内存,并赋予默认值;
  • 解析:将符号引用替换为直接引用,该阶段会把一些静态方法替换为只想数据所在内存区域的指针或句柄(直接引用),这是所谓的静态链接过程,动态链接是在程序运行过程完成的将符号引用替换为直接引用;
  • 初始化:对类的静态变量初始化为指定的值,执行静态代码块;

在这里插入图片描述

1.1 加载

在加载阶段,虚拟机需要完成以下三件事情:

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

《Java虚拟机规范》对这三点的要求并不是特别具体,所以留给虚拟机实现与Java应用的灵活度非常大,例如我们通过一个类的全限定类名来获取定义此类的二进制字节流这条规则,它并没有指明二进制文件流必须得从某个Class文件中获取,确切的说根本没有指明说要从哪里获取,如何获取。这也是日后的JAR、WAR、EAR格式的基础。

这一阶段就是先把字节码文件丢到内存。但是加载之前要先验证一下。

1.2 验证

验证是连接的第一步,这一个阶段的目的是保证Class文件的字节流中包含的信息符合<JVM虚拟机规范>的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。验证阶段大致上会完成下面四个阶段的校验动作:

  1. 文件格式验证:这个阶段要验证字节流文件是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。例如:是否以魔数0xCAFEBABE开头,主次版本是否在当前Java虚拟机的接受范围之内等;
  2. 元数据验证:这个阶段主要是对字节码描述的信息进行语义分析,以确保其描述信息符合<Java语言规范>的要求,例如:这个类是否有父类,这个类是否继承了不允许继承的类(被final修饰的类)等;
  3. 字节码验证:这个阶段验证过程是最复杂的一个过程,主要目的是通过数据流分析和控制流分析,确定程序语义是合法的、符合逻辑的。在第二个阶段对元数据信息中的数据类型校验分析完毕后,这阶段就要对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机的行为。
  4. 符号引用验证:最后一个阶段校验行为发生在虚拟机将符号引用转换为直接引用的时候,这个转化动作在链接阶段的第三阶段-解析阶段中发生。符号引用验证可以看作是对类自身以外的各类信息进行匹配校验,通俗来说就是,该类是否缺少或被禁止访问它依赖的某些类、方法、字段等资源。

在这里插入图片描述

在这里插入图片描述

1.3 准备

准备之前要先验证各种格式等是否正确。准备就是把静态变量初始值赋值。这个赋值与最终值没有关系,比如Boolean就会赋值false,int就先赋值为0这种。

在这里插入图片描述

1.4 解析

解析阶段是将Java虚拟机将常量池内的符号引用替换直接引用的过程。

  • 符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义地定位到目标即可。
  • 直接引用:直接引用是可以直接指向目标的指针、相对偏移量或者是一个能简介定位到目标的句柄。

http://www.ppmy.cn/news/95911.html

相关文章

科技的力量:致敬全国科技工作者

在这个日新月异的时代&#xff0c;科技的力量正在改变着我们的生活。为了庆祝5月30日的全国科技者工作日&#xff0c;我们特地上线本次创作活动&#xff0c;向所有为科技进步付出辛勤努力的科技工作者们致敬。在这篇博文中&#xff0c;我们将通过讲述科技发展的故事、分享技术成…

洛谷01背包变形(P1858多人背包)

多人背包 文章目录 一、问题简述二、问题分析三、代码参考 一、问题简述 DD 和好朋友们要去爬山啦&#xff01; 他们一共有 K 个人&#xff0c;每个人都会背一个包。这些包 的容量是相同的&#xff0c;都是 V。可以装进背包里的一共有 N 种物品&#xff0c;每种物品都有 给定…

【地铁上的面试题】--基础部分--数据结构与算法--数组和链表

零、章节简介 《数据结构与算法》是《地铁上的面试题》专栏的第一章&#xff0c;重点介绍了技术面试中不可或缺的数据结构和算法知识。数据结构是组织和存储数据的方式&#xff0c;而算法是解决问题的步骤和规则。 这一章的内容涵盖了常见的数据结构和算法&#xff0c;包括数组…

NodeJs服务链路追踪日志

&#xff08;逆境给人宝贵的磨炼机会。仅有经得起环境考验的人&#xff0c;才能算是真正的强者。自古以来的伟人&#xff0c;大多是抱着不屈不挠的精神&#xff0c;从逆境中挣扎奋斗过来的。——松下幸之助&#xff09; 服务链路追踪 服务的链路追踪指我们可以通过一个标记&am…

javascript基础八:JavaScript原型,原型链 ? 有什么特点?

一、原型 JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象 当试图访问一个对象的属性时&#xff0c;它不仅仅在该对象上搜寻&#xff0c;还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&#xff0c;直到找到一个…

阿里云ECS部署Trojan代理

项目地址&#xff1a;GitHub - Jrohy/trojan: trojan多用户管理部署程序, 支持web页面管理 一、容器部署&#xff1a; docker run --name trojan-mariadb --restartalways -p 3306:3306 -v /home/mariadb:/var/lib/mysql -e MYSQL_ROOT_PASSWORDtrojan -e MYSQL_ROOT_HOST% -e…

Vue3 除了 keep-alive,还有哪些实现页面缓存的方法

有这么一个需求&#xff1a;列表页进入详情页后&#xff0c;切换回列表页&#xff0c;需要对列表页进行缓存&#xff0c;如果从首页进入列表页&#xff0c;就要重新加载列表页。 对于这个需求&#xff0c;我的第一个想法就是使用keep-alive来缓存列表页&#xff0c;列表和详情…

大数据治理入门系列:数据治理

在信息经济时代&#xff0c;数据是企业的一大关键资产。为了制定科学、有效、合理的决策&#xff0c;企业需要收集大量的数据并进行各种数据分析&#xff0c;为决策提供依据。在此过程中&#xff0c;收集数据的速度、数据的质量和可靠性、对数据的分析过程、合适的分析工具等&a…