在之前的笔记中记录过,Java程序变成可执行文件的步骤是:源代码——>经过编译变成class文件——>经过JVM虚拟机变成可执行的二进制文件。因此,为了对JVM执行程序的过程有一个好的了解,我们需要先明白class文件到底是什么东西,它里面有那些信息以及如何存储的。

Class类文件结构

   Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑排列在Class文件中。当遇到需要占用超过8位字节的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。

   Class文件格式采用一种类似于C语言结构体的伪结构来存储,这种伪结构中只有两种数据类型:无符号数和表。

   无符号数是基本的数据类型,以u1,u2,u4,u8分别表示1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成的字符串值。

   表是由多个无符号数或者其他表作为数据项构成的复合数据结构,所有表习惯性地以_info结尾。

   我们先来看一下Class文件的格式,然后对这些数据一一进行讲解。

魔数和Class文件的版本

   每个Class文件的头四个字节称为魔数,作用是来表示该文件是一个可以被虚拟机接受的Class文件。其作用类似于扩展名,但扩展名易更改,而魔数来进行类型判别比较安全。

   紧接着的四个字节存储的是Class文件的版本号。第5、6字节为次版本号,第7、8字节为主版本号。

常量池

   版本号之后的就是常量池。常量池是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一。

   常量池中主要存放两大类常量,字面量和符号引用。字面量比较接近于Java语言的常量概念,比如文本字符串、被声明为final的常量值等等而符号引用属于编译原理方面的概念,包括了下面三类常量:1、类和接口的全限定名 2、字段的名称和描述符 3、方法的名称和描述符

   Java代码进行编译的时候,没有C那样用"链接"这一步骤,而是在虚拟机加载Class文件的时候进行动态链接。也就是Class文件不会保存各个方法和字段的最终内存布局信息,因此这些字段和方法的符号引用不经过转换的话是无法被虚拟机使用的。当虚拟机运行的时候,需要从常量池获得对应的符号引用,再在类创建或运行的时候解析并翻译到具体内存地址中 ??

   对这些一一列举也没有什么意义,如果需要某一项的内容,可以单独查找。本章我认为更关键的是对Class文件怎么生成的,怎么运作的理解。

   在常量池中,记载了各种常量(包括系统执行时内部需要的)、方法表(用来记录该类的所有方法)、属性表等。他们的运作方法大同小异:通过已经定义的常量(包括字符串常量、方法名之类的信息)来填充对应的表信息,比如方法表中,我们需要得到方法名、返回值、参数等等信息,这些信息都存储在常量池中,只需要引用到对应位置即可表示。而方法表中更为关键的信息就是Code属性了,Code属性表示了该方法的执行过程。

   先看一下Code属性表的内容:



   里面像attribute_name_index之类都是索引,指向常量池中的一个字符串来表示对应的数据常量。关键的地方是code_length和后面的code,他们用来存储Java源代码编译后生成的字节码指令。code_length代码字节码长度,code用于存储字节码指令的一系列字节流,每一个指令都是一个u1类型的单字节。,当虚拟机读到对应字节码的字节后,他会查询出是什么指令并执行。

   

   通过指令的分析,我们可以看到,通过字节码我们可以实现利用常量池中的数据信息,来分析运行结果并执行的。

   在这个字节码中,它执行的数据交换、方法调用都是基于操作栈进行的,比如2A将对象移动到栈顶,B7是以栈顶对象为接受者,他们都是对一个栈进行的操作,但又有像invokespecial这样带参数的指令,这就与单纯使用堆栈进行操作不相符,因此另一个问题是JVM如何堆字节码执行。

