Java基础 — Java 虚拟机(上篇)

该文章属于Java进阶部分的JVM入门,本章讲述了JVM的历史、Java源代码到机器码的过程以及 Class字节码文件的内部结构等。
了解了这篇文章,能让你深入地了解JVM知识,保证在短时间内掌握JVM!

JVM 入门教程(上篇)

开篇:为什么要学虚拟机

  1. 学习Java虚拟机能深入地理解Java这门语言

  2. 学习虚拟机是为了线上排查问题打下基础

  • 学会垃圾回收机制等,看懂Java虚拟机内存模型,看懂GC日志,解决线上的Java应用崩溃问题

第 1 讲 Java语言的前世今生

1. JDK 与 JRE

  • JRE 仅包含运行Java程序的必须组件,包括Java虚拟机以及Java核心类库等。

  • JDK 除了包含JRE外,还附带了一系列开发、诊断工具。

  • 一般来说,如果只需要运行Java程序,那么安装JRE即可。但如果要运行Java程序的开发,那么就需要安装JDK。

2. JDK 与 J2SE

  • Java SE 是Java三大技术体系的一个。

  • 在1998年,JDK1.2发布,Java技术体系被拆分为 J2SE、J2EE、J2ME三大体系。

  • J2SE称之为标准版技术体系,它包含了构成Java语言核心的类,如:数据库连接、网络编程、接口定义等。J2SE技术体系主要用于桌面应用软件的编程。

  • J2EE称之为企业版技术体系,它除了包含J2SE中的类,还包含用于开发企业级应用的类,如:Servle、JSP、EJB等。J2EE技术体系主要用于分布式的网络程序的开发,如电子商务网站等。

  • J2ME称之为嵌入式技术体系,它包含J2SE中的一部分类。J2ME技术体系主要用于消费电子产品的软件开发,如:手机、PDA、寻呼机等。

3. J2SE 与 Java SE

  • J2SE 与 Java SE ,其实它们指的是同一个东西,只不过在2006年JDK 1.6 发布时,讲J2SE、J2EE、J2ME的命名方式改为 Java SE 6、Java EE 6、Java ME 6。

4. Java语言的历史

  • 在 1991 年,James Gosling 博士发布了 Oak,这个是 Java 语言的前身。但一直到 1995 年的时候,Oak 语言才改名为 Java。

  • 1991 年,James Gosling 博士发布产品 Oak,这是 Java 语言的前身。

  • 1995 年,Oak 语言改名为 Java。

  • 1996 年,JDK1.0 发布,提供了纯解释执行的 Java 虚拟机实现:Sun Classic VM。

  • 1997 年,JDK1.1 发布,代表技术有:JDBC、JavaBeans、内部类、反射。

  • 1998 年,JDK1.2 发布,Java 技术体系被拆分为 J2SE、J2EE、J2ME 三大体系。

  • 2000 年,JDK1.3 发布,默认的 Java 虚拟机由 Sun Classic VM 改为 HotSopt。

  • 2002 年,JDK1.4 发布,Java 真正走向成熟,代表技术有:正则表达式、NIO等。

  • 2004 年,JDK1.5 发布,对语法易用性做了很大改进,新增了泛型、枚举等,代表技术有:并发包等。

  • 2006 年,JDK1.6 发布,将 J2EE/J2SE/J2ME 的命名方式改为 Java SE 6、Java EE 6、Java ME 6。

  • 2009 年,Sun 公司因为经营不善被 Oracle 公司收购。

  • 2011 年,JDK1.7 发布。

  • 2013 年,JDK1.8 发布。

  • …………

5. 总结

  • 这一部分简单地介绍了一些常见概念上地区别,以及Java语言的历史,让大家对Java语言的发展有一个大致的理解。

第 2 讲 Java虚拟机的历史

1. Sun Classic —— 虚拟机始祖

  • 在 1996 年 1 月 23 日,Sun 发布 JDK1.0,齐总自带的虚拟机就是Classic VM。但是这款虚拟机有个特点,只能使用纯解释器的方式来执行Java代码,此时解释器与编译器无法共同存在。到JDK1.4正式退出历史舞台。

2. Sun Exact VM —— 无疾而终

  • 在 JDK1.2 时发布了Exact VM 的虚拟机,尝试解决 Classic VM遇到的所有问题,它的执行系统解决了Classic VM 存在的编译器和解释器无法同时工作的问题,还具备了一些现代高性能处理器的特性,如:两级即时编译等。

  • Exact VM 还改进了虚拟机的对象查找方式,使用了准确式内存管理,即虚拟机可以知道内存中某个位置的数据具体是什么类型,这样就减少了查找的开销,提升了执行性能。

  • 但可惜的是,虽然Exact VM发布了,但是直到它退出时,都没有被大规模使用过。

