JVM 虚拟机

ops/2024/10/15 22:13:30/

JVM 是 Java Virtual Machine 的简称,意为 Java 虚拟机,虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机有:JVM、VMwave、Virtual Box等。JVM 是一台被定制过的现实当中不存在的计算机;

一、JVM 执行流程

JVM 是 Java 运行的基础,也是实现一次编译到处执行的关键;程序在执行前,首先要将 Java 代码(.java 文件)编译为字节码(.class 文件),JVM 把编译后的字节码通过类加载器(ClassLoader)—— 把文件加载到内存中的 —— 运行时数据区(Runtime Data Area),而字节码文件是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解释器 —— 执行引擎(Execution Engine)将字节码翻译为底层系统指令再交给 cpu 去运行,而这个过程需要调用其他语言的接口 —— 本地库接口(Native Interface)来实现;

即 JVM 主要通过以下四部分来执行 Java 程序;

类加载器,运行时数据区,执行引擎,本地库接口;

二、JVM 内存区域划分

一个运行起来的 Java 进程,需要从操作系统中申请一块内存区域;

JVM 运行时数据区域也叫内存区域,由以下 5 大部分组成:

1. 方法区 / 元数据区(线程共享)

用来存储被虚拟机加载的类信息、常量池、静态变量、即时编译器编译后的代码等数据;

常量池存放字面量和符号引用:

字面量:字符串常量(JDK 8 移动到了堆中),final 常量,基本数据类型的值;

符号引用:类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符;

2. 堆区(线程共享)

程序中创建的所有对象都在保存在堆中,堆里面分为两个区域:新生代和老年代,新生代放新建的对象,当新生代的对象经过一定 GC 次数之后还存活的对象会放入老年代

3. 虚拟机栈(线程私有)

Java 虚拟机栈的生命周期和线程相同,Java 虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息;

1)局部变量表:存放了编译器可知的各种基本数据类型(8 大基本数据类型)、对象引用,局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小;简单来说就是存放方法参数和局部变量

2)操作栈:每个方法会生成一个先进后出的操作栈;

3)动态链接:指向运行时常量池的方法引用;

4)方法返回地址:PC 寄存器的地址;

4. 本地方法栈(线程私有)

本地方法栈和虚拟机栈类似,本地方法栈是给本地方法(用 native 关键字修饰,在 JVM 内部通过 C++ 实现)使用的,即存放了 JVM 内部 C++ 方法的调用关系

5. 程序计数器(线程私有)

用来记录当前线程执行的行号的,程序计数器是一块比较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器;

三、类加载过程

一个类的生命周期如下:

其中前五步都属于类加载的过程;

1. 加载 

根据全限定类名找到该类的字节码文件,并在内存中生成一个代表这个类的 java.lang.Class对象,作为方法区这个类的各种数据的访问入口;

2. 验证

字节码文件是一个二进制格式的文件,需验证当前字节码格式是否符合 Java 虚拟机规范的全部要求,保证字节码中信息被当作代码运行后不会危害虚拟机自身的安全;

3. 准备

为类对象分配内存空间,但并不赋值(真正初始化赋值是在初始化阶段);例如下面的代码:

public static int num = 100;

这个阶段之后,num 的值为 0,而非 100;

但如果是 static final 修饰的基本数据类型的直接赋值方式,或 String 类的直接赋值方式,则会直接在该阶段初始化并赋值;例如

public static final int num = 100;

public static final String str = "abc";

此时 num 的值就是 100,str 的值为 "abc"; 

4. 解析

针对类对象中包含的字符串常量进行初始化操作;

String s = "abc";

s 的初始化语句,会先被设置为一个 "文件的偏移量",当类真正被加载到内存时,再把偏移量替换为真正的内存地址,这个过程也称为将符号引用替换为直接引用; 

5. 初始化

Java 虚拟机真正开始执行类中编写的 Java 程序代码,真的类对象进行初始化,加载父类包括类对象的各个属性,static 成员,静态代码块;

会导致类的初始化的情况

  1. 首次访问这个类的静态变量或静态方法时(由于 main 方法是程序的入口方法,并且main 方法是 static 的,所以 main 方法所在的类,会被首先初始化,但也遵循第 2 条);
  2. 子类初始化,如果父类还未初始化,会先初始化父类; 
  3. 子类访问父类的静态变量,只会触发父类的初始化;
  4. new 会导致初始化;

