Java是怎么运行起来的?深入理解Java虚拟机

2023-12-19

介绍Java的工作原理和JVM的内部结构。

微信搜索关注《Java学研大本营》

Java虚拟机(JVM)是一个运行时环境,可以执行用Java编程语言编写的程序。Java语言是一种高级语言,它通过抽象和封装的机制,让开发者可以专注于业务逻辑和功能实现,而不用关心底层的细节。因此,运行/开发Java程序时,不必深入了解Java程序的执行过程或JVM的内部原理。对于大多数开发者来说,JVM就像一个神奇的盒子,能够帮助他们实现功能和完成任务。

但是,了解JVM是如何支持Java语言和其他相关语言的,对于程序员来说是很有裨益的!

图片

本文分享一下Java的工作原理和JVM的内部结构。

1 Java虚拟机

Java虚拟机(JVM)是一个抽象的机器,用来执行一种代码,即 bytecode 。你可以把它看作是我们的代码和计算机硬件之间的桥梁,它把我们的代码作为输入,转换成字节码并在计算机硬件上运行它,从而实现开发者预期的结果。

2 字节码 (bytecode)

字节码是一种JVM能够理解的文件类型。它是通过 compiling Java代码(使用 javac )生成的一种Java程序的中间表示形式。它之所以叫字节码,是因为每个操作码(operation)都是单字节大小的。字节码可以再次编译成机器码并在计算机上运行。

3 编译

运行Java程序的第一步是编译。如果你有一个单独的Java文件,你可以使用提供的命令行工具 javac 来触发编译。

javac HelloWorld.java

图片

上面代码会把一个给定的Java文件编译成 .class 文件,其中包含 bytecode 。如果源代码有错误,编译会失败并报出编译错误。

你可以使用提供的工具javap来查看已创建的类文件,以了解类文件的内部情况。

javap HelloWorld.class

4 执行

在通过编译创建了 .class 文件之后,可以使用 java 语法来启动一个JVM的实例,它会触发一个包含多个复杂步骤的执行路径,最终执行我们提供的代码。

java HelloWorld

首先JVM需要获取.class文件,并将它加载到JVM的内存区域中。这个初始过程是通过JVM类加载器来实现的。

5 什么是类加载?

抽象地说,类加载就是扫描并遍历提供的 .class 文件,并将类文件中的内容加载到JVM的内存区域中。然后,执行引擎就可以引用这些存储的数据,继续执行我们的代码。

JVM中有三种类型的类加载器,分别是:

  • 引导类加载器

  • 扩展类加载器

  • 应用类加载器

引导类加载器的职责是加载基础/核心的Java类,这些类对于Java程序运行是必不可少的。在早期的Java版本中,这些核心类被包含在位于 jre/lib 目录下的 rt.jar 文件中,但在后来的Java版本中, rt.jar 中的内容被分割成模块化的组件。

扩展类加载器的职责是加载 lib/ext 目录下的类,这些类可能包括我们在代码中使用的任何扩展。

应用类加载器是三种中最常用的一种,它负责加载用户定义的类。它会扫描我们程序的类路径,并加载其中的类。

6 类加载过程

类加载过程有两个主要步骤:

  • 加载

  • 链接

7 加载

在加载过程中,类加载器读取类文件的二进制表示形式,即 .class 文件,并在JVM的运行时内存中创建它的表示。这个表示称为 Class Object ,它位于JVM内存的方法区中。

8 链接

在加载过程之后,开始链接。链接有三个步骤。

  • 验证 — 确保类文件的正确性。验证类是否符合Java规范。

  • 准备 — 为静态块/字段分配内存,并为静态变量赋予默认值(不是初始值!)。

  • 解析 — 解析类文件中的(符号)引用。

图片

解析

在链接的解析阶段,类加载器会解析常量池表,这是一个位于 .class 文件/类对象中的实体,类似于一个符号表,指定了类中的字段/方法/引用。在类文件中,对其他类的引用是以符号方式表示的,没有具体的内存地址来引用。解析会搜索JVM内存,并为那些符号引用分配具体的引用。如果在.class文件中发现了一个尚未加载的类,它会触发该类本身的加载/链接过程,这可能会导致一个递归的加载和链接过程。

