深入Java虚拟机(程序运行)

引子:打开黑匣子 心中有数

老实说,对于C++的整个编译运行过程,我并没有全面的了解,好几次被问住了,看来是汇编没有学好,但是在看完《深入Java虚拟机》之后,对于Java代码到运行的每一个细节,有了更全面的认识。

描述一下整体的流程:程序员根据Java API编写Java程序,各种类文件,用一个Java编译器编译Java程序为class文件,class文件通过一定的分发方式被Java虚拟机装载、连接、初始化,变成Java虚拟机方法区的Class类,然后被实例化为堆区的对象,随着虚拟机的执行,对象可能不再被引用而被垃圾回收,随后class文件可能变得不可触及而被虚拟机卸载,最后虚拟机随着最后一个非后台的线程的结束而退出。



步骤一:编写Java程序【生成 *.java】

一个Java文件只允许定义一个public的Java类,因为虚拟机是通过文件名的机制搜索类型定义的。Java程序员根据Java API编写程序。



步骤二:编译Java文件为class文件【生成class】

class文件的结构包含了Java虚拟机所需要知道的关于类的所有信息。文件内容大致为:魔术、版本、常量池、this_class、super_class、接口、字段、方法、属性

class文件稍微有点绕的是常量池。常量池中的常量不是我们程序员角度理解的狭义的常量,一个类的名字是常量,一个方法的描述是常量,一个属性的描述也是常量。常量池中包含了所有的字面信息,通过索引,你可以查找到一个方法的名字和描述,一个字段的名字,一个常量字符串 等等。在连接模型中,有一个解析的过程,就是因为在字节码中,所有的都是符号引用,比如调用了某个方法,字节码是说调用了常量区的一项内容,这项内容表示的是一个方法,因此,这就需要进行解析,将这个常量区的引用转变为方法的直接引用。常量池中被解析的项都会被标记,这样下一次就不用再次解析了。

所以我们看class文件是如何完全表达一个类的信息的:类的名字通过this_class指向的常量池可以得到,父类通过super_class,接口、方法、字段 都可以通过相应的文件段在常量区中找到基本信息。方法的字节码在方法的属性字段中定义了字节码,方法的属性还定义了有多少个变量,需要用多大的栈空间。



步骤三:装载、连接、初始化【生成类】

在最开始我们强调通过一定的分发方式,这是因为class文件可能存在与运行的虚拟机上,也可能存在与网络上,通过用户自定义的类型装载器,开发人员可以定义灵活的机制获取代码。

1,装载。装载必须产生代表该类型的二进制流(读文件或者从网络或者其他方式),解析二进制数据为内部数据结构,创建一个 java.lang.Class类

2,验证。验证是否符合Java语言的语义。

3,准备。为类变量分配内存,并初始化为默认值。

4,解析。就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把他们替换为直接引用的过程。在符号引用被首次使用之前,解析都是可选的。

5,初始化。初始化为“正确”的初始值,即程序员期望的初始值,代码中static定义的,被收集到 <clinit> 方法中。



步骤四:类实例生成,垃圾回收【生成类实例:对象】

现在一切具备,程序开始运行。内存分别如下图



到此时,我想我们对整个流程有了一个全面的认识(我们刻意忽略了安全相关的话题)

从虚拟机的角度,最开始是面对的class文件,读入并解析class文件,将PC寄存器设置为main入口,然后开始执行字节码。字节码总是针对运算栈的,所以虚拟机知道操作数就在运算栈那里。字节码由操作符和操作数定义,操作数可能为Java栈的局部变量,可能为常量池的引用。如果是常量池的引用,并且还未解析,则需要进行解析。任何时候,栈中都是基本变量或者对象引用,按部就班执行就行了。

时间: 2024-08-28 14:40:07

深入Java虚拟机(程序运行)的相关文章

深入理解Java虚拟机:运行时数据区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁.根据<Java虚拟机规范(Java SE 7版)>的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域. 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里

深入理解Java虚拟机笔记---运行时栈帧结构

栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区的虚拟机栈(Virtual Machine Stack)的栈元素.栈帧存储了方法的局部变量表,操作数栈,动态连接和方法返回地址等信息.第一个方法从调用开始到执行完成,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程. 每一个栈帧都包括了局部变量表,操作数栈,动态连接,方法返回地址和一些额外的附加信息.在编译代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到了方法表的

