JVM解毒——JVM与Java体系结构
你是否也遇到过这些问题?
- 运行线上系统突然卡死,系统无法访问,甚至直接OOM
- 想解决线上JVM GC问题,但却无从下手
- 新项目上线,对各种JVM参数设置一脸懵逼,直接默认,然后就JJ了
- 每次面试都要重新背一遍JVM的一些原理概念性东西
这段广告语写的好,趁着在家办公学习下JVM,先列出整体知识点
点赞+收藏 就学会系列,文章收录在 GitHub JavaEgg ,N线互联网开发必备技能兵器谱
Java开发都知道JVM是Java虚拟机,上学时还用过的VM也叫虚拟机,先比较一波
虚拟机与Java虚拟机
所谓虚拟机(Virtual Machine),就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。
- Visaual Box,VMware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台
- 程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为Java字节码指令
JVM 是什么
JVM
是 Java Virtual Machine
(Java虚拟机)的缩写,JVM
是一种用于计算设备的规范,它是一个虚构的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
Java虚拟机是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里。
特点
- 一次编译,到处运次(跨平台)
- 自动内存管理
- 自动垃圾回收功能
字节码
我们平时所说的java字节码,指的是用java语言编写的字节码,准确的说任何能在jvm平台上执行的字节码格式都是一样的,所以应该统称为jvm字节码。
不同的编译器可以编译出相同的字节码文件,字节码文件也可以在不同的jvm上运行。
Java虚拟机与Java语言没有必然的联系,它只与特定的二进制文件格式——Class文件格式关联,Class文件中包含了Java虚拟机指令集(或者称为字节码、Bytecodes)和符号集,还有一些其他辅助信息。
Java代码执行过程
JVM的位置
JVM是运行在操作系统之上的,它与硬件没有直接的交互。
JDK
(Java Development Kit) 是 Java
语言的软件开发工具包(SDK
)。JDK
物理存在,是 Java Language
、Tools
、JRE
和 JVM
的一个集合。
JVM整体结构
JVM的架构模型
Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构。
两种架构之间的区别:
- 基于栈式架构的特点
- 设计和实现更简单,适用于资源受限的系统;
- 避开了寄存器的分配难题,使用零地址指令方式分配;
- 指令流中的指令大部分是零地址指令,其执行过程依赖于操作栈。指令集更小,编译器容易实现;
- 不需要硬件支持,可移植性更好,更好实现跨平台
- 基于寄存器架构的特点
- 典型的应用是X86的二进制指令集:比如传统的PC以及Android的Davlik虚拟机;
- 指令集架构则完全依赖硬件,可移植性差;
- 性能优秀和执行更高效;
- 花费更少的指令去完成一项操作;
- 大部分情况下,基于寄存器架构的指令集往往都以一地址指令、二地址指令和三地址指令为主,而基于栈式架构的指令集却是以零地址指令为主
由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的,优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。
分析基于栈式架构的JVM代码执行过程
进入class文件所在目录,执行javap -v xx.class
反解析(或者通过IDEA插件Jclasslib
直接查看),可以看到当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等信息。
以上图中的 1+2 为例说明:
Classfile /Users/starfish/workspace/myCode/starfish-learning/starfish-learn/target/classes/priv/starfish/jvm/JVM1.class
Last modified 2020-2-7; size 487 bytes
MD5 checksum 1a9653128b55585b2745270d13b17aaf
Compiled from "JVM1.java"
public class priv.starfish.jvm.JVM1
SourceFile: "JVM1.java"
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#22 // java/lang/Object."<init>":()V
#2 = Class #23 // priv/starfish/jvm/JVM1
#3 = Class #24 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 Lpriv/starfish/jvm/JVM1;
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 args
#14 = Utf8 [Ljava/lang/String;
#15 = Utf8 i
#16 = Utf8 I
#17 = Utf8 j
#18 = Utf8 k
#19 = Utf8 MethodParameters
#20 = Utf8 SourceFile
#21 = Utf8 JVM1.java
#22 = NameAndType #4:#5 // "<init>":()V
#23 = Utf8 priv/starfish/jvm/JVM1
#24 = Utf8 java/lang/Object
{
public priv.starfish.jvm.JVM1();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lpriv/starfish/jvm/JVM1;
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_1 //冒号前的数字表示程序计数器的数,常量1入栈
1: istore_1 //保存到1的操作数栈中,这里的1表示操作数栈的索引位置
2: iconst_2
3: istore_2
4: iload_1 //加载
5: iload_2
6: iadd //常量出栈,求和
7: istore_3 //存储到索引为3的操作数栈
8: return
LineNumberTable:
line 6: 0
line 7: 2
line 8: 4
line 9: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
2 7 1 i I
4 5 2 j I
8 1 3 k I
MethodParameters: length = 0x5
01 00 0D 00 00
}
JVM生命周期
虚拟机的启动
Java虚拟机的启动是通过引导类加载器(Bootstrap Class Loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的。
虚拟机的执行
- 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序
- 程序开始执行时它才运行,程序结束时它就停止
- 执行一个所谓的Java程序的时候,真正执行的是一个叫做Java虚拟机的进程
- 你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。 Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、只接受一个字符串数组。在程序执行时,你必须给Java虚拟机指明这个包含main()方法的类名。
虚拟机的退出
有以下几种情况:
- 程序正常执行结束
- 程序在执行过程中遇到了异常或错误而异常终止
- 由于操作系统出现错误而导致Java虚拟机进程终止
- 某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理器也允许这次exit或halt操作
- 除此之外,JNI(Java Native Interface)规范描述了用
JNI Invocation API
来加载或卸载Java虚拟机时,Java虚拟机的退出情况
Java和JVM规范
Java Language and Virtual Machine Specifications
JVM发展历程
JDK 版本升级不仅仅体现在语言和功能特性上,还包括了其编译和执行的 Java 虚拟机的升级。
- 1990年,在Sun计算机公司中,由Patrick Naughton、MikeSheridan及James Gosling领导的小组Green Team,开发出的新的程序语言,命名为Oak,后期命名为Java
- 1995年,Sun正式发布Java和HotJava产品,Java首次公开亮相
- 1996 年,JDK 1.0 发布时,提供了纯解释执行的 Java 虚拟机实现:Sun Classic VM。
- 1997 年,JDK 1.1 发布时,虚拟机没有做变更,依然使用 Sun Classic VM 作为默认的虚拟机
- 1998 年,JDK 1.2 发布时,提供了运行在 Solaris 平台的 Exact VM 虚拟机,但此时还是用 Sun Classic VM 作为默认的 Java 虚拟机,同时发布了JSP/Servlet、EJB规范,以及将Java分成J2EE、J2SE、J2ME
- 2000 年,JDK1.3 发布,默认的 Java 虚拟机由 Sun Classic VM 改为 Sun HotSopt VM,而 Sun Classic VM 则作为备用虚拟机
- 2002 年,JDK 1.4 发布,Sun Classic VM 退出商用虚拟机舞台,直接使用 Sun HotSpot VM 作为默认虚拟机一直到现在
- 2003年,Java平台的Scala正式发布,同年Groovy也加入了Java阵营
- 2004年,JDK1.5发布,同时JDK1.5改名为JDK5.0
- 2006年,JDK6发布,同年,Java开源并建立了OpenJDK。顺理成章,Hotspot虚拟机也成为了OpenJDK默认虚拟机
- 2008年,Oracle收购BEA,得到了JRockit虚拟机
- 2010年,Oracle收购了Sun,获得Java商标和HotSpot虚拟机
- 2011年,JDK7发布,在JDK1.7u4中,正式启用了新的垃圾回收器G1
- 2014年,JDK8发布,用元空间MetaSpace取代了PermGen
- 2017年,JDK9发布,将G1设置为默认GC,替代CMS
Sun Classic VM
- 世界上第一款商用 Java 虚拟机。1996年随着Java1.0的发布而发布,JDK1.4时完全被淘汰;
- 这款虚拟机内部只提供解释器;
- 如果使用JIT编译器,就需要进行外挂。但是一旦使用了JIT编译器,JIT就会接管虚拟机的执行系统,解释器就不再工作,解释器和编译器不能配合工作;
- 现在hotspot内置了此虚拟机
Exact VM
- 它的执行系统已经具备了现代高性能虚拟机的雏形:如热点探测、两级即时编译器、编译器与解析器混合工作模式等;
- 使用准确式内存管理:虚拟机可以知道内存中某个位置的数据具体是什么类型;
- 在商业应用上只存在了很短暂的时间就被更优秀的 HotSpot VM 所取代
Sun HotSpot VM
- 它是 Sun JDK 和 OpenJDK 中所带的虚拟机,也是目前使用范围最广的 Java 虚拟机;
- 继承了 Sun 之前两款商用虚拟机的优点(如准确式内存管理),也使用了许多自己新的技术优势,如热点代码探测技术(通过执行计数器找出最具有编译价值的代码,然后通知 JIT 编译器以方法为单位进行编译;
- Oracle 公司分别收购了 BEA 和 Sun,并在 JDK8 的时候,整合了 JRokit VM 和 HotSpot VM,如使用了 JRokit 的垃圾回收器与 MissionControl 服务,使用了 HotSpot 的 JIT 编译器与混合的运行时系统。
BEA JRockit VM
- 专注于服务器端应用,内部不包含解析器实现;
- 号称是世界上最快的JVM
IBM J9 VM
- 全称:IBM Technology for Java Virtual Machine,简称IT4J,内部代号:J9
- 市场定位于HotSpot接近,服务器端、桌面应用、嵌入式等多用途VM
- 目前是有影响力的三大商用虚拟机之一
虚拟机有很多,此外还有Azul VM、Liquid VM、Apache Harmony、TaobaoJVM、Graal VM等
参考
《深入理解Java虚拟机》
《尚硅谷JVM》
JVM解毒——JVM与Java体系结构的更多相关文章
- 【JVM之内存与垃圾回收篇】JVM与Java体系结构
JVM与Java体系结构 前言 作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问题? 运行着的线上系统突然卡死,系统无法访问,甚至直接OOMM! 想解决线上JVM GC问题,但却无从下手. 新 ...
- JVM与Java体系结构
参考笔记:https://blog.csdn.net/weixin_45759791/article/details/107322503 前言 作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问 ...
- <JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- JVM1 JVM与Java体系结构
目录 JVM与Java体系结构 虚拟机与Java虚拟机 虚拟机 Java虚拟机 JVM的位置 JVM的整体结构 Java代码执行流程 JVM的架构模型 基于栈的指令级架构 基于寄存器的指令级架构 两种 ...
- JVM上篇:JVM与Java体系结构
JVM笔记 JVM传言 Java不是最强大的语言,但是JVM是最强大的虚拟机 虚拟机分类 系统虚拟机 类似VMware,就属于系统虚拟机,它提供了一个可运行完整操作系统的平台 程序虚拟机 Java虚拟 ...
- Java -JVM:JVM百科
ylbtech-Java -JVM:JVM百科 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机 ...
- [转帖]JVM总结--JVM体系结构
JVM总结--JVM体系结构 https://blog.csdn.net/samjustin1/article/details/52215274 需要不断的学习才可以. 2016年08月15日 22: ...
- JVM性能优化,提高Java的伸缩性
很多程序员在解决JVM性能问题的时候,花开了很多时间去调优应用程序级别的性能瓶颈,当你读完这本系列文章之后你会发现我可能更加系统地看待这类的问题.我说过JVM的自身技术限制了Java企业级应用的伸缩性 ...
- java之Jvm学习--JVM运行机制
JVM启动流程 1.java虚拟机启动的命令是通过java +xxx(类名,这个类中要有main方法)或者javaw启动的. 2.执行命令后,系统第一步做的就是装载配置,会在当前路径中寻找jvm的co ...
随机推荐
- 【JavaScript学习笔记】数据类型
1.获取数据类型 typeof 用法: typeof variable or typeof(variable) JavaScript中总共有6种数据类型,string.number.boolean ...
- txLive模块(直播类)试用分享
本文出自APICloud官方论坛, 感谢论坛版主uoaccw的分享. txLive 模块封装了腾讯云直播服务 https://docs.apicloud.com/Client-API/Open-SDK ...
- cf 450b 矩阵快速幂(数论取模 一大坑点啊)
Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, ple ...
- 依赖注入之IConfiguration
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; ...
- postman的测试,用对象接收所有的字符串
1.post请求 Headers: Content-Type application/json { "taskId":"1000001161", " ...
- (数据科学学习手札73)盘点pandas 1.0.0中的新特性
本文对应脚本及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 毫无疑问pandas已经成为基于Pytho ...
- 关于Hive中case when不准使用子查询的解决方法
在公司用Hive实现个规则的时候,遇到了要查询某个字段是否在另一张表中,大概情况就是 A表: id value1 value2 1 100 0 2 101 1 3 102 1 B表: value1 1 ...
- 无法解析导入javax.mail
本文链接:https://blog.csdn.net/aaqian1/article/details/89357195下载地址: http://www.oracle.com/technetwork/j ...
- 深入Nodejs模块fs - 文件系统操作
node 的fs文档密密麻麻的 api 非常多,毕竟全面支持对文件系统的操作.文档组织的很好,操作基本分为文件操作.目录操作.文件信息.流这个大方面,编程方式也支持同步.异步和 Promise. 本文 ...
- applyColorMap 在OpenCV中对灰度图进行颜色映射,实现数据的色彩化
什么是色彩映射: 说直白点就是将各种数据映射成颜色信息,例如:温度,高度,压力,密度,湿度,城市拥堵数据等等 色彩化后更加直观表达 在OpenCV里可以使用 Mat im_gray = imread( ...