在字节码加载和链接之后,类就成功地存储在JVM内存中(将在后面的部分讨论),并准备好初始化。

9 初始化

当代码中第一次用 new 关键字或静态字段来引用一个类,或者当程序执行时遇到一个初始化类(比如Main类),则会触发类文件的初始化。

在初始化阶段,执行静态块,静态变量被分配初始值。

10 运行时内存区域

在上面的段落中,多次提到了将类文件数据存储在JVM内存中。这些数据究竟存储在哪里,来作为加载/链接/初始化的结果?答案是运行时内存区域。

JVM运行时内存区域是指定的内存空间,它被划分为多个部分,用于存储执行相关/类文件相关的数据。

运行时内存区的主要区域如下:

10.1 方法区

方法区是运行时内存的一部分,用于存储与类文件相关的数据。运行时常量池、字段元数据、类元数据、方法元数据和字节码本身等都存储在方法区中。

10.2 程序计数器(PC)

程序计数器是一个小的内存区域,用于存储当前正在执行的操作的地址,这是Java程序执行的必要信息。每个线程都有自己的PC。

10.3 堆

存储所有的类/数组实例,是所有线程共享的一块内存。

10.4 JVM栈

保存局部变量和部分结果。包含栈帧。每个线程都有自己的JVM栈。

11 栈帧

当一个方法被调用时,在栈中创建一个新的帧。它会存储与该方法相关的局部变量和部分结果。如果在该方法内部调用了另一个方法,就会为新调用的方法创建一个新的栈帧。在给定线程中,一次只有一个帧是活动的。

12 执行

在上面的部分中,简要地介绍了Java源代码是如何编译并加载到JVM运行时内存区域中的。

接下来看看这些数据是如何执行的。

这部分过程是通过JVM的执行引擎来实现的,它由两个主要部分组成:(执行引擎还包括许多其他组件,但在本文中不会提及。)

  • 解释器

  • JIT(即时)编译器

“Java作为一种编程语言,是一种混合的解释和编译语言,也就是说Java代码既要经过编译,又要经过解释。简单来说,当类文件开始运行时,JVM会先用解释器直接执行字节码,不需要编译。这样做的主要好处是可以提高启动速度和执行速度(不用等待编译过程)。

在解释的过程中,JVM会发现代码中的热点和热区,也就是经常执行或者可以优化的代码段。这些代码段会被JIT编译器编译成本地代码,然后执行引擎会从解释模式切换到执行模式。”

这个编译过程有多个层次,称为分层编译。

推荐书单

《 JavaScript从入门到精通(第5版)(软件开发视频大讲堂)》

《JavaScript从入门到精通(第5版)》从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用JavaScript语言进行程序开发需要掌握的各方面技术。全书分为4篇,共24章,内容包括初识JavaScript、JavaScript基础、流程控制语句、函数、对象、数组与集合、String对象、正则表达式、异常处理与程序调试、JavaScript高级编程、事件处理、Document对象、文档对象模型、Window对象、浏览器对象模型、Style对象、Form对象、图像处理、JavaScript中的XML、JSON、JavaScript的安全、Ajax技术、Vue.js编程,以及星光电影网项目实战。书中的大多数知识点结合具体实例进行介绍,涉及的程序代码给出了详细的注释,读者可轻松领会 JavaScript 程序开发的精髓,快速提高开发 技能。

《 JavaScript从入门到精通(第5版)(软件开发视频大讲堂)》 icon-default.png?t=N7T8 https://item.jd.com/13791889.html

图片

精彩回顾

10道Java限流器面试题和答案

一文搞懂Java面向对象编程中的封装机制

一文搞懂Java面向对象编程中的继承机制

详解Java中的装饰器

5个Java开发者不可不知的编程库

微信搜索关注《Java学研大本营》