3. Sun HotSpot VM —— 武林盟主

  • HotSpot不仅仅有前面说到两款虚拟机的优点,也有许多自己的新技术,如:热点探测技术。热点探测技术指的是通过执行计数器找出最具优化价值的代码,然后通知JIT编译器一方法为单位进行深度优化编译。

  • 从 2000 年JDK1.3发布,HotSpot VM作为默认的虚拟机开始登上历史舞台。

4. BEA JRockit / IBM J9 VM —— 百家争鸣

  • 前面说的都是 Sun 公司推出的虚拟机,其他组织、公司也研发过不少的虚拟机实现。这里是最著名的。

  • BEA 公司的 JRockit 是一款专注于服务器硬件和服务端应用场景的虚拟机,其针对服务端场景做了大量的优化,因此其不太关注程序启动速度。JRockit 虚拟机内部不包含解释器实现,全部代码都靠即时编译器编译后执行。此外,其提供的 MissionControl 服务套件也十分强大。

  • IBM 公司的 J9 VM 则是一款比较通用的虚拟机,其定位应用于从服务端到桌面应用再到嵌入式的多用途虚拟机。IBM 公司开发 J9 VM 的目的是将其作为 IBM 公司各种 Java 产品的执行平台。

5. 那些无名虚拟机 —— 武林外传

  • 除了上述的这些虚拟机之外,其实还有各种各样的虚拟机存在。

  • 例如性能最强悍的并不是上面所说的虚拟机,而是名为 Azul VM 和 BEA Liquid VM 的专用商业及虚拟机。这些虚拟机只运行在特定硬件平台,因此要求比较高。但其性能也是非常强悍的。其可以管理至少数十个 CPU 和数百 GB 的内存资源,还提供在巨大内存范围内实现可控 GC 时间的垃圾收集器等等。

  • 此外还有许许多多其他的虚拟机存在,例如:Apache Harmony、Google Android Dalvik VM、Mircosoft JVM 等等。

  • Oracle 看了这么些历史,似乎都是在说 Sun公司发布的虚拟机,与 Oracle 似乎没有什么关系。但在 2010 年,Oracle 公司收购了 Sun 公司,这样 Oracle 就拥有了 HotSpot VM。再加上其在 2008 年收购 BEA 公司获得的 JRocket VM,Oracle 公司就拥有了地球上最优秀的两款虚拟机。

  • 对于虚拟机未来的规划,Oracle 宣布会将 JRockit 的优秀特性整合到 HotSpot VM 中,例如移植 JRockit 的垃圾回收器和 MissionControl 服务。

第 3 讲 到底什么是虚拟机?

  • 为什么不同系统上的软件无法安装,这是因为操作系统底层的实现是不一样的。对于Windows系统来说,exe后缀的软件代码最终编译成Windows系统能识别的机器码。而Mac OSX 系统来说,dmg后缀的软件代码最终编译成 Mac OSX 系统能识别的代码。

  • 与其他语言不同,Java语言并不直接讲代码编译成与系统有关的机器码,而是编译成一种特定的语言规范,这种语言规范我们称之为字节码。无论Java程序要在Windows系统,还是Mac OSX系统,或者是Linux系统,它首先都得编译成字节码文件,之后才能运行。

  • 但即使编译成字节码文件了,各个系统还是无法明白字节码文件的内容,这时就需要Java虚拟机的帮助了。Java虚拟机会解析字节码文件的内容,并将其翻译为各操作系统能理解的机器码。

  • Java虚拟机运行的是字节码文件,如果你用php语言写一段代码,并自己用特定编译器能生成符合字节码规范的字节码文件,那么Java虚拟机也是可以运行的。

  • 简单来说Java虚拟机就是一个字节码翻译器,它将字节码文件翻译成各个系统对应的机器码,确保字节码文件能在各个系统正确运行。

第 4 讲 对于Java语言,从源代码到机器码,发生了什么?

编译器可以分为:前端编译器、JIT编译器和AOT编译器

前端编译器

