JVM学习-Class文件结构①

字节码文件的跨平台性
Java语言:跨平台的语言(Write Once,Run Anywhere)
  • 当Java源代码编译成字节码后,如果想在不同平台上运行,则无须再次编译
  • 这上优势不再那么吸引人,Python,PHP,Ruby,Lisp等有强大的解释器
  • 跨平台似乎已经成为一门语言必选的特性
Java虚拟机:跨语言的平台
  • Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class文件”这种特定的二进制格式文件关联,无论使用何种语言进行软件开发,只要能将源文件编译成正确的Class文件,那么这种语言就可以在Java虚拟机上执行,统一而强大的Class文件结构,是Java虚拟机的基石和桥梁。请添加图片描述
  • 所有的JVM全部遵守Java虚拟机规范,字节码文件可以在各种JVM上执行
前端编译器
  • 负责将符合Java语法规范的Java代码编译成符合JVM规范的字节码
  • javac是最常用的前端编译器
  • javac编译器将Java源码编译为一个有效的字节码文件过程经历4步,分别是词法分析、语法分析、语义解析以及生成字节码
    请添加图片描述
Oracle JDK软件包括两部分内容
  • 一部分将Java源代码编译成Java虚拟机的指令集的编译器
  • 另一部分是用于实现Java虚拟机的运行时环境
public class IntegerTest {public static void main(String[] args) {Integer x = 5;int y = 5;System.out.println(x == y);Integer i1 = 5;Integer i2 = 5;System.out.println(i1 == i2);Integer i3 = 128;Integer i4 = 128;System.out.println(i3 == i4);}
}
//执行结果
true
true
false
//查看字节码0 iconst_51 invokestatic #2 <java/lang/Integer.valueOf>   //给Integer x进行赋值4 astore_15 iconst_56 istore_27 getstatic #3 <java/lang/System.out>
10 aload_1
11 invokevirtual #4 <java/lang/Integer.intValue>  //对Integer x进行拆箱操作
14 iload_2
15 if_icmpne 22 (+7)
18 iconst_1
19 goto 23 (+4)
22 iconst_0
23 invokevirtual #5 <java/io/PrintStream.println>
26 iconst_5
27 invokestatic #2 <java/lang/Integer.valueOf>
30 astore_3
31 iconst_5
32 invokestatic #2 <java/lang/Integer.valueOf>
35 astore 4
37 getstatic #3 <java/lang/System.out>
40 aload_3
41 aload 4
43 if_acmpne 50 (+7)
46 iconst_1
47 goto 51 (+4)
50 iconst_0
51 invokevirtual #5 <java/io/PrintStream.println>
54 sipush 128
57 invokestatic #2 <java/lang/Integer.valueOf>
60 astore 5
62 sipush 128
65 invokestatic #2 <java/lang/Integer.valueOf>
68 astore 6
70 getstatic #3 <java/lang/System.out>
73 aload 5
75 aload 6
77 if_acmpne 84 (+7)
80 iconst_1
81 goto 85 (+4)
84 iconst_0
85 invokevirtual #5 <java/io/PrintStream.println>
88 return/*** 成员变量赋值过程:①默认初始化②显式初始化③构造器初始化④有了对象后,可以通过对象.属性的方式对成员变量赋值*/
class Father {int x = 10;public Father() {this.print();x = 20;}public void print() {System.out.println("Father.x = " + x);}
}
class Son extends Father {int x = 30;public Son() {this.print();x = 40;}public void print() {System.out.println("Son.x = " + x);}
}
public class SonTest {public static void main(String[] args) {Father f = new Son();System.out.println(f.x);}
}
//执行结果
Son.x = 0
Son.x = 30
20
Class文件
  • 字节码文件里是什么?
  • 源代码经过编译器编译生成一个字节码文件,字节码是一种二进制的类文件,它的内容是JVM指令,不像C,C++经由编译器直接生成机器码
  • 什么是字节码指令(byte code)
  • Java虚拟机的指令由一个字节长度,代表某种特定操作含义的操作码以及跟随其后的零至多个代表此操作所需参数的操作数所构成,虚拟机中指令并不包含操作数,只有一个操作码
    在这里插入图片描述
  • 如何解读供虚拟机解释执行的二进制字节码
  • ①通过NotePad++中安装一个HEX-Editor插件,或使用BinaryViewer
    在这里插入图片描述
  • ②使用javap指令:jdk自带反解析工具
C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -v -p IntegerTest.class
  • ③使用IDEA插件:jclasslib或jclasslib bytecode viewer客户端