深入JAVA虚拟机之运行时数据区

前言最近在啃一本书<深入JAVA虚拟机>,这本书不是第一次看,可以说是从大学就开始看,这一次应该算第三次啃这本书,也应该说算是第一次真正啃这本书.大学的时候,只是好奇表层的一些神奇现象,随着工作几年后,现在回过头来再次啃这本书,对于表层的那些以前觉得神奇的现在已经感觉乏味,反而对于底层是如何实现.如何运作的越来越着迷.这也是这次看这本书的初衷.通过写博客记录下自己的学习过程,也方便以后回头看看现在的看法想法在将来会变成怎样.如果我在下面的文字表述上或者理解上有误解或者错误,请各位大神能够留言指

java虚拟机2.运行时内存对象

对象的创建 虚拟机遇到一条new指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过. 在类加载检查通过后,接下来虚拟机将为新生对象分配内存.对象所需内存的大小在类加载完成后便可完全确定,为对象分配空间的任务等同于把一块确定大小的内存从java堆中划分出来. 假设java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那分配内存就仅仅是把那个指针向空闲空间那边挪动

java虚拟机3.运行时内存异常

在java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能. java堆溢出 java堆用于存储对象实例,只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆得容量限制后就会产生内存溢出异常.当出现java堆内存溢出时,异常堆栈信息"java.lang.OutOfMemoryError"会跟着进一步提示"java heap space&qu

详细理解Java虚拟机的运行过程

基本概述: Java虚拟机简称JVM,是JRE中的一部分,也是Java程序运行的最关键的部分.完整的Java运行流程大致包括编译.java文件形成.class文件,然后根据.class文件的内容进行一系列的步骤使整个程序运行起来.其中将.java文件编译为.class文件由Java编译器完成,而由.class文件进而完成整个运行过程则主要是由JVM来完成的.由于所有的编译链接过程都由JRE来完成,所以Java具有良好的平台可移植性,不依赖具体的操作系统. 具体结构及功能: 1.Class Loa

Java 虚拟机程序执行:02 虚拟机的类加载机制

虚拟机的类加载机制 虚拟机的类加载机制 类加载的时机 类的显式加载和隐式加载 类加载的过程 类的生命周期 加载 加载的 3 个阶段 分类 验证 准备 解析 初始化 类加载器 如何判断两个类 “相等” 类加载器的分类 双亲委派模型 类加载的时机 JVM 会在程序第一次主动引用类的时候,加载该类,被动引用时并不会引发类加载的操作.也就是说,JVM 并不是在一开始就把一个程序就所有的类都加载到内存中,而是到不得不用的时候才把它加载进来,而且只加载一次.那么什么是主动引用,什么是被动引用呢? 主动引用

Java 虚拟机程序执行:01 Class文件的组成结构

Class文件的组成结构 Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件中,中间没有任何分隔符.Java 虚拟机规范规定 Class 文件采用一种类似 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表,我们之后也主要对这两种类型的数据类型进行解析. 无符号数: 无符号数属于基本数据类型,以 u1.u2.u4.u8 分别代表 1 个字节.2 个字节.4 个字节和 8 个字节的无符号数,可以用它来描述数字.

Java多线程-程序运行堆栈分析

class文件内容 class文件包含JAVA程序执行的字节码:数据严格按照格式紧凑排列在class文件中的二进制流,中间无任何分隔符:文件开头有一个0xcafebabe(16进制)特殊的一个标志. JVM运行时数据区 线程独占:每个线程都会有它独立的空间,随线程生命周期而创建和销毁 线程共享:所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁 方法区 JVM用来存储加载的类信息.常量.静态变量.编译后的代码等数据. 虚拟机规范中这是一个逻辑区划.具体实现根据不同虚拟机来实现. 如:ora

Java 虚拟机的运行模式

这几天在读周志明老师的<深入理解JVM虚拟机> 讲到了 java的运行模式, 有mixed 模式 interpret模式还有compile模式.效果如下面所示 java -version java -Xint -version java -Xcomp -version 原文地址:https://www.cnblogs.com/jinanxiaolaohu/p/11211376.html