JVM 工作原理和流程

作为一名Java使用者,掌握JVM的体系结构也是必须的。

说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API)。它们的关系如下图所示:


运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。

Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。这个平台的结构如下图所示:


在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;在JVM 的上方是Java的基本类库和扩展类库以及它们的API, 利用Java API编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。 

JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了。下面我们从JVM的体系结构和它的运行过程这两个方面来对它进行比较深入的研究。

1、Java虚拟机的体系结构

·每个JVM都有两种机制:

①类装载子系统:装载具有适合名称的类或接口

②执行引擎:负责执行包含在已装载的类或接口中的指令 

·每个JVM都包含

方法区、Java堆、Java栈、本地方法栈、指令计数器及其他隐含寄存器



对于JVM的学习,在我看来这么几个部分最重要:

Java代码编译和执行的整个过程

JVM内存管理及垃圾回收机制

下面分别对这几部分进行说明:

2、Java代码编译和执行的整个过程

也正如前面所说,Java代码的编译和执行的整个过程大概是:开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。

(1)Java代码编译是由Java源码编译器来完成,也就是Java代码到JVM字节码(.class文件)的过程。 流程图如下所示:


(2)Java字节码的执行是由JVM执行引擎来完成,流程图如下所示:



Java代码编译和执行的整个过程包含了以下三个重要的机制:

·Java源码编译机制

·类加载机制

·类执行机制


(1)Java源码编译机制

Java 源码编译由以下三个过程组成:

①分析和输入到符号表

②注解处理

③语义分析和生成class文件

流程图如下所示:

最后生成的class文件由以下部分组成:

①结构信息:包括class文件格式版本号及各部分的数量与大小的信息

②元数据:对应于Java源码中声明与常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法声明信息和常量池

③方法信息:对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息

(2)类加载机制
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:


①Bootstrap ClassLoader

负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

②Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

③App ClassLoader

负责记载classpath中指定的jar包及目录中class

④Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader


加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

(3)类执行机制

JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。

JVM执行class字节码,线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。栈的结构如下图所示:


3、JVM内存管理及垃圾回收机制

JVM内存结构分为:方法区(method),栈内存(stack),堆内存(heap),本地方法栈(java中的jni调用),结构图如下所示:


(1)堆内存(heap)

所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。 
操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。但由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。这时由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,它不是在堆,也不是在栈,而是直接在进程的地址空间中保留一块内存,虽然这种方法用起来最不方便,但是速度快,也是最灵活的。堆内存是向高地址扩展的数据结构,是不连续的内存区域。由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大

(2)栈内存(stack)