前端编译器:源代码到字节码 对于Java虚拟机来说,其实际输入的是字节码文件,而不是Java文件。 怎样讲Java代码转化为字节码文件?我们知道在JDK的安装目录里有一个javac工具,就是它讲Java代码翻译成字节码,这个工具我们叫做编译器,因为是处于编译前期,所以被称为前端编译器。常见的前端编译器有Sun的javac,Eclipse JDT的增量编译器(ECJ)。 通过javac编译器,我们可以很方便地将java源文件翻译成字节码文件。javac编译器解析Java源码,并生成字节码文件地过程,就是使用javac编译器把Java语言规范转化为字节码语言规范。

javac编译器地处理过程可以分为下面地四个阶段:

第一阶段:词法、语法分析

javac编译器会对源代码地字符进行一次扫描,最终生成一个抽象地语法树。

第二阶段:填充符号表

对抽象地类或接口进行符号填充,等到类加载阶段,javac编译器会将符号替换成具体地内存地址。

第三个阶段:注解处理

Java是支持注解地,因此在这个阶段会对注解进行分析,根据注解地作用将其还原成具体的指令集。

第四个阶段:分析与字节码生成

javac编译器会根据上面几个阶段分析出来的结果,进行字节码的生成,最终输出为class文件。

JIT编译器(即时编译器)

  • JIT编译器:从字节码到机器码

  • 当源代码转化为字节码后,其实要运行程序有两种选择:

    • 一种是Java解释器解释执行字节码,另一种则是使用JIT编译器将字节码转化为本地机器代码。

    • 两者区别在于,前者启动速度快但运行速度慢,后者启动速度慢但运行速度快。

  • 在HotSpot虚拟机内置了两个即时编译器,分别为Client Compiler和Server Compiler。

  • 这两种不同的编译器衍生出两种不同的编译模式,我们分别称之为:C1编译模式、C2编译模式(非官方说法)。

C1编译模式和C2编译模式的区别

  • C1编译模式会将字节码编译为本地代码,进行简单、可靠的优化,如:有必要将加入性能监控的逻辑。优化相对比较保守,比C2较快。

  • 而C2编译模式,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。C2的编译质量相对较好,但耗时更长。

对于HotSpot虚拟机有三种运行模式可选

  1. 混合模式:

  • C1和C2两种模式混合起来使用,这是默认的运行模式,如果想单独使用C1模式或C2模式,使用 -client 或 -server 打开即可。

  1. 解释模式:

  • 所有代码都解释执行,使用 -Xint 参数可以打开这个模式。

  1. 编译模式:

  • 此模式优先采用编译,但是无法编译时也会解释执行,使用 -Xcomp 打开这种模式。

此时,我们了解了从Java源代码到字节码,再从字节码到机器码的全过程,可以到这里就结束了。但是Java中还有一个AOT编译器,它能直接将源代码转换为机器码。

AOT编译器

  • AOT编译器:源代码到机器码

  • AOT编译器的基本思想是:在程序执行前生成Java方法的本地代码,以便在程序运行时直接使用本地代码,也就是在进入JVM之前就已经将本地机器码生成了。

  • 优点:
    • 启动速度快,减少运行时的开销

  • 限制:
    • 由于缺乏运行时信息,AOT编译质量也就是优化效果通常不如JIT编译。

    • Java的动态类加载等特性可能会增加AOT编译的复杂性。

总结

  • 在JVM中有三个非常重要的编译器,它们分别是:前端编译器、JIT编译器、AOT编译器。

  • 前端编译器,最常见的是javac编译器,将Java源代码编译为Java字节码文件。

  • JIT编译器(即时编译器),最常见的是HotSpot虚拟机中的Client Compiler和 Server Compiler,将Java字节码编译成本地机器代码。

  • AOT编译器能将源代码直接编译为本地机器码。

编译速度和编译质量上的区别

  • 编译速度上,解释执行>AOT编译器>JIT编译器

  • 编译质量上,JIT编译器>AOT编译器>解释执行。

而在JVM中,通过这几种不同方式的配合,使得JVM的编译质量和运行速度达到最优的状态。

第 5 讲 字节码文件结构

《Java虚拟机规范》规定了Java虚拟机结构、Class类文件结构、字节码指令等内容。
字节码文件结构是一组以8位字节为基础的二进制流,各数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符。
在字节码结构中,有两种最基本的数据类型来表示字节码文件格式,分别是:无符号数和表。

无符号数
  • 无符号数属于最基本的数据类型。它以u1、u2、u4、u8分别代表1个字节、2个字节、4个字节、8个字节的无符号数。

  • 无符号数可以用来描述数字、索引引用、数量或者按照UTF-8编码构成的字符串值。

  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型。