访问【IT今日热榜】,发现每日技术热点

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java是怎么运行起来的?深入理解Java虚拟机 的相关文章

  • Java:扩展类并实现具有相同方法的接口

    可能无法完成以下操作 我收到编译错误 继承的方法 A doSomthing int 无法隐藏 B 中的公共抽象方法 public class A int doSomthing int x return x public interface
  • java.lang.ClassNotFoundException:javax.mail.MessagingException

    我想使用 eclipse 将电子邮件从我的 gmail 帐户发送到另一个邮件帐户 我使用 apache tomcat 7 0 34 作为我的 Web 服务器 并使用端口 8080 作为 apache 服务器 HTTP 1 1 并使用 JRE
  • 如何在 JavaFX 中连接可观察列表?

    我所说的串联是指获得一个新列表 该列表侦听所有串联部分的更改 方法的目的是什么FXCollections concat ObservableList
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • 为什么即使我的哈希码值相同,“==”也会返回 false

    我写了一个像这样的课程 public class HashCodeImpl public int hashCode return 1 public static void main String args TODO Auto generat
  • 如何调试“com.android.okhttp”

    在android kitkat中 URLConnection的实现已经被OkHttp取代 如何调试呢 OkHttp 位于此目录中 external okhttp android main java com squareup okhttp 当
  • Android中如何使用JNI获取设备ID?

    我想从 c 获取 IMEIJNI 我使用下面的代码 但是遇到了未能获取的错误cls 它总是返回NULL 我检查了环境和上下文 它们都没有问题 为什么我不能得到Context班级 我在网上搜索了一下 有人说我们应该使用java lang Ob
  • Runtime.exec 处理包含多个空格的参数

    我怎样才能进行以下运行 public class ExecTest public static void main String args try Notice the multiple spaces in the argument Str
  • 在 Java 中如何找出哪个对象打开了文件?

    我需要找出答案哪个对象在我的 Java 应用程序中打开了一个文件 这是为了调试 因此欢迎使用工具或实用程序 如果发现哪个对象太具体了 这class也会很有帮助 这可能很棘手 您可以从使用分析器开始 例如VisualVM http visua
  • Java 中如何将 char 转换为 int? [复制]

    这个问题在这里已经有答案了 我是Java编程新手 我有例如 char x 9 我需要得到撇号中的数字 即数字 9 本身 我尝试执行以下操作 char x 9 int y int x 但没有成功 那么我应该怎么做才能得到撇号中的数字呢 ASC
  • 如何在.NET中使用java.util.zip.Deflater解压缩放气流?

    之后我有一个转储java util zip Deflater 可以确认它是有效的 因为 Java 的Inflater打开它很好 并且需要在 NET中打开它 byte content ReadSample sampleName var inp
  • Java继承,扩展类如何影响实际类

    我正在查看 Sun 认证学习指南 其中有一段描述了最终修饰符 它说 如果程序员可以自由地扩展我们所知的 String 类文明 它可能会崩溃 他什么意思 如果可以扩展 String 类 我是否不会有一个名为 MyString 的类继承所有 S
  • JDBC 时间戳和日期 GMT 问题

    我有一个 JDBC 日期列 如果我使用 getDate 则会得到 date 仅部分2009 年 10 月 2 日但如果我使用 getTimestamp 我会得到完整的 date 2009 年 10 月 2 日 13 56 78 890 这正
  • 将 JavaFX FXML 对象分组在一起

    非常具有描述性和信息性的答案将从我这里获得价值 50 声望的赏金 我正在 JavaFX 中开发一个应用程序 对于视图 我使用 FXML
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • java XMLSerializer 避免复杂的空元素

    我有这个代码 DocumentBuilderFactory factory DocumentBuilderFactory newInstance DocumentBuilder builder factory newDocumentBuil
  • 子类构造函数(JAVA)中的重写函数[重复]

    这个问题在这里已经有答案了 为什么在派生类构造函数中调用超类构造函数时 id 0 当创建子对象时 什么时候在堆中为该对象分配内存 在基类构造函数运行之后还是之前 class Parent int id 10 Parent meth void
  • Java RMI - 客户端超时

    我正在使用 Java RMI 构建分布式系统 它必须支持服务器丢失 如果我的客户端使用 RMI 连接到服务器 如果该服务器出现故障 例如电缆问题 我的客户端应该会收到异常 以便它可以连接到其他服务器 但是当服务器出现故障时 我的客户端什么也
  • MiniDFSCluster UnsatisfiedLinkError org.apache.hadoop.io.nativeio.NativeIO$Windows.access0

    做时 new MiniDFSCluster Builder config build 我得到这个异常 java lang UnsatisfiedLinkError org apache hadoop io nativeio NativeIO
  • 由 Servlet 容器提供服务的 WebSocket

    上周我研究了 WebSockets 并对如何使用 Java Servlet API 实现服务器端进行了一些思考 我没有花费太多时间 但在使用 Tomcat 进行一些测试时遇到了以下问题 如果不修补容器或至少对 HttpServletResp