类文件结构——深入理解Java虚拟机 笔记三的更多相关文章

  1. 深入理解Java虚拟机第三版,总结笔记【随时更新】

    最近一直在看<深入理解Java虚拟机>第三版,无意中发现了第三版是最近才发行的,听说讲解的JDK版本升级,新增了近50%的内容. 这种神书,看懂了,看进去了,真的看的很快,并没有想象中的晦 ...

  2. Java内存区域与内存溢出异常——深入理解Java虚拟机 笔记一

    Java内存区域 对比与C和C++,Java程序员不需要时时刻刻在意对象的创建和删除过程造成的内存溢出.内存泄露等问题,Java虚拟机很好地帮助我们解决了内存管理的问题,但深入理解Java内存区域,有 ...

  3. 深入理解Java虚拟机笔记

    1. Java虚拟机所管理的内存 2. 对象创建过程 3. GC收集 4. HotSpot算法的实现 5. 垃圾收集器 6. 对象分配内存与回收细节 7. 类文件结构 8. 虚拟机类加载机制 9.类加 ...

  4. 深入理解java虚拟机笔记Chapter12

    (本节笔记的线程收录在线程/并发相关的笔记中,未在此处提及) Java内存模型 Java 内存模型主要由以下三部分构成:1 个主内存.n 个线程.n 个工作内存(与线程一一对应) 主内存与工作内存 J ...

  5. 深入理解java虚拟机笔记Chapter7

    虚拟机类的加载机制 概述 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类的加载机制. 类加载的时机 J ...

  6. 深入理解java虚拟机(三)对象回收判断算法以及死亡过程

    在堆里面存放着Java几乎所有的对象实例,垃圾收集器要进行垃圾回收,要做的第一步便是找出那些对象是需要回收的. 怎么判断对象是否需要回收? 常用的方法有两种. 1.引用计数算法.为每一个对象添加一个引 ...

  7. 深入理解Java虚拟机笔记——虚拟机类加载机制

    目录 概述 动态加载和动态连接 类加载的时机 类的生命周期 被动引用 例子一(调用子类继承父类的字段) 例子二(数组) 例子三(静态常量) 类加载的过程 加载 验证 准备 解析 符号引用 直接引用 初 ...

  8. 深入理解java虚拟机笔记Chapter8

    运行时栈帧结构 栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈(Virtual Machine Stack)的栈元素.栈帧存储了方法 ...

  9. 深入理解java虚拟机笔记之一

    Java的技术体系主要有支撑java程序运行的虚拟机,提供各开发领域接口支持Java API,java编程语言及许多第三方java框架( 如Spring,Structs等)构成. 可以把Java程序设 ...

随机推荐

  1. [wp]xctf newscenter

    手工注入 查询所有数据库名称和表名 ' union select 1,table_schema,table_name from information_schema.tables# 发现就两个数据库i ...

  2. php phpStudy session存放位置

    如果你仅仅是想知道session保存的文件在哪里,你可以在你的PHP文件当中运行函数:session_save_path之后查看运行结果即可知道session文件的存放目录. 或者: 在php-ini ...

  3. 使用宝塔面板部署tp5网站

    来源:https://www.cnblogs.com/e0yu/p/9102902.html 遇到一个问题,就是当thinkphp5部署在宝塔面板上,会出现这个问题: 参考解决办法: http://w ...

  4. MySQL 入门(1):查询和更新的内部实现

    摘要 在MySQL中,简单的CURD是很容易上手的. 但是,理解CURD的背后发生了什么,却是一件特别困难的事情. 在这一篇的内容中,我将简单介绍一下MySQL的架构是什么样的,分别有什么样的功能.然 ...

  5. IDEA 之 ERROR:无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]

    问题描述:在使用IDEA对JSTL进行测试时出现error:无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core] ...

  6. JAVA进程CPU高的解决方法

    无限循环的while会导致CPU使用率飙升吗?经常使用Young GC会导致CPU占用率飙升吗?具有大量线程的应用程序的CPU使用率是否较高?CPU使用率高的应用程序的线程数是多少?处于BLOCKED ...

  7. Git 常见问题汇总

    git reabse 合并多个commit git rebase -i HEAD~{NUM} git rebase -i start end 会进入一个指定区间的commit列表 根据提示进行文本编辑 ...

  8. jQuery里面click、this事件遇到(Django模型里for)相同的id名和class名想获取值

    遇到的原型是这样的!下面我把它简化一下; click事件: 在浏览器里面只能获取横线上面的值,和下面的第一个值!! 这是因为id等级比class高,而且js要求id不能重复! 当 转载于:https: ...

  9. python基础1习题练习

    python基础1习题练习: #encoding:utf-8 #1.实现用户输入用户名和密码,当用户名为 seven 且 密码为 123 时,显示登陆成功,否则登陆失败! name=input('na ...

  10. Algorithm Exercises

    汇总一些常见的算法题目,参考代码. 注:部分题目没有合适的oj地址 枚举 Perfect Cubes.Biorhythms.Counterfeit Dollar.EXTENDED LIGHTS OUT ...