一个Class字节码文件的格式内容

  1. magic: 魔数,固定为0xCAFEBABE,用于标识这是一个Java Class文件。

  2. minor_versionmajor_version: 分别表示Class文件的次版本号和主版本号。

  3. constant_pool_count: 常量池中常量的数量。

  4. constant_pool: 常量池,存储了类中用到的所有常量,包括字符串、类名、方法名等。这里除了基本类型和UTF-8的字符串存储的是值外,其他的都是存储的索引。

  5. access_flags: 访问标志,标识类或接口的访问权限和属性(如public, final, abstract等)。 如:这个Class是类还是接口、是否定义位public类型、是否定义为abstract类型等。标志值可以通过相加来叠加。

  6. this_class: 当前类的索引,确定这个类的全限定名,指向常量池中的一个项。

  7. super_class: 父类的索引,确定这个类的父类的全限定名,指向常量池中的一个项。

  8. interfaces_countinterfaces: 接口的数量和接口列表。Class文件中由this_class、super_class、interfaces_count这三项数据来确定这个类的继承关系。

  9. fields_countfields: 字段的数量和字段列表。

  10. methods_countmethods: 方法的数量和方法列表。

  11. attributes_countattributes: 属性的数量和属性列表。

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

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

相关文章

通过docker启动ElasticSearch后为ElasticSearch设置用户和密码

文章目录 0. 前言1. 没有设置用户名和密码的情况2. 为ElasticSearch设置用户名和密码2.1 进入 ElasticSearch 容器内部2.2 修改 ElasticSearch 的配置文件2.3 设置用户名和密码 3. 在 kibana 容器中指定访问 ElasticSearch 的用户名和密码4. 设置用户名和密码后的情况4.1 访问 …

[51单片机] 简单介绍 (一)

文章目录 1.单片机介绍2.单片机内部三大资源3.单片机最小系统4.STC89C52RC单片机 1.单片机介绍 兼容Intel的MCS-51体系架构的一系列单片机。 STC89C52:8K FLASH、512字节RAM、32个IO口、3个定时器、1个UART、8个中断源。 单片机简称MCU单片机内部集成了CPU、RAM、…

Maxim(美信)—MAX20079AATP/VY PMIC芯片详解

写在前面 本系列文章主要讲解Maxim(美信)—MAX20079AATP/VY PMIC芯片的相关知识,希望能帮助更多的同学认识和了解MAX20079AATP/VY芯片。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) PMIC是Power Management Int…

CC面试准备

半导体基础 半导体是介于导体和绝缘体之间的一种介质,在不同条件下表现出不同的导电性或者不导电特性, 电子半导体器件材料大部分为硅,锗等元素 本征半导体:完全不含杂质的纯净半导体,因为不含杂质,其中…

QT widgets 窗口缩放,自适应窗口大小进行布局

1. 窗口布局 2. 尺寸策略:扩展 Fixed (固定): 行为:控件的大小是固定的,不会随着窗口大小的变化而改变。它的大小由控件的 sizeHint() 返回的值决定。 适用场景:当你希望控件的大小保持不变,不随布局调整时使用&#x…

RAG+Agent人工智能平台:RAGflow实现GraphRA知识库问答,打造极致多模态问答与AI编排流体验

1.RAGflow简介 全面优化的 RAG 工作流可以支持从个人应用乃至超大型企业的各类生态系统。大语言模型 LLM 以及向量模型均支持配置。基于多路召回、融合重排序。提供易用的 API,可以轻松集成到各类企业系统。支持丰富的文件类型,包括 Word 文档、PPT、exc…

前端报错401 【已解决】

前端报错401 【已解决】 在前端开发中,HTTP状态码401(Unauthorized)是一个常见的错误,它表明用户试图访问受保护的资源,但未能提供有效的身份验证信息。这个错误不仅关乎用户体验,也直接关系到应用的安全性…

Uniapp时间戳转时间显示/时间格式

使用uview2 time 时间格式 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 <text class"cell-tit clamp1">{{item.create_time}} --- {{ $u.timeFormat(item.create_time, yyyy-mm-dd hh:MM:ss)}} </text>

OpenAI发布多语言MMMLU数据集;火山引擎发布AI视频生成大模型豆包

&#x1f989; AI新闻 &#x1f680; OpenAI发布多语言MMMLU数据集 摘要&#xff1a;OpenAI在Hugging Face上推出了多语言大规模多任务语言理解&#xff08;MMMLU&#xff09;数据集&#xff0c;旨在评估大型语言模型在各种语言和任务中的表现。该数据集涵盖广泛的主题与学科…

