📣 📣 📣 📢📢📢
☀️☀️你好啊!小伙伴,我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。
📒 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️,擅长使用Java技术开发web项目和工具
📒 文章内容丰富:覆盖大部分java必学技术栈,前端,计算机基础,容器等方面的文章
📒 如果你也对Java感兴趣,关注小冷吧,一起探索Java技术的生态与进步,一起讨论Java技术的使用与学习
✏️高质量技术专栏专栏链接: 微服务,数据结构,netty,单点登录,SSM ,SpringCloudAlibaba等
😝公众号😝 : 想全栈的小冷,分享一些技术上的文章,以及解决问题的经验
⏩当前专栏:Java虚拟机系列
目录
JVM的整体结构
JVM运行的位置
Jvm的结构
之前我们的学习 更倾向于 是用 API 现在我们的学习更加的底层 倾向于最底下的部分。
前端编译器: Javac(.java -> .class)
后端虚拟机 :hotspot client and server VM
HotSpotVm 结构
- Hot Spot VM 是目前市面上高性能虚拟机的代表作之一
- 他采用解释器与即时编译器并存的架构
- 在今天 java程序的运行性能已经可以达到和C/C++程序比较的地步了
Java代码的执行流程
- 生成字节码文件 先从源码 走到 编译器 最后生成 Class 字节码文件
- 到了 虚拟机 首先是: 类加载器 - > 字节码校验器 -> 执行引擎(编译器(针对热点代码,总是要执行的)或者翻译字节码(解释器)执行)
JVM架构模型
Java 编译器输入的指令流基本上是一种基于栈道指令集架构 另外一种指令集则是基于寄存器的指令集架构
两种架构的区别就是 :
- 基于栈式架构的特点
- 设计和实现更简单 更适用于资源受限的系统
- 避开了寄存器的分配难题,使用零地址指令方式分配
- 指令流中的指令大部分都是零地址指令,其执行的过程主要依赖与操作栈,指令集更小
- 不需要硬件支持,可移植性更好,更好的实现跨平台
- 基于寄存器的特点
- 典型的应用就是 x86 的二进制指令集,比如传统的PC 以及安卓的Davlik 虚拟机
- 指令集架构完全依赖硬件,可移植性差
- 性能够优秀 执行更高效
- 话费更少的指令去完成一项操作
- 在大部分情况下 基于寄存器的指令集往往都以一地址指令 二地址指令和 三地址指令为主,基于栈式架构的指令集往往以零地址的指令集为主
反编译实践
查看编译后的字节码文件,是如何的
public static void main(String[] args) {
int i = 2;
int j = 3;
int k = i + j;
}
反编译的结果
思考总结
现在跨平台的设计 java 的指令 都是根据栈来设计的,不同平台的cpu 架构不同,所以不能设计基于寄存器的 优点是 跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令
时至今日 尽管嵌入式瓶盖已经不是java 程序的主流运行平台,(准确的来说 Host Spot VM 对于宿主的环境已经布不局限于嵌入式平台了) 那么为什么不讲 架构更换成 速度更快的 寄存器架构呢?
答 : java指令执行 是 基于栈的架构 设计的,再受限的环境(嵌入式环境)和非受限环境都可以有不错的反响,所以基于有点 不需要更换架构
JVM生命周期
虚拟机的启动
Java 虚拟机的启动 是引导类加载器 bootstarp class loader
创建一个初始类(initial class )来完成的
这个类是由虚拟机了来具体实现的
虚拟机的执行
- 一个运行中的java 虚拟机有着一个清晰的任务 就是 :执行java 程序
- 程序执行的时候 他开始运行 程序结束的时候 他停止
- 执行一个所谓的java程序的时候 其实真真正正的执行的是一个叫做java 虚拟机的线程
实例
还是以刚才的代码为例子
查看java进程命令 : jps
来查看执行中的java程序
可以看到我们在执行的程序.
代码
public class StackStruTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int k = i + j;
try {
TimeUnit.SECONDS.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("hello");
}
}
执行之后主线程会 睡眠 10 秒,此时用 jps 命令来查看线程,可以看到我们执行的程序
输出 hello 之后 下次查看 就会发现 执行完成了 刚才的类名线程就停止了
虚拟机的退出
有如下几种情况:
- 程序正常执行结束
- 程序在执行中遇到了 异常 或者错误终止
- 由于操作系统出现了错误 导致 Java 虚拟机 进程终止
- 某线程调用 runtime 类或者 system 类的 exit 方法 或者是 runtime 类的halt 方法 并且 Java 安全管理器也允许这次exit 或者 halt 操作
- 除此之外 JNI(Java native interface ) 规范描述了 JNI Invocation API 加载或者卸载,Java 虚拟机时。java虚拟机的退出情况
代码操作退出
不管是 System 还是 runTime 调用到最后都是 shutDown 类中的 halt的halt 方法 来调用 halt0本地方法来结束进程
/* The halt method is synchronized on the halt lock
* to avoid corruption of the delete-on-shutdown file list.
* It invokes the true native halt method.
*/
static void halt(int status) {
synchronized (haltLock) {
halt0(status);
}
}
JVM 发展历程
Sun Classic VM
简介
早在 1996 年 Java 1.0 版本 的时候 Sun 公司 发布了一款名为Sun Classic VM 的 Java 虚拟机 它同时也是世界上第一款 Java 虚拟机 ,在 Java 1.4 的版本中 被淘汰
**特点: 这款虚拟机内部只提供解释器不提供 JIT **
如果需要使用JIT 需要外挂,但是一旦使用了JIT编译器,JIT就会接管虚拟机状态的执行系统,解释器将不在工作,解释器不能和编译器配合工作 现在都 hotspot VM
内置了此虚拟机
Exact VM
简介
为了解决上一个虚拟机的问题DK 1.2 的以后 sun 提供了此虚拟机
Exact Memory Management 准确式内存管理
- 也可以叫 Non - Conservative /Accurate Memory Management
- 虚拟机可以准确的知道内存中某个位置的数据 具体是什么类型
特点:
- 热点代码编译探测
- 编译器与解释器可以混合工作
不过只在 SUN公司自己的服务器上使用 ,还没有大展身手 被 hotspot VM
替换
HotSpot VM
HotSpot VM 历史:
简介
- 最初是一家叫做 Longview Technologies 的小公司
- 1997 这个公司被 sun收购,2009年 sun 被甲骨文收购
- JDK 1.3 的时候 Hotspot VM 成为默认虚拟机
此后 所有的版本默认都是使用的HotSpot VM
虚拟机
特点:
- 通过计数器 找到最具编译价值的代码,出发即时编译或者栈上编译
- 通过编译器与解释器同时协作,在最优化的程序响应时间与最佳的执行性能中取得平衡
BEA JRockit
简介
JRockit 专注于服务器端,这个虚拟机不关注程序的启动速度,因此 JRockit 内部不包含解释器实现,全部代码,都靠即时解释器后执行,
大量测试基准:JRockit 是世界上 最快的虚拟机,使用JRockit速度显著提高(70%),硬件上也有成本的减少(50%)
优质特点:
- JRockit 面向延迟敏感性应用提供解决方案 JRockit real time 提供以毫秒或者微秒级别的JVM响应时间,适合财务,军事指挥,电信网络等需求
- MissionControl工作套件,它是一组以极低开销来监控,管理 , 分析生产环境中的应用工具
2008 年 BEA 被甲骨文收购
优化:
甲骨文整合了两大虚拟机的优势,在JDK 8中 在Hotspot 基础上 整合了JRockit 的优秀特性
IBM J9
简介
全称叫 : IBM Technology for java Virtual Machine 简称IT4J内部代号 J9
应用场景 : 服务端,桌面,嵌入式等
广泛用于 IBM的各种Java 产品
目前 最有影响力的三大商用虚拟机之一,也号称是世界上最快的Java虚拟机,
2017左右 有影响力 J9 VM 命名为 OpenJ9 交给 Eclipse 会管理 也成为 Eclipse OpenJ9
Apache Harmony
简介
Apache 也曾经退出过JDK 1.5 和 JDK1.6 兼容的Java运行平台 Apache Harmony
它是 IBM和intel 联合开发的开源 JVM 受到同样开源的 OpenJDK 压制,SUN坚决不给Harmony
获得JCP认证,最终 2011 年 停止,IBM转而参与 OpenJDK
虽然没有大规模商用,但是它的类库被安卓SDK 吸纳,继续发光发热
Microsoft JVM
简介
微软为了 ie3 浏览器 Java Applets 开发了 Microsoft JVM 只能再 window 平台运行 但确是win端 性能最好用的JVM
特点:只能在Microsoft平台运行
1997 Sun以侵犯商标和不正当竞争指控微软成功,导致微软赔了很多钱,最后再 win环境中移除了Microsoft JVM
Dalvik VM
简介
谷歌开发的 应用于安卓系统 并且在 安卓 2.2 中提供了JIT 发展迅猛,Dalvik VM只能做虚拟机,而不能称作java虚拟机,因为它没有遵守java虚拟机的规范
区别 不能直接执行Java CLass
基于寄存器架构 不是JVM的栈架构
执行的是编译以后的dex文件,执行效率较高,
这个dex : 可以通过class转换成dex 使用java语法来编写应用程序,可以直接使用大部分都Java API等
不过再 安卓 5.0 已经替换成了 ART VM
Graal VM
简介
2018年四月份 甲骨文 公开了 Graal VM号称 Run Programs Faster Anywhere(使用任何的程序在任何场景更快)
与 1995 年的 编写一次 任意运行 遥遥呼应,
特性
怎正意义上的全栈虚拟机 可以作为任何语言的运行平台使用
- 支持不同语言中混用对方的接口和对象,支持这些语言已经编写好的本地库文件
- 工作原理是将这些语言的源代码或者源代码编译后的中间格式,通过转换器转为能被 Graal VM接受的中间标识,Graal VM提供Trffle工具快速构建面向一种语言的解释器,在运行的时候还可以即时编译优化,获得比原生编译器更优秀的效率
- 如果有一天 Hotspot VM会被替代 最有机会的就是 Graal VM但是替换的过程中 不会影响Java软件生态的一分一毫