不会导致类的初始化的情况: 

  1. 访问类的 static final 静态常量(基本类型和字符型)不会触发初始化;
  2. 类对象.class 不会触发初始化;
  3. 创建该类的数组时不会触发初始化;

四、双亲委派模型

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每⼀个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载;(查找类的优先级问题) 

类加载器要做的就是根据给定类的全限定类名(包名+类名,例如 java.lang.String)找到其对应的字节码文件,对应类加载过程中的第一步;

JVM 内置了三个类加载器,分别是

启动类加载器:BootStrap ClassLoader;

扩展类加载器:Extension ClassLoader;

应用程序类加载器:Application ClassLoader;

这三个类由上到下是 "爷,父,子" 的关系,但并不是继承的关系,而是 ClassLoader 中,有一个 parent 属性,指向了它的 "父加载器";

若开发人员想要自己实现一个类加载器,需要继承 java.lang.ClassLoader 抽象类;

由一个类的全限定类名,找该类的字节码文件的过程大致如下:

1)从 Application ClassLoader 作为入口,开始查找,Application ClassLoader 负责搜索项目目录和第三方库目录,但是它不会立即寻找,而是交给它的父亲 Extension ClassLoader;

2)Extension ClassLoader 负责 JDK 中扩展的库的目录,但是它也不会立即寻找,而是交给它的父亲 BootStrap ClassLoader;

3)BootStrap ClassLoader 负责标准库的目录,此时,如果在标准库中找打了,则开始读取该字节码文件,若没有找到,则返回给它的孩子寻找;

若最终 Application ClassLoader 也没有找到该类,则会抛出 ClassNotFoundException


http://www.ppmy.cn/ops/47854.html

相关文章

酒茶元宇宙 - 探索味觉与科技的融合奇迹

在追求创新和完美体验的新时代,酒茶文化也迎来了前所未有的变革——"酒茶元宇宙"。这一概念不仅重新定义了我们对于酒茶享受的理解,更为酒茶爱好者及业界人士提供了一个独特的交流平台。让我们一起探索这个将传统饮品与现代科技完美融合的全新…

python tqdm怎么安装

tqdm是一个显示循环的进度条的库。taqadum, تقدّم)在阿拉伯语中的意思是进展。tqdm可以在长循环中添加一个进度提示信息,用户只需要封装任意的迭代器 tqdm(iterator),是一个快速、扩展性强的进度条工具库。 tqdm库的安装 在CMD窗口下输…

区块链简要介绍及运用的技术

一、区块链的由来 区块链概念最早是从比特币衍生出来的。 比特币(Bitcoin)诞生于2008年,是由一个名叫中本聪(Satoshi Nakamoto)的人首次提出,这个人非常神秘,至今没有他的任何准确信息。在提出…

2024河南高考作文ChatGPT

阅读下面的材料,根据要求写作。(60分) 随着互联网的普及、人工智能的应用,越来越多的问题能很快得到答案。那么,我们的问题是否会越来越少? 以上材料引发了你怎样的联想和思考?请写一篇文章。 要…

Windows系统电脑本地部署AI音乐创作工具并实现无公网IP远程使用

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 本文主要介绍如何在Windows系统电脑上快速本地部署一个文字生成音乐的AI创作工具MusicGPT,并结合cpolar内网穿透工具实现随时随地远程访问使用。 MusicG…

Spring Cloud Gateway中的GlobalFilter:构建强大的API网关过滤器

在微服务架构中,API网关扮演着至关重要的角色,负责路由、过滤、以及对进入微服务集群的请求进行预处理。Spring Cloud Gateway作为Spring Cloud生态中的一款高性能API网关,提供了丰富的功能来满足这些需求。其中,GlobalFilter是一…

链表的回文结构OJ

链表的回文结构_牛客题霸_牛客网对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为。题目来自【牛客题霸】https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId49&&tqId29370&rp1&a…

基于简单Agent对医疗数据进行分析

数据表 供应商资格审核规定.pdf 医生名录.xlsx 历史就诊记录.xlsx 患者信息名录.xlsx 药品.xlsx 药品库存管理.xlsx 采购单位基本信息.xlsx Agent测试 模型基于ChatGPT-3.5 问题:帮我找出不达标的供应商 Agent分析过程 [Thought: 0] Key Concepts: - 不达标的供…