随机推荐

  • 如何在 Windows 电脑的SSD硬盘恢复数据

    当人们想要更换硬盘时 他们通常会从 HDD 硬盘驱动器 切换到 SSD 固态硬盘 这是因为 SSD 被认为比 HDD 更好并且速度更快 但这并不意味着您不会丢失 SSD 设备中的文件 当 SSD 丢失文件时 恢复过程与 HDD 相同 但是
  • C# DataTable 生成Excel 和 CSV文件

    EXCEL using NPOI SS UserModel using NPOI XSSF UserModel using System Data using System IO public class ExcelService publ
  • 安卓自动化 APP:轻松关闭任意开屏广告 | 开源日报 No.116

    gkd kit gkd Stars 8 7k License GPL 3 0 基于无障碍 高级选择器 订阅规则的自定义屏幕点击 APP 主要功能包括实现跳过任意开屏广告 关闭应用内部弹窗广告以及一些快捷操作 如微信电脑登录自动同意和领取红包
  • 一键生成精美电子书:让阅读更加惬意 | 开源日报 No.115

    keyvanakbary learning notes Stars 4 0k License NOASSERTION 这个项目是一个学习笔记的仓库 作者在这里记录了自己阅读书籍 观看讲座 研究文章和喜爱论文时所做的简要总结 主要功能包括提供
  • 服务器安全最常见的5大威胁!

    服务器安全是将服务器的软件和硬件保护起来 以防止黑客对服务器构架和数据进行未经授权的访问及操作 也是网络安全体系中的重要组成部分 本文主要为大家介绍一下最常见的影响服务器安全的5大因素 一起来了解一下 1 电子邮件欺骗 电子邮件欺骗是一种网
  • 网络安全岗位面试题

    前言 介绍了网络安全岗位常见的面试题 仅供参考 一 常识部分 1 Linux服务器种用户关键信息存储在那个文件中 启动 停止 重启 开机自启mysql服务命令 如何查找 etc test txt文件中 password 关键字信息 如何精确
  • SpringCloud有什么优势

    SpringCloud是一个基于Spring Boot的微服务框架 它提供了许多工具和库 可以帮助开发者更容易地构建和部署分布式系统 以下是SpringCloud的一些主要优势 易于集成 SpringCloud提供了丰富的工具和库 可以帮助
  • 【思扬赠书 | 第1期】教你如何一站式解决OpenCV工程化开发痛点

    写在前面参与规则 参与方式 关注博主 点赞 收藏 评论 任意评论 每人最多评论三次 本次送书1 3本 取决于阅读量 阅读量越多 送的越多 思扬赠书 第1期活动开始了 机器视觉 缺陷检测 工业上常见缺陷检测方法 方法一 基于简单二值图像分析
  • 【华为OD】给定一个整数数组nums,请你在该数组中找出两个数,使得这两个数 的和的绝对值abs(nums[x] + nums[y])为最小值并按从小到大返回这 两个数以及它们和的绝对值

    题目描述 给定一个整数数组nums 请你在该数组中找出两个数 使得这两个数 的和的绝对值abs nums x nums y 为最小值并按从小到大返回这 两个数以及它们和的绝对值 每种输入只会对应一个答案 数组中同一 个元素不能使用两遍 输入
  • 2023年30米分辨率土地利用遥感监测数据

    改革开放以来 中国经济的快速发展对土地利用模式产生了深刻的影响 同时 中国又具有复杂的自然环境背景和广阔的陆地面积 其土地利用变化不仅对国家发展 也对全球环境变化产生了深刻的影响 为了恢复和重建我国土地利用变化的现代过程 更好地预测 预报土
  • 请解释Nginx代理中的正向代理和反向代理

    正向代理 Forward Proxy 和反向代理 Reverse Proxy 是Nginx代理模式中的两种主要类型 正向代理 Forward Proxy 是一种代理服务器 它允许客户端 用户 通过它访问远程服务器 在这种模式下 客户端发送的
  • 讲解module ‘tensorflow‘ has no attribute ‘Session‘

    目录 讲解module tensorflow has no attribute Session 错误原因 解决方案 总结 讲解module tensorflow has no attribute Session 在使用TensorFlow进
  • 广州软件第三方测试报告需要盖CNAS\CMA吗?怎么取费?

    CNAS CMA资质 1 CMA资质标识 根据报告接收方要求 第三方测试报告上是否加盖CMA标识 第三方测试机构执行标准为GB T25000 51和GB T25000 10标准 2 CNAS标识 ILAC MRA国际互认标识 通常第三方测试
  • SDN前沿技术【SMaRT-5G项目】

    目录 引言 节能方法 快速了解投资回报率 ROI ONF SMaRT 5G Initiative RAN 能量优化 方法 电池开 关方法 MIMO 睡眠和 RF 通道打开 关闭 高级睡眠模式 ASM RAN节能解决方案的
  • 【最新】2023年30米分辨率土地利用遥感监测数据

    改革开放以来 中国经济的快速发展对土地利用模式产生了深刻的影响 同时 中国又具有复杂的自然环境背景和广阔的陆地面积 其土地利用变化不仅对国家发展 也对全球环境变化产生了深刻的影响 为了恢复和重建我国土地利用变化的现代过程 更好地预测 预报土
  • Dubbo 注册中心挂了,consumer 还能不能调用 provider?

    在 Dubbo 中 如果注册中心 如 Zookeeper Nacos 等 出现故障 消费者 consumer 仍然可以调用提供者 provider 的服务 但需要满足以下条件 消费者和提供者之间的通信配置正确 消费者需要知道提供者的地址和端
  • Clion远程开发无法解析头文件,但是代码可以正常编译运行

    问题 当我在使用Clion进行远程开发时 需要用到Opencv库 我首先在CMakeLists txt添加了opencv库 如下 find package OpenCV REQUIRED INCLUDE DIRECTORIES OpenCV
  • 天眼情报分析——问题收集

    分为几类 一 代码实现问题 1 将两个字符串交替合并 这段代码错在逻辑错误 由于w1此时小于w2剩下的部分应该是w2而不是w1 我分析这位星友错误的原因应该是对底层逻辑实现没有深入理解 学到了不少 多多交流是好事 二 如何使用GitHub
  • NFS原理详解

    一 NFS介绍 1 什么是NFS 它的主要功能是通过网络让不同的机器系统之间可以彼此共享文件和目录 NFS服务器可以允许NFS客户端将远端NFS服务器端的共享目录挂载到本地的NFS客户端中 在本地的NFS客户端的机器看来 NFS服务器端共享
  • Java是怎么运行起来的?深入理解Java虚拟机

    介绍Java的工作原理和JVM的内部结构 微信搜索关注 Java学研大本营 Java虚拟机 JVM 是一个运行时环境 可以执行用Java编程语言编写的程序 Java语言是一种高级语言 它通过抽象和封装的机制 让开发者可以专注于业务逻辑和功能