在Windows下, 栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是固定的(是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 由系统自动分配,速度较快。但程序员是无法控制的。

堆内存与栈内存需要说明:

基础数据类型直接在栈空间分配,方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量 。方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完成后从栈空间回收。局部变量new出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束后,栈空间立刻被回收,堆空间区域等待GC回收。方法调用时传入的literal参数,先在栈空间分配,在方法调用完成后从栈空间收回。字符串常量、static在DATA区域分配,this在堆空间分配。数组既在栈空间分配数组名称,又在堆空间分配数组实际的大小。

如:


(3)本地方法栈(java中的jni调用)

用于支持native方法的执行,存储了每个native方法调用的状态。对于本地方法接口,实现JVM并不要求一定要有它的支持,甚至可以完全没有。Sun公司实现Java本地接口(JNI)是出于可移植性的考虑,当然我们也可以设计出其它的本地接口来代替Sun公司的JNI。但是这些设计与实现是比较复杂的事情,需要确保垃圾回收器不会将那些正在被本地方法调用的对象释放掉。

(4)方法区(method)

它保存方法代码(编译后的java代码)和符号表。存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(Permanet Generation)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。

垃圾回收机制

堆里聚集了所有由应用程序创建的对象,JVM也有对应的指令比如 new, newarray, anewarray和multianewarray,然并没有向 C++ 的 delete,free 等释放空间的指令,Java的所有释放都由 GC 来做,GC除了做回收内存之外,另外一个重要的工作就是内存的压缩,这个在其他的语言中也有类似的实现,相比 C++ 不仅好用,而且增加了安全性,当然她也有弊端,比如性能这个大问题。


4、Java虚拟机的运行过程示例

上面对虚拟机的各个部分进行了比较详细的说明,下面通过一个具体的例子来分析它的运行过程。

虚拟机通过调用某个指定类的方法main启动,传递给main一个字符串数组参数,使指定的类被装载,同时链接该类所使用的其它的类型,并且初始化它们。例如对于程序:


编译后在命令行模式下键入: java HelloApp run virtual machine 

将通过调用HelloApp的方法main来启动java虚拟机,传递给main一个包含三个字符串”run”、”virtual”、”machine”的数组。现在我们略述虚拟机在执行HelloApp时可能采取的步骤。

开始试图执行类HelloApp的main方法,发现该类并没有被装载,也就是说虚拟机当前不包含该类的二进制代表,于是虚拟机使用ClassLoader试图寻找这样的二进制代表。如果这个进程失败,则抛出一个异常。类被装载后同时在main方法被调用之前,必须对类HelloApp与其它类型进行链接然后初始化。链接包含三个阶段:检验,准备和解析。检验检查被装载的主类的符号和语义,准备则创建类或接口的静态域以及把这些域初始化为标准的默认值,解析负责检查主类对其它类或接口的符号引用,在这一步它是可选的。类的初始化是对类中声明的静态初始化函数和静态域的初始化构造方法的执行。一个类在初始化之前它的父类必须被初始化。整个过程如下:

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

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

相关文章

中国未来技术学院盘点

来源:科学网8月19日,上海交通大学未来技术学院正式揭牌成立。香港首富、宁德时代公司董事长曾毓群担任未来技术学院名誉院长,宁德时代首席制造官和工程制造及研发体系联席总裁倪军出任首任院长。一家市值超万亿的高科技龙头企业掌门人和高管&…

QT高级编程之QT基本概览

QT高级编程 主要从以下几个方面来介绍QT高级编程,并介绍QT相关的概念。 1、 QT部件Widget; 2、 QT信号与槽机制; 3、 对象树关系; 4、 布局管理; 5、标准对话框以及自定义对话框; 6、文件与目录&#xff…

计算机视觉中的自注意力

来源:机器学习研究组订阅自从引入网络以来,深度学习中的注意力机制在机器翻译和 社区中广受欢迎。然而,在计算机视觉中,卷积神经网络 (CNN) 仍然是常态,自注意力才刚刚开始慢慢渗透到研究的主体中,要么补充…

QT信号与槽-启动系统程序以及相关控件介绍

1.1 创建一个继承至QWidget的项目。 1.2 设计界面,分析界面采用的布局方式。 首先,每行控件采用水平布局方式,第三行为了使控件靠右,前面添加一个占位控件。三行采用垂直平局;选中控件,通过右键可以控件的布局方式&a…

科技部向全社会征集颠覆性技术研发方向

来源:人民网据科技部网站消息,为提升我国重大科技创新方向前瞻布局能力,加快推动颠覆性技术创新,科技部办公厅拟面向各有关单位和广大科研人员,开展颠覆性技术研发方向建议征集工作,对于符合条件的建议&…

springboot前后端分离项目MultipartFile获取前端传的file为null问题

【问题描述】 springbootvue 前后端分离项目,在对接上传文件功能时,一直显示文件为空。 【分析】 查找了很多博客,解决方法五花八门,但原因应该还是 springboot自带的org.springframework.web.multipart.MultipartFile和Multi…

计算机网络( 二十二)-数据链路层(补充)

1.链路link:结点------>相邻结点的物理线路。 2.数据链路:物理线路通信协议,通信协议(通信规程)用来控制数据的传输。 3.最常用网络适配器(硬件、软件)来实现协议。适配器包括了数据链路层和物理层两层的功能。 4.数据链路层的协议数据单元PDU------帧…

《科学之路》| 图灵奖得主杨立昆人工智能十问:AI会统治人类吗?

来源:《科学之路》作者:杨立昆封面:Yukai Du即便是最先进的人工智能系统也存在局限性,它们还不如一只猫聪明。人工智能常常被认为是一项将要颠覆世界的技术,从这一概念诞生至今的65年中,无数电影与小说塑造…

计算机网络(二十三)-网络层-概述与数据交换方式

一.网络层的功能 主要任务是把分组从源端传送到目的端,为分组交换网上的不同主机提供通信服务。 网络层传输单位是数据报。功能 路由选择与分组转发,最佳路径。异构网络互联;拥塞控制; 若所有结点都来不及接收分组,网…

数字大脑学术沙龙:“城市大脑与应急管理专题研讨会”成功召开

来源:城市大脑全球标准研究组2021年以来城市大脑的建设与研究获得了长足发展,数百个城市开展了城市大脑的建设与规划,取得了诸多成果。于此同时,伴随着疫情、水灾、交通事故、环境事故的不断出现,城市大脑如何应对应急…

Java 注解:@PostConstruct和@PreConstruct

从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解(Annotation):PostConstruct和PreConstruct。这两个注解被用来修饰一个非静态的void()方法.而且这个方法不能有抛出异常声明。 使用方式,例如&#xff…

计算机网络(二十四)-路由算法及路由协议

1.1 路由算法 将最优的路径填入路由转发表。 1.2 路由算法分类 静态路由算法(非自适应路由算法):管理员手动配置路由信息。 简便、可靠,在负载稳定、拓扑变化不大的网络中运行效果很好,广泛用于高度安全性的军事网络和较小的商业网络。 动…

研究速递:老年人的心智能力不一定在衰减,抗干扰的能力会更强

来源: 混沌巡洋舰长期以来,人们一直认为,衰老会导致我们的心智能力大幅下降。现在,乔治城大学医学中心的新研究,反驳这一观点,研究结果发表在2021年8月19日的《自然---- 人类行为》杂志上,由于世…

计算机网络(二十五)-IP数据报格式

1.1 TCP/IP协议栈 1.2 IP数据报格式 IP数据报如果过大,就会对它进行分片,每个分片为一个分组。 版本指的是IPv4或IPv6;首部长度:单位是4B(4字节),最小为5;区分服务:指示期望获得哪种类型的服…

NLP≠NLU,机器学习无法理解人类语言

来源:图灵人工智能 编译:吴彤校对:暮编辑:琰琰长期以来,我们一直在与机器沟通:编写代码--创建程序--执行任务。然而,这些程序并非是用人类“自然语言“编写的,像Java、Python、C和C …

CentOS 7 安装并启动Nginx

一、安装必要的库 1、安装gcc gcc-c yum install -y gcc gcc-c 2、gzip模块需要 zlib 库 cd /usr/local wget http://zlib.net/zlib-1.2.11.tar.gz tar -zxvf zlib-1.2.11.tar.gz cd zlib-1.2.11 ./config make && make install3、重写模块需要pcre库 cd /usr/loc…

计算机网络(二十六)-IP数据报分片

一.最大传输单元MTU 1.1 数据链路层数据帧可封装数据的上限。以太网的MTU是1500字节; 1.2 当数据报超过了MTU,则进行分片; 1.3 分片-IP数据报格式 标识:同一数据报的分片使用同一标识;标志:只有两位有意…

论文速递:智能作为信息处理系统

来源:混沌巡洋舰圣塔菲研究院4月就智能的本质(不管其是人类的,还是机器的)举行的研讨会,旨在通过跨学科的整合来促进人工智能的发展。研讨会期间,来自不同学科的大牛聚集在一起,讨论如何将智力分…

Nginx启动后无法访问页面

同个人网站 https://www.serendipper-x.cn/,欢迎访问 ! 【问题描述】 Nginx启动后浏览器输入IP地址无法访问页面 一、检查Nginx是否成功启动 ./sbin/nginx -t 二、检查80端口是否开放 三、打开防火墙80端口,重启防火墙 firewall-cmd -…

计算机网络(二十七)-IPv4

一.IP地址 1.1 分类的IP地址 IP地址::{<网络号>,<主机号>} 32位&#xff1a;前八位为网络号&#xff0c;后面的为主机号------>点分十进制表示 路由器也有多个IP地址&#xff1b; 中间的三个组成一个无编号网络(无名网)&#xff1b;整个网络具有6个逻辑上的…