【从零开始学习JVM | 第二篇】字节码文件的组成

前言:

        字节码作为JAVA跨平台的主要原因,熟练的掌握JAVA字节码文件的组成可以帮助我们解决项目的各种问题,并且在面试中,关于字节码部分的内容却是一大考点和难点,因此我们在这里穿插讲解一下字节码文件的组成。

目录

前言:

1.如何打开字节码文件? 

2.字节码文件的组成:

3.简单阅读字节码

总结:


 

1.如何打开字节码文件? 

字节码文件中保存了原代码编译后的内容,以二进制的形式进行存储。因此我们是无法用记事本这种普通的阅读软件打开的。

因此我们要使用专业的字节码阅读工具进行。好在IDEA中就有对应的插件,我们只需要点击下载就可以。

jclasslib Bytecode Viewer

 然后通过这个插件,我们就可以便捷的查看一个字节码文件:

我们来逐一解释一下这些部分:

1.基础信息:魔数,字节码文件对应的JAVA版本号,访问标识符 ,父类和接口。

2.常量信息:保存了字符串常量,类或接口名,字段名。主要在字节码指令中使用。

3.字段:当前类或接口声明的字段信息。

4.方法:当前类或接口声明的方法信息字节码指令。

5.属性 :类的属性,比如源码的文件名,内部类的列表等。 

通过这款插件,我们就可以看到上图的字节码:

2.字节码文件的组成:

ava字节码文件(通常以.class扩展名结尾)是Java源代码编译后的产物。它包含了Java程序在JVM上执行所需的指令和信息。字节码文件的组成结构非常标准化,按照特定的格式排列,主要由以下部分组成:

  1. 魔数(Magic Number)

    • 每个字节码文件的前4个字节都是固定的魔数0xCAFEBABE,用于标识这是一个Java字节码文件。
  2. 版本信息

    • 紧接着魔数的是版本信息,包括次版本号(Minor Version)和主版本号(Major Version),用于表示编译该字节码的Java编译器版本。
  3. 常量池(Constant Pool)

    • 常量池紧随版本信息之后,是.class文件中资源的集合,包括各种文字字符串、类或接口名、字段名和其他常量。
    • 它是一个表结构,存储了类中所有的符号引用,这些引用将在类加载阶段被解析。
  4. 访问标志(Access Flags)

    • 用于描述类或接口的访问权限(如public、private、protected)和属性(如abstract、final、interface等)。
  5. 此类索引、父类索引和接口索引集合

    • 这些索引值指向常量池中的项,分别代表当前类、超类和实现的接口的符号引用。
  6. 字段表(Fields Table)

    • 包含类或接口中声明的所有字段,每个字段都有其对应的属性集合,如名称、类型、访问标志等。
  7. 方法表(Methods Table

    • 列出了类中的所有方法,包括方法的名称、返回类型、参数类型、访问标志以及方法的字节码指令。
  8. 属性表(Attributes Table)

    • 属性表为字段表、方法表提供附加信息,如异常表、行号表、局部变量表等。每个属性都有自己的结构定义,例如,Code属性就包含了Java方法的JVM指令、操作数栈、局部变量表等信息。
  9. 接口表(Interfaces Table)

    • 列出该类实现的所有接口。

字节码文件的这些组成部分共同定义了Java类的结构和行为。当JVM加载一个类时,它会解析字节码文件并根据其中的信息创建出相应的Class对象,然后再在JVM上执行该类的代码。字节码文件的结构设计使得Java程序具有很强的跨平台性,可以在任何安装了兼容JVM的设备上运行。

很多同学都不理解这个魔数,因此我们换种说法解释一下:由于我们可以随意的更改一个文件的后缀,例如把jpg更改为png。因此电脑是无法通过文件扩展名来确定文件类型的。因此如电脑需要通过文件的头几个字节(文件头)去校验文件的类型。而在JAVA字节码文件中,将文件头叫做魔数 

3.简单阅读字节码

 了解了字节码文件的组成部分之后,我们来看看一段字节码以及解释:

 0 iconst_0          // 将int类型常量0压入操作数栈顶1 istore_1          // 将操作数栈顶的int类型数值(0)存入第二个局部变量槽中(局部变量索引1)2 iload_1           // 从局部变量表中加载索引为1的int类型值到操作数栈顶3 iinc 1 by 1       // 将局部变量表中索引为1的int类型变量增加16 istore_1          // 将操作数栈顶的int类型数值(经过iinc后的值)存入第二个局部变量槽中(局部变量索引1)7 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;> // 获取类java.lang.System的静态字段out的值,即PrintStream对象,并压入操作数栈顶
10 iload_1           // 从局部变量表中加载索引为1的int类型值到操作数栈顶
11 invokevirtual #3 <java/io/PrintStream.println : (I)V> // 调用PrintStream对象的println方法打印int值
14 return            // 从当前方法返回

 这段字节码对应的代码就是:

看不懂的同学们对着我的字节码注释自己尝试一步一步走一下就理解了。其实我们通过字节码就可以清晰的知道为什么代码运行结果等于0。

我们再来看一眼这个代码的:

他的字节码指令为:

 0 iconst_01 istore_12 iinc 1 by 15 iload_16 istore_17 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
10 iload_1
11 invokevirtual #3 <java/io/PrintStream.println : (I)V>
14 return

由此我们可以看出:之所以i++和++i不一样,从字节码角度上来看,是因为iinc和iload的执行顺序不一样,导致一个在打印的时候加载的是旧值,一个是新值。

总结来讲:int i=0; i = i ++之所以结果等于0,是因为在字节码中,i ++ 先把 0 取出来放入到临时的操作数栈中,接下来对 i 进行加 1 操作,i 变为了1,最后再把操作数栈中之前保存的i值拿出来放入i中,使得i变为了0。

而int i=0; i = ++ i 之所以结果等于 1 ,是因为在字节码中,++i 先进行自增,使得i变为 1 ,然后再将 1 取出来放入到临时的操作数栈中,再把操作数栈中的1拿出来赋值为i,使得i变为了 1 .

总结:

当我们编写和阅读Java代码时,我们通常关注的是高级语言层面的代码。然而,在Java编译器将高级代码转换为可执行的机器码之前,它会将我们的代码转换为一种称为字节码的中间表示形式。

字节码是一种与特定平台无关的指令集,它使用单字节的操作码和操作数来描述操作。它是Java虚拟机(JVM)的基本指令集,JVM可以解释执行字节码或将其编译为机器码。

通过深入理解字节码的组成,我们可以更好地理解Java代码的底层运行原理,进一步优化性能和调试问题。

如果我的内容对你有帮助,请点赞,评论,收藏创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

16、观察者模式(Observer Pattern)

观察者&#xff08;Observer Pattern&#xff09; 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。主要解决一个对象状态改变给其他对象通知的问题&#xff0c;而且要考虑到易用和低耦合&…

你好!哈希表【JAVA】

1.初识&#x1f3b6;&#x1f3b6;&#x1f3b6; 它基本上是由一个数组和一个哈希函数组成的。哈希函数将每个键映射到数组的特定索引位置&#xff0c;这个位置被称为哈希码。当我们需要查找一个键时&#xff0c;哈希函数会计算其哈希码并立即返回结果&#xff0c;因此我们可以…

【OpenGauss源码学习 —— (RowToVec)算子】

VecToRow 算子 概述ExecInitRowToVec 函数ExecRowToVec 函数VectorizeOneTuple 函数 ExecEndRowToVec 函数总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在…

github首次将文件合到远端分支,发现名字不是master,而是main

暂存区和本地仓库的信息都存储在.git目录中其中 其中&#xff0c;暂存区和本地仓库的信息都存储在.git目录中 在自己的github上实践 1、刚开始&#xff0c;git clone gitgithub.com:lingze8678/my_github.git到本地 2、在克隆后的代码中加入一个pdf文件 3、在git bash中操作…

CentOS增加虚拟内存 (Linux增加内存)

前言 因为囊中羞涩不敢言&#xff0c;所以内存只有2G&#xff0c;项目在运行的时候&#xff0c;占用的内存已经报表&#xff0c;所以有的时候就会出现宕机的情况发生&#xff0c;后面发现可以通过使用增加虚拟内存空间&#xff0c;来增加内存容量。 下面进入正题&#xff0c;讲…

Selenium+Python自动化测试之验证码处理

两种方式&#xff1a; 验证码识别技术 (很难达到100%) 添加Cookie &#xff08;*****五星推荐&#xff09; 方式一&#xff1a;验证码识别技术 逻辑方式&#xff1a; 1&#xff1a;打开验证码所在页面&#xff0c;截图。获取验证码元素坐标&#xff0c;剪切出验证码图片&…

【MATLAB】辛几何模态分解分解+FFT+HHT组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 辛几何模态分解&#xff08;CEEMDAN&#xff09;是一种处理非线性和非平稳信号的适应性信号分解方法。通过在信号中加入白噪声&#xff0c;并多次进行经验模态分解&#xff08;EMD&#…

深度学习TensorFlow2基础知识学习前半部分

目录 测试TensorFlow是否支持GPU&#xff1a; 自动求导&#xff1a; 数据预处理 之 统一数组维度 定义变量和常量 训练模型的时候设备变量的设置 生成随机数据 交叉熵损失CE和均方误差函数MSE 全连接Dense层 维度变换reshape 增加或减小维度 数组合并 广播机制&#…

clickhouse的向量化执行

背景 clickhouse快的很大一部分原因来源于数据的向量化执行&#xff0c;本文就来看一下向量化执行和正常标量执行的区别 SIMD的向量化执行 从上图可知&#xff0c;clickhouse通过SIMD指令可以做到一个cpu周期操作两个向量的运算操作&#xff0c;比起普通的cpu指令效率提高了N…

Understanding Computer Hardware

文章目录 I. Input Devices1. Keyboard&#xff08;1&#xff09;Layout&#xff08;2&#xff09;Key Types&#xff08;3&#xff09;Functionality&#xff08;4&#xff09;Connectivity&#xff08;5&#xff09;Ergonomics&#xff08;6&#xff09;Multimedia Keys&…

【计算机组成体系结构】主存储器的基本组成

一、半导体元器件存储二进制0/1的原理 一个存储器逻辑上分为MAR&#xff0c;MDR和存储体&#xff0c;这三块在时序逻辑电路的控制下相互配合工作。 而存储体有多个存储单元构成&#xff0c;每个存储单元又由每个存储元构成。一个存储元可以存放一位的二进制的0/1。 一个存储元…

OWASP安全练习靶场juice shop-更新中

Juice Shop是用Node.js&#xff0c;Express和Angular编写的。这是第一个 完全用 JavaScript 编写的应用程序&#xff0c;列在 OWASP VWA 目录中。 该应用程序包含大量不同的黑客挑战 用户应该利用底层的困难 漏洞。黑客攻击进度在记分板上跟踪。 找到这个记分牌实际上是&#…

想考研到电子类,未来从事芯片设计,目前该怎么准备?

最近看不少天坑学子想考研微电子专业&#xff0c;但却不知道该怎么准备&#xff1f;接下来就带大家一起来具体了解一下~ 首先是目标院校的选择&#xff1f; 目前所设的微电子专业学校里&#xff0c;比较厉害的有北京大学、清华大学、中国科学院大学、复旦大学、上海交通大学、…

ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译

ROS2的功能包、依赖管理、工作空间配置与编译 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyrigh…

品牌是如何通过软文推广产品的?媒介盒子为您揭秘

需求是概念的、抽象的&#xff0c;产品是具象的&#xff0c;多维的。软文推广就是通过发现消费者的需求来促使消费者主动购买产品&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;品牌是如何通过软文推广产品的。 一、 差异化内容打出独特点 差异化内容指通过和竞品的分析…

基于Intel Ai Analytics Toolkit 及边缘计算的溶氧预测水产养殖监测方案

基于AI的淡水养殖水质溯源、优化系统方案 前言一、关键需求及方案概述二、方案设计预测机制LSTM 模型基于intel AI 的时序水质分析模型与分类模型优化 三、实战分析1、方案简述2、数据分析预处理特征类型处理特征分布分析 3、特征构造4、特征选择过滤法重要性排序 5.构建LSTM模…

算法--最短路

这里写目录标题 xmind单源最短路简介所有边权都是正朴素的Dijkstra算法思想例子题解 堆优化版的Dijkstra算法 存在负数权Bellman-Ford算法思想例子题解 多源汇最短路简介 xmind 上述中&#xff0c;朴素Dijkstra算法适用于稠密图 其他用堆优化版 而SPFA算法一般都比Bellman-For…

设计模式:装饰者模式

目录 一、定义 二、场景 三、例子 四、优缺点 优点&#xff1a; 缺点&#xff1a; 一、定义 在不改变已有对象结构的情况下&#xff0c;动态添加新的功能到对象上&#xff0c;是继承的一种替代方案。属于结构型模式。 二、场景 1.扩展一个类的功能&#xff0c;添加附加职责…

七、ZooKeeper选举机制

目录 1、概念 2、全新集群选举 3、非全新集群选举 zookeeper默认的算法是FastLeaderElection,采用投票数大于半数则胜出

资料分析(花生)

基期A&#xff08;给出BR或BX&#xff09; 前期&#xff1a;代入、直除、假设分配隔年前期&#xff1a;求出间隔增长率&#xff0c;再变成第一类考法前期差值&#xff1a;假设分配法求得两个前期作差。 现期B 有增量求现期&#xff1a;求出 X&#xff0c;列不等式即可有增速求现…