Java虚拟机:虚拟机介绍
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 033 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。
–
在当今的软件开发领域,Java 虚拟机(JVM)扮演着至关重要的角色,它不仅是 Java 语言的运行时环境,也是跨平台应用的基石。理解 JVM 的原理和功能,对 Java 开发者来说至关重要。本篇文章将带你全面了解 JVM 的起源、结构和工作原理,帮助你奠定扎实的基础,为后续深入研究 JVM 的各个方面做好准备。
文章目录
- 1、对于 Java 虚拟机的认知
- 1.1、Java 虚拟机(Jvm) 与 Java 语言的关系
- 1.2、one write run anywhere(一次编写到处运行)
- 1.2.1、C 语言的编译过程
- 1.2.2、如何理解汇编语言
- 1.2.3、C 语言为什么不能跨平台
- 1.2.4、Java 为什么可以跨平台
- 2、Java 虚拟机的基础知识
- 2.1、Java 虚拟机概述
- 2.2、JVM、JRE、JDK的关系
- 2.3、Java 虚拟机的结构组成
1、对于 Java 虚拟机的认知
1.1、Java 虚拟机(Jvm) 与 Java 语言的关系
在我们系统的认识 Java 虚拟机前,我们应该明确一个事实,即:“Java 虚拟机不和包括 Java 在内的任何一种语言绑定,它只与 ‘Class文件’ 这种特定的二进制文件格式所关联,Class 文件中包含了 Java 虚拟机指令集和符号表以及若干其他辅助信息”。
所以 “Java 虚拟机” 这一命名本身有一定的误导性,Java 虚拟机和 Java 语言并不存在必要的联系,将其称作 “Class 文件虚拟机” 可以更适合理解。
Java 在 1997 年发布规范文档的时候,也刻意的将 Java 的规范拆分为《 Java 语言规范(The Java Language Specification)》与 《Java 虚拟机规范(The Java Virtual Machine Specification)》两部分。
Java 语言规范 & Java 虚拟机规范:https://docs.oracle.com/javase/specs/
Java 虚拟机是语言无关性的,作为一个通用的、与机器无关的执行平台,任何其他语言的实现都可以将 Java 虚拟机作为其运行的基础,以 Class 文件作为他们产品的交付媒介。
例如,使用 Java 编译器可以把 Java 代码编译为存储字节码的 Class 文件,使用 JRuby 等其他语言的编译器一样可以把它们的源程序代码编译成 Class 文件。虚拟机丝毫不关心 Class 的来源是什么语言,它与程序语言之间的关系如图所示:
1.2、one write run anywhere(一次编写到处运行)
在我们初次接触 Java 时,都不可不避免的了解到,Java 的一个优势,也是 Java 刚推出时的宣传语:“one write run anywhere(一次编写到处运行)”,在这句话中,突出了 Java 虚拟机核心的思想,Java 虚拟机是与平台无关的,或者说 Java 虚拟机具有平台无关性!
1.2.1、C 语言的编译过程
既然 Java 虚拟机具有平台无关性,那么什么是平台有关性呢,我们先来看一下,C 语言的执行过程:
#include <stdio.h>
int main()
{printf("hello world");return 0;
}
这是一个 C 语言的程序,最终的至执行结果是打印一行 “hello world” 字符串,我们知道,计算机里的世界里只有 “0” 和 “1”,那以上的 C 程序是如何转换为 “0” 和 “1” 的呢?
以上 C 程序的编译过程:
我们分阶段来讨论:
- 首先是 “预处理阶段” :预处理器(cpp)会将头文件(# 开头的行)展开,将宏名替换为字符串,并将注释去掉;
- 接下来是 “编译阶段” :编译器(ccl)将修改后的
.c
文件,翻译为.s
文件,即汇编程序; - 再然后是 “汇编阶段” :汇编器(as)将
.s
文件翻译成.o
文件,这就是机器语言指令,二进制文件; - 在最后是 “链接阶段” :链接器(ld)将
.o
文件中的函数库对应的代码组合到最终目变文件中,这就是.out
文件了。
1.2.2、如何理解汇编语言
作为一个插曲,在这里阐述一下笔者对于汇编语言的理解。
什么是汇编语言,其实就是因为计算机只能识得 “0” 和 “1”,在计算机刚被发明时,科学家们只能通过向计算机输入 0|1 代码的方式(通过穿孔纸带,有孔 1,无孔 0),来运行计算任务,但是这样的效率实在太慢了,所以汇编语言就被发明出来,用于简化程序的编写。
比如计算 1+1
,两个 “1” 数据使用 0x0001
来表示,而 “加” 操作,放在 CPU 中,可以是 0xa90df
(这个是胡乱写的),这个二进制代表的加操作能被计算机识别。而因为这个加操作对于 CPU 来说,编码的 0xa90df
格式是固定的。所以可以直接一个助记符 add
来表示,这样科学家们写程序就方便多了。而这就是汇编程序的由来。因为汇编程序完成之后,可以再有一个专门的程序(就是要上文中所说的汇编器)来把编写的汇编程序编译成 “0” 和 “1”,这样计算机也可以识别了,而汇编语言本身也方便了程序的编写和阅读。
编写汇编比直接编写二进制方便高效了太多。但是随着计算任务的复杂,程序的规模越来越庞大,使用汇编程序也很累啊,那么是否有更简单的方式呢?所以科学家们发明了高级语言(比如 C,lisp 等),在编写程序的时候,使用 C。语言等编写,然后再使用编译器将 C 语言程序翻译成汇编程序,汇编程序再使用汇编器编译成 “0” 和 “1”,这样,CPU 能识别的东西没有变化,但是对于编写程序的人,确实方便了很多。
通过以上的描述,我们就知道了高级语言的大概由来。也明白了我们所编写的各种高级语言,到了最后,其实都是转化为二进制执行。
1.2.3、C 语言为什么不能跨平台
在对汇编语言再一次理解之后,我们回到正题,即为什么 C 语言不具备平台无关性,或者说为什么 C 语言为什么不能跨平台。
直接二进制格式的程序,我们称之为本地机器码(native code)。而类似那些 add
之类的助记符,以及汇编的编写格式或标准,我们称之为指令集。
但是问题的关键来了。不同公司所生产的 CPU 芯片。他们所使用的指令集不同啊,这种芯片设计的事情,又不像 TCP/IP 协议那样,有国际统一的标准,甚至像 Intel 所代表的复杂指令集,和 ARM 为代表的精简指令集,它们指令集的设计思路就是不一样的。
所以我们 C 语言最后编译出来的的二进制文件,不同的 CPU 上识别的意义是完全不同的。
此外,还有一种场景,就是一段 C 语言的程序,我们编写一个 .c
的文件后,将其拿到另外一个操作系统|CPU 平台去执行,是否会成功呢?成功了之后那么是否可以说明 C 语言具有跨平台性呢,很多人存在着不同的看法,对此,笔者是这样认为的:
- C 语言并非不能跨平台(CPU 或者操作系统),准确的说是 C 语言编译出的程序无法二进制跨平台;
- 不同环境下,C 语言的标准有差别,比如不同平台的 int 类型可能是 16 位表示也可能是 32 位表示,但笔者认为这种情况是可以有多种方式去规避的,随意最终的结论还是 C 语言不能跨平台是特指二进制跨平台。
那有没有一种办法,能够让高级语言实现(二进制)跨平台的运行呢?
思考实际编程中的一个场景,我们前端需要处理的某个数据是 A 格式,但是后台只能提供B格式的数据,那我们怎么办?很简单啊。写个接口,把 B。格式转化为 A 格式。这就是设计模式当中的适配器设计模式。
关于跨平台也是一样的道理。CPU 的指令集不同, 不同平台编译出来的结果格式都不同,那么我们可以在各个平台上运行虚拟机,然后我们制定某种编译结果的输出格式,我们的输出了某种格式的结果,直接在虚拟机上运行。 这就是 Java 采取的方式。
1.2.4、Java 为什么可以跨平台
这是 Java 版本的 “Hello World”:
public static void main(String[] args) {System.out.println("Hello World!");
}
这段 Java 程序编译出来的结果是 hello.class
,换句话说,它输出的结果是 Class 文件格式(也叫字节码存储格式)。
这其实就是 Java 虚拟机定义的二进制格式,这种我们称之为字节码(ByteCode),是 Java 虚拟机所能运行的格式。类似本地机器码可以反编译成汇编,这种二进制也可以反编译成更容易阅读的格式。
而各个平台的 Java 虚拟机 是不同的。但是我们编写的 Java 程序 统一编译成特定格式的 Class 文件格式,然后 Class 文件可以在各个不同平台的 Java 虚拟机上运行,当然运行结果肯定也是一致的,至于各个不同平台之间的差异,这是那些编写 Java 虚拟机的人去考虑的事情。
通过这种方式,我们的 Java 程序就实现了跨平台。
2、Java 虚拟机的基础知识
2.1、Java 虚拟机概述
Java 虚拟机(英语:Java Virtual Machine,缩写:JVM),一种能够执行 Java 字节码(Class 文件)的虚拟机,以堆栈结构机器来进行实做。最早由 Sun 公司所研发并实现第一个实现版本,是 Java 平台的一部分,能够执行以 Java 语言所写的软件程序。
Java 虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 Java 虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。通过对中央处理器(CPU)所执行的软件实现,实现能执行编译过的 Java 程序码(Applet 与应用程序)。
作为一种编程语言的虚拟机,实际上不只是专用于 Java 语言,只要生成的编译文件符合 JVM 对加载编译文件格式要求,任何语言都可以由 JVM 编译运行。此外,除了甲骨文,也有其他开源或闭源的实现。
2.2、JVM、JRE、JDK的关系
JVM 是 Java 程序能够运行的核心。但需要注意,JVM 自己什么也干不了,你需要给它提供生产原料(Class 文件)。 仅仅是 JVM,是无法完成一次编译,处处运行的。它需要一个基本的类库,比如怎么操作文件、怎么连接网络等。
而 Java 体系很慷慨,会一次性将 JVM 运行所需的类库都传递给它。JVM 标准加上实现的一大堆基础类库,就组成了 Java 的运行时环境,也就是我们常说的 JRE。
对于 JDK 来说,就更庞大了一些。除了JRE,JDK还提供了一些非常好用的小工具,比如 javac、java、jar 等。它是 Java 开发的核心。 我们也可以看下 JDK 的全拼,JavaDevelopmentKit。
JVM、JRE、JDK 它们三者之间的关系,可以用一个包含关系表示:
2.3、Java 虚拟机的结构组成
Java 虚拟机整体组成可分为四个部分:类加载器(Class Loader)、运行时数据区(Runtime Data Area)、执行引擎(Execution Engine)、本地库接口(Native Interface)
- 类加载器:负责从字节码 Class 文件中,加载 Class 信息到运行时数据区的方法区;
- 运行时数据区:存放 Jvm 在执行 Java 程序时相关数据的区域;
- 执行引擎:将字节码翻译成底层系统指令再交由 CPU 去执行;
- 本地库接口:执行过程中可能需要调用到其他语言(比如 C 语言)的本地接口。
Ps:Javac 是收录于 Jdk 中的 Java 语言编译器。该工具可以将 .java
源文件编译为 Class 文件(.class
文件)。
在程序被执行之前,Java 前, Java 代码会被先转换成字节码 Class 文件,Jvm 首先通过一定的方式使用「类加载器」把字节码文件加载到内存中「运行时数据区」,而字节码文件是 Jvm 提供的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器「执行引擎」将字节码翻译成底层系统指令再交由 CPU 去执行,而这个过程中需要调用其他语言的接口「本地库接口」,来实现整个程序的功能,这就是这 4 个主要组成部分的职责与功能。
相关文章:

Java虚拟机:虚拟机介绍
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 033 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...
硬件面试经典 100 题(31~40 题)CRE4
31、多级放大电路的级间耦合方式有哪几种?哪种耦合方式的电路零点偏移最严重?哪种耦合方式可以实现阻抗变换? 有三种耦合方式:直接耦合、阻容耦合、变压器耦合。直接耦合的电路零点漂移最严重,变压器耦合的电路可以实现…...

ReactNative笔记(自用)
环境 ios更换gem镜像源: 查看当前源: gem sources -l 移除默认源: gem sources --remove https://rubygems.org/。添加新的源: 添加 Ruby China 的镜像源: gem source -a https://gems.ruby-china.com/或者添加其他镜像源。 清华大学的gem源: htt…...
嵌入式八股-面试30题(20240812)
TCP和UDP的区别是什么? **TCP(Transmission Control Protocol)**是面向连接的协议,提供可靠的、顺序的数据传输。它通过三次握手建立连接,并在数据传输过程中使用确认和重传机制来确保数据的正确性。TCP还支持流量控制和拥塞控制…...
单一职责原则(SRP)
目录 1、定义 2、优点 3、原则的重要性 4、 示例 5、注意事项 单一职责原则(Single Responsibility Principle, SRP)是面向对象设计中的一项重要原则,属于 SOLID 原则之一。它的核心思想是:一个类应该只有一个引起它变化的原因&am…...

骨传导耳机怎么选?分享五款资深用户都说好的骨传导耳机!
在追求健康生活的道路上,运动健身已成为一种时尚潮流,而音乐则是这场潮流中不可或缺的催化剂。然而,传统耳机在运动场景下的局限性日益凸显,难以满足运动者对自由与舒适的双重追求。正是基于这样的市场需求,骨传导耳机…...
【计算机网络——分组延时,丢失,吞吐量】
处理延时:1检查分组首部信息,决定将该分组导向何处所需时间。2检查比特级别的差错所需时间:分析这个分组是否出错,目标IP地址字段提取出来,查路由表……。 传播延时和传输延时:传输延时就是分组到链路所需…...

使用1panel 申请证书配置雷池站点
1.创建测试站点 2.使用1panel申请测试站点的自签名证书 ps:雷池支持自签的证书 关于如果选择网站的SSL证书 百度搜索 看起来是证书的问题 调整了参数重新申请一个证书上传 注意,如果文件上传错了,雷池会报错,如下图 再次访问配…...

4章7节:用R做数据重塑,数据去重和数据的匹配
在数据科学的分析流程中,数据重塑是一项非常重要的操作。数据的重塑通常指将数据从一种形式转换为另一种形式,以满足后续分析的需求。R语言提供了丰富的工具和函数来帮助用户高效地进行数据重塑操作。本文中,我们将深入探讨数据重塑的概念及其…...

大数据面试SQL(七):累加刚好超过各省GDP40%的地市名称
文章目录 累加刚好超过各省GDP40%的地市名称 一、题目 二、分析 三、SQL实战 四、样例数据参考 累加刚好超过各省GDP40%的地市名称 一、题目 现有各省地级市的gdp数据,求从高到低累加刚好超过各省GDP40%的地市名称,临界地市也需要。 例如: 浙江省…...

建议收藏!这4款设计师常用的素材管理软件,助你工作效率翻倍!
嘿,设计师们!你是否还在为那一堆堆散乱的素材头疼?每次灵感来袭,却要花费大量时间在层层文件夹中苦苦搜寻?别急,今天我就来给大家推荐4款超给力的素材管理软件,它们不仅能帮你轻松整理素材库&am…...
用于NLP领域的排序模型最佳实践
在自然语言处理(NLP)领域,用于排序任务的模型通常是指那些能够对文本进行排序、比较或评估其相关性的模型。这些模型可以应用于诸如文档排序、句子排序、问答系统中的答案排序等多种场景。在当前的研究和发展中,基于深度学习的方法…...
域名未备案的支付平台遭遇大攻击怎么办
域名未备案的支付平台遭遇大攻击怎么办?在当今数字化时代,支付平台的安全与稳定性是保障业务连续性和用户信任的关键。然而,对于因域名未备案而面临法律风险的支付平台来说,其安全挑战更为严峻。当这类平台遭遇大规模的网络攻击&a…...

【NI-DAQmx入门】LabVIEW数据采集基础应用程序框架
对于可管理规模的 LabVIEW 程序,分析现有程序或设计新程序的方法通常是从整体到具体,即从高级到低级的分析和设计。从一开始就直接深入细节可能会效率较低。 在设计阶段,开发人员首先将程序垂直划分为几个层级。从最顶层开始,他们…...
海山数据库(He3DB)源码详解:CommitTransaction函数源码详解
文章目录 海山数据库(He3DB)源码详解:CommitTransaction函数1. 执行条件2. 执行过程2.1 获取当前节点状态:2.2 检查当前状态:2.3 预提交处理:2.4 提交处理:2.5 释放资源:2.6 提交事务: 作者介绍…...

【网络】传输层TCP协议的报头和传输机制
目录 引言 报头和有效载荷 确认应答机制 捎带应答机制 超时重传机制 排序和去重 连接管理机制 个人主页:东洛的克莱斯韦克-CSDN博客 引言 TCP是传输层协议,全称传输控制协议。TCP报头中有丰富的字段以及协议本身会制定完善的策略来保证网络传输的…...
【活动报名】打造编程学习“知识宝库”:高效笔记记录与整理指南
如何高效记录并整理编程学习笔记? 在编程学习的旅程中,拥有一套高效的笔记记录和整理方法至关重要。以下将从三个方向为您详细介绍如何打造属于自己的编程学习“知识宝库”。 方向一:笔记工具选择 选择合适的笔记工具是高效记录编程学习笔记…...

使用Arduino IDE生成带有bootloader的烧录文件
使用Arduino IDE生成bin(烧录)文件 1、在“项目”中,选择“导出已编译的二进制文件” 2、在工程目录中,会出现“build”文件夹 3、在build文件夹中,有hex文件,以及包含bootloader的bin和hex文件 bin和h…...

搭建高可用OpenStack(Queen版)集群(九)之部署nova计算节点
一、搭建高可用OpenStack(Queen版)集群之部署计算节点 一、部署nova 1、安装nova-compute 在全部计算节点安装nova-compute服务 yum install python-openstackclient openstack-utils openstack-selinux -y yum install openstack-nova-compute -y 若yu…...
C# 字符串扩展方法
功能 1.判断一个字符串是否为null或者空字符串 2.判断一个字符串是否为null或者空白字符 3.判断一个字符串是否为数字 4.判断一个字符串是否为邮件 5.判断一个字符串是否为字母加数字 6.判断一个字符串是否为手机号码 7.判断一个字符串是否为电话号码 8.判断一个字符串是否为网…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...
Netty自定义协议解析
目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...