记某学校小程序漏洞挖掘

前言&#xff1a; 遇到一个学校小程序的站点&#xff0c;只在前端登录口做了校验&#xff0c;后端没有任何校验&#xff0c;奇葩弱口令离谱进去&#xff0c;站点里面越权泄露敏感信息&#xff0c;接管账号等漏洞&#xff01;&#xff01;&#xff01; 渗透思路 1.绕过前端 …

代码随想录算法训练营Day14 | 226.翻转二叉树、101. 对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度

目录 226.翻转二叉树 101. 对称二叉树 104.二叉树的最大深度 111.二叉树的最小深度 226.翻转二叉树 题目 226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例1&#…

[网络] 网络层--IP协议

目录 一、IP协议 1.1 基本概念 1.2 IP协议报头 1.3 如何将报头和有效载荷分离和分用 1.4 分片与组装 1.5 如何减少分片&#xff1f; 1.6 分片和封装的具体过程 二、网段划分 2.1 再次理解IP地址 2.2 了解DHCP 2.3 网络划分方案 2.4 为什么要进行网络划分 2.5 特殊的…

接口加解密及数据加解密

目录 一、 加解密方式介绍 1.1 Hash算法加密 1.2. 对称加密 1.3 非对称加密 二、 我们要讲什么&#xff1f; 三、 接口加解密 四、 数据加解密 一、 加解密方式介绍 所有的加密方式我们可以分为三类&#xff1a;对称加密、非对称加密、Hash算法加密。 算法内部的具体实现…

【html】基础(二)

本专栏内容为&#xff1a;前端专栏 记录学习前端&#xff0c;分为若干个子专栏&#xff0c;html js css vue等 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;js专栏 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &am…

http增删改查四种请求方式操纵数据库

注意&#xff1a;在manage.py项目入口文件中的路由配置里&#xff0c;返回响应的 return语句后面的代码不会执行&#xff0c;所以路由配置中每个模块代码要想都执行&#xff0c;不能出现return 激活虚拟环境&#xff1a;venv(我的虚拟环境名称&#xff09;\Scripts\activate …

Unity3D 小案例 像素贪吃蛇 03 蛇的碰撞

Unity3D 小案例 像素贪吃蛇 第三期 蛇的碰撞&#xff08;完结&#xff09; 像素贪吃蛇 碰撞蛇身 当蛇头碰撞到蛇身时&#xff0c;游戏应该判定为失败。 找到蛇身预制体&#xff0c;添加 Body 标签和碰撞体&#xff0c;碰撞体的大小为 0.5&#xff0c;跟蛇头和蛇身的碰撞体范…

AlDente Pro for Mac电池健康保护工具

AlDente Pro for Mac 是一款适用于 Mac 的实用电池健康保护工具。以下是它的主要特点和优势&#xff1a; 软件下载地址 一、保护电池寿命的原理 锂离子和聚合物电池&#xff08;如 Mac 笔记本中的电池&#xff09;在 30% 到 80% 之间运行时使用寿命最长。始终将电池电量保持…

Windows 10 on ARM, version 22H2 (updated Aug 2024) ARM64 AArch64 中文版、英文版下载

Windows 10 on ARM, version 22H2 (updated Aug 2024) ARM64 AArch64 中文版、英文版下载 基于 ARM 的 Windows 10 请访问原文链接&#xff1a;https://sysin.org/blog/windows-10-arm/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;s…

【VUE3.0】动手做一套像素风的前端UI组件库---Message

目录 引言自己整一个UI设计稿代码编写1. 设计信息窗口基础样式2. 设置打开和关闭的方法3. 编写实例化组件的js文件4. 看下最终效果5. 组件完整代码6. 组件调用方式 总结 引言 本教程基于前端UI样式库 NES.css 的UI设计&#xff0c;自行研究复现。欢迎大家交流优化实现方法~ 此次…

《线性代数》学渣笔记

文章目录 1 行列式1.1 克拉默法则1.2 基本性质1.3 余子式 M i j M_{ij} Mij​1.4 代数余子式 A i j ( − 1 ) i j ⋅ M i j A_{ij} (-1)^{ij} \cdot M_{ij} Aij​(−1)ij⋅Mij​1.5 具体型行列式计算&#xff08;化为基本型&#xff09;1.5.1 主对角线行列式&#xff1a;主…