Class文件结构
//class文件结构相应信息都使用下面代码编译为字节码进行
public class Demo {private int num = 1;public int add() {num += 2;return num;}
}
  • class类的本质
    任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,Class文件实际上它并不一定以磁盘文件的形式存在,Class文件是一组以字节为基础单位的二进制流
  • class文件格式
  • Class的结构不像XML等描述语言,由于没有分隔符,所以其中的数据项,无论是字节顺序还是数量,都被严格限定,哪个字节代表什么含义,长度多少,先后顺序如何,都不允许改变
  • Class文件格式采用一种类似于C语言结构体的方式进行数据存储,包含两种数据类型:无符号数和表
  • 无符号数属于基本的数据类型,以u1,u2,u4,u8来分别代表1字节,2字节,4字节和8字节无符号数,无符号数可以用来描述数字、索引引用、数量值或者按UTF8编码构成的字符串值
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以_info结尾,表用于描述有层次关系的复合结构数据,整个Class文件本质上就是一张表,由于表没有固定长度,所以通常会在其前面 加上个数说明
  • class文件结构描述
  • Class文件的结构并不是一成不变的,随着Java虚拟机的不断发展,总是不可避免地会对Class文件结构做出一些调整,但是其基本结构和框架是非常稳定的
  • 魔数
  • Class文件版本
  • 常量池
  • 访问标志
  • 类索引、父类索引、接口索引集合
  • 字段表集合
  • 方法表集合
  • 属性表集合
    在这里插入图片描述
魔数(Magic Number)
  • 每个Class文件开头的4个字节的无符号整数称为魔数
  • 它的唯一作用是确定文件是否为一个能被虚拟机接受的有效合法的Class文件,即魔数是Class文件的标识符
  • 魔数值固定为0xCAFEBABE,不会改变
  • 如果一个Class文件不以oxCAFEBABE开头,虚拟机在进行文件校验的时候就会直接抛出以下错误:
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1885430635 in class file Demoat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(Unknown Source)at java.security.SecureClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.access$100(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
  • 使用魔数而不是扩展名来进行识别主要是基于安全方面的考虑,因为文件扩展名可以随意地更改
Class文件版本号
  • 紧接着魔数的4个字节存储的是Class文件的版本号,同样4个字节,第5、6字节所代表的含义就是编译的副版本号minor_version,第7、8字节就是编译的主版本号major_version
  • 它们共同构成了class文件的格式版本号,譬如某个Class文件的主版本号为M,副版本号为m,那么这个Class文件的格式版本号就确定为M.m
  • 版本号和Java编译器的对应关系统如下
    在这里插入图片描述
  • Java版本号从45开始,JDK1.1之后的每个JDK大版本发布主版本号向上加1
  • 不同版本的Java编译器的Class文件对应的版本是不一样的,目前,高版本的Java虚拟机可以执行由低版本编译器生成的Class文件,但是低版本的Java虚拟机不能执行高版本编译器生成的Class文件,否则JVM会抛出java.lang.UnsupportedClassVersionError异常
  • 在实际应用中,由于开发环境和生产环境的不同,可能导致该问题的发生,因此,需要在开发时,注意开发编译JDK版本和生产环境是否一致
  • 虚拟机JDK版本为1.k(k >= 2)时,对应的class文件格式版本号的范围为45 - (44 + k.0)
常量池
  • 常量池是Class文件中最为丰富的区域之一,常量池对于Class文件中的字段和方法解析也有着至关重要的作用

  • 随着Java虚拟机的不断发展,常量内容日渐丰富,常量池是整个Class文件的基石
    在这里插入图片描述

  • 在版本号之后,是常量池的数量,以及若干个常量池表项

  • 常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的无符号数,代表常量池容量计数值(constant_pool_count),与Java中语言习惯不一样的是,这个容量计数是从1而不是0开始的
    在这里插入图片描述

  • 由上表可见,Class文件使用了一个前置的容量计数器(constant_pool_count)加若十个连续的数据项(constant_pool)的形式来描述常量池内容,我们把一系列连续常量池数据称为常量池集合

  • 常量池表项中,用于存放编译时期生成的各种字面量和符号引用,这部分加载后进入方法区的运行时常量池中存放

常量池计数器
  • 由于常量池的数量不固定,时长时短,需要两个字节表示常量池容量计数值
  • 常量池容量计数值:从1开始,表示常量池中有多少项常量,即constant_pool_count = 1表示常量池中有0个常量项
    在这里插入图片描述

其值0x0016,掐指一算,是22
注:实际上只有21项常量,索引范围1-21,常量池是从1开始的

常量池
  • constant_poo是一种表结构,以1-constant_pool_count - 1索引,表明后面有多少个常量项
  • 常量池主要存放两大类常量:字面量(Literal)和符号引用(Symbolic Reference)
  • 它包含了class文件结构及子结构中引用的所有字符串常量、类或接口名、字段名和其他常量,常量池中的每一项具备相同的特征,第1个字节作为类型标记,用于确定该项的格式,这个字节称为tag byte(标记字节、标签字节)
    在这里插入图片描述
字面量和符号引用

在这里插入图片描述

  • 全限定名
  • com/chapter09/Demo这个是类的全限定名,仅把包名的".“替换为”/“,为了使连续的多个全限定名之间不产生混淆,在使用时最后一般会加入一个”;"表示全限定名结束
  • 简单名称
  • 简单名称是没有类型和类修饰的方法或者字段名称,上面例子中的类的add()方法和num字段的简单名称分别为add和num
  • 描述符
  • 描述符的作用用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值,根据描述符规则,基本数据类型(byte,char,double,float,int,long,short,boolean)以及代表无返回值的void类型都用一个大写字符来表示,而对象类型用字符L加对象的全限定名来表示
    在这里插入图片描述
    注:虚拟机在加载Class文件时才会进行动态链接,Class文件中不会保存各个方法和字段的最终内存布局信息,因此,这些字段和方法的符号引用不经过转换是无法直接被虚拟机使用的,当虚拟机运行时,需要从常量池中获得对应的符号引用,再在类加载过程中的解析阶段将其替换为直接引用,并翻译到具体的内存地址中
  • 符号引用:以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用与虚拟机实现内存布局无关,引用的目标并不一定已经加载到了内存中
  • 直接引用:可以直接指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同,如果有了直接引用,那说明引用的目标必定已经在于内存之中了。

在这里插入图片描述
注:常量池:可以理解为Class文件之中的资源仓库,它是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项之一
常量池中为何要包含这么多内容
Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态链接,在Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换无法得到真正的内存地址,也就无法直接被虚拟机使用,当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。

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

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

相关文章

《最新出炉》系列入门篇-Python+Playwright自动化测试-41-录制视频

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 上一篇讲解和分享了录制自动生成脚本&#xff0c;索性连带录制视频也一股脑的在这里就讲解和分享了。今天我们将学习如何使用Playwright和Python来录制浏览器操作的视频&#…

Overleaf中出现文字越界、越下届、没有正确分页、换页的原因和解决方法

在使用overleaf中&#xff0c;我偶尔会遇到如标题所说的情况&#xff0c;也如图所示&#xff1a; 后来发现&#xff0c;是因为这一页前面是一个表格&#xff0c;所以怀疑是表格的格式导致的。所以让chatgpt帮我更换了表格的格式&#xff0c;成功解决问题。 对于问题可能的成因…

Exel 求某行数最大值

方法1 MAX&#xff08; 选中比较数回车

从感知机到神经网络

感知机 一、感知机是什么二、用感知机搭建简单逻辑电路2.1 与门2.2 与非门2.3 或门 三、感知机的局限性3.1 异或门3.2 线性和非线性 四、多层感知机4.1 已有门电路的组合4.2 Python异或门的实现 五、感知机模型5.1 感知机模型5.2 感知机损失函数5.3 感知机学习算法 六、感知机原…

使用Pyecharts构建Map对象无法显示颜色--解决

我们在做数据可视化的过程中&#xff0c;可能需要使用到地图作为数据可视化的工具&#xff1b; 包括世界地图、国家地图、省市区地图等&#xff1b; 如果在你设置好颜色数据匹配后&#xff0c;可视化地图未显示对应数据的颜色&#xff0c;那么请检查是否出现以下情况&#xf…

安全分析[1]之网络协议脆弱性分析

文章目录 威胁网络安全的主要因素计算机网络概述网络体系结构 网络体系结构脆弱性分组交换认证与可追踪性尽力而为匿名与隐私对全球网络基础实施的依赖无尺度网络互联网的级联特性中间盒子 典型网络协议脆弱性IP协议安全性分析IPSec&#xff08;IP Security)IPv6问题 ICMP协议安…

HTML与CSS的学习

什么是HTML,CSS&#xff1f; HTML(HyperText Markup Language):超文本标记语言。 超文本:超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息&#xff0c;还可以定义图片、音频、视频等 标记语言:由标签构成的语言 >HTML标签都是预定义好的。例如:使用<a>…

c语言:模拟strlen(三种方法)最全版本

1.计数的方法 #include <stdio.h> #include <assert.h> int my_strlen(const char * str)//const的使用优化 {int count0;assert(str)while(*str){count;str;}return count; } 2.用指针的方法&#xff08;指针-指针&#xff09; #include <stdio.h> #incl…

Visual Studio 的调试(一)

最近事儿很多昂&#xff0c;更新速度相较以往慢了许多&#xff0c;备考六月份的四级&#xff0c;还有学校的期末等等&#xff0c;事儿真的太多啦&#xff0c;所以后面的更新速度也会放慢一点&#xff0c;实在是抽不开身啊诸位&#xff0c;相当抱歉&#xff0c;还望诸君见谅 言…

MySQL大表删除方案

1.问题 在生产环境中&#xff0c;执行大表删除操作时&#xff0c;很容易因为占用了大量io资源导致其他事务被阻塞&#xff0c;最终事务不断堆积导致MySQL挂掉。 2.drop命令 drop命令&#xff0c;MySQL主要干了两件事&#xff1a; 清除buffer pool缓冲&#xff08;内存&…

STL源码刨析:序列式容器之vector

目录 1.序列式容器和关联式容器 2.vector的定义和结构 3.vector的构造函数和析构函数的实现 4.vector的数据结构以及实现源码 5.vector的元素操作 前言 本系列将重点对STL中的容器进行讲解&#xff0c;而在容器的分类中&#xff0c;我们将容器分为序列式容器和关联式容器。本章…

Docker Hub注册及上传自定义镜像

说明&#xff1a;本文介绍如何注册Docker Hub&#xff0c;及将自己自定义镜像上传到Docker Hub上&#xff1b; 注册Docker Hub 浏览器输入&#xff1a;http://hub.docker.com/&#xff0c;进入Docker Hub官网 注&#xff1a;如果无法访问&#xff0c;可在GitHub上下载一个Ste…

Git--本地仓库

文章目录 工作区和暂存区工作区&#xff08;Working Directory&#xff09;版本库&#xff08;Repository&#xff09; 初始化git仓库添加文件到版本库步骤 查看修改内容查看工作区和暂存区状态已add文件已修改/新增 的未add文件git跟踪修改原理 查看提交历史版本回退撤销修改撤…

信息学奥赛初赛天天练-12-数论-整除问题

更多资源请关注纽扣编程微信公众号 整除的性质 1 整除性 若 &#x1d44e; 和 &#x1d44f; 都为整数&#xff0c; &#x1d44e; 整除 &#x1d44f; 是指 &#x1d44f; 是 &#x1d44e; 的倍数&#xff0c;&#x1d44e; 是 &#x1d44f; 的约数&#xff08;或者叫 因…

基于Arduino IDE的ESP32开发环境搭建

文章目录 一. Arduino IDE安装二. Arduino IDE安装ESP开发包 一. Arduino IDE安装 Arduino官网下载IDE软件 解压下载好的安装包&#xff0c;以管理员身份运行Arduino IDE软件 IDE第一次启动会安装各种驱动&#xff0c;直接点击确定就行 二. Arduino IDE安装ESP开发包 将…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-22讲 RTC 时钟设置

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

头歌结构化分析方法-数据流图

第1关&#xff1a;数据流图-画出外部实体 第2关&#xff1a;数据流图-画出加工 第3关&#xff1a;数据流图-画出数据存储 第4关&#xff1a;数据流图-画出数据流 第5关&#xff1a;数据流图-机票预定系统

VXLAN小结

1.VXLAN:(组件虚拟网络的架构核心)虚拟扩展本地局域网&#xff0c;通过隧道的形式&#xff0c;将物理上有隔离的资源&#xff0c;在逻辑上连通起来&#xff0c;使其二层互通。 a.物理网络:指的是构成 VXLAN 连接的基础 IP 网络 b.逻辑网络:指的是通过 VXLAN 构建的虚拟网络 C.N…

DragonKnight CTF2024部分wp

DragonKnight CTF2024部分wp 最终成果 又是被带飞的一天&#xff0c;偷偷拷打一下队里的pwn手&#xff0c;只出了一题 这里是我们队的wp web web就出了两个ez题&#xff0c;确实很easy&#xff0c;只是需要一点脑洞(感觉)&#xff0c; ezsgin dirsearch扫一下就发现有ind…

ROS参数服务器

一、介绍 参数服务器是用于存储和检索参数的分布式多机器人配置系统&#xff0c;它允许节点动态地获取参数值。 在ROS中&#xff0c;参数服务器是一种用于存储和检索参数的分布式多机器人配置系统。它允许节点动态地获取参数值&#xff0c;并提供了一种方便的方式来管理和共享配…