JVM基础:字节码文件详解①

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、Java虚拟机的组成
  • 二、字节码文件的组成
    • 2.1 为什么要了解字节码文件?
    • 2.2 如何“窥探”字节码文件的奥秘?
      • 2.2.1 使用工具打开字节码文件
      • 2.2.2 字节码文件是由哪几部分组成?
      • 2.2.3 基础信息(一般信息)
      • 2.2.4 常量池
      • 2.2.5 方法
  • 参考目录


提示:以下是本篇文章正文内容,下面案例可供参考

一、Java虚拟机的组成

👉它可以分为以下四个部分

  1. 类加载器(ClassLoder)加载class字节码文件中的内容到内存中(加载到内存是为了高效的利用)
  2. 运行时数据区域(JVM管理的内存)负责管理JVM使用到的内存,比如创建对象和销毁对象
  3. 执行引擎((即时编译器、解释器与垃圾回收器等)将字节码文件中的指令解
    释成机器码,同时使用即时编译器优化性能
  4. 本地接口调用本地已经编译的方法,比如虚拟机中提供的c/c++的方法,就是本地方法(即jvm底层已经实现好的,用C/C++语言编写好的方法,使用native修饰的方法)在这里插入图片描述

👉基本执行流程如下所示:

在这里插入图片描述


二、字节码文件的组成

2.1 为什么要了解字节码文件?

👉原因

①它可以解决一些面试难题

例如以下面试题

  • int i = 0; i = i++; 最终i的值是多少?
  • 请你回答一下Java的反射是如何实现的?

②它可以解决工作中的一些实际问题——版本冲突

例如以下报错

在这里插入图片描述

2.2 如何“窥探”字节码文件的奥秘?

2.2.1 使用工具打开字节码文件

👉常用工具

①使用Jclasslib字节码插件【idea插件】

在这里插入图片描述

如何使用该插件查看指定字节码文件?

👉步骤

①在idea中 file – settings – plugins 中搜索 jclass 安装该插件

在这里插入图片描述
②选中指定的Java源文件,按照以下步骤操作,即可
在这里插入图片描述
在这里插入图片描述

👉注意

使用jclasslib的idea插件版的两个小细节

  1. 要打开一个新的字节码文件,就需要选中当前的源代码,然后点击 view - show bytecode with jclasslib 就可以打开新的字节码文件

    在这里插入图片描述

    1. 如果源代码发生变化,需要重新运行编译,可通过 build - Recompile ‘xxx.java’ 或 重新运行该源代码的方式重新编译,然后在jclasslib中重新刷新即可
      在这里插入图片描述

②使用Javap命令

如何使用该命令查看指定字节码文件?

👉步骤

  1. 首先确保已经安装了JDK(Java Development Kit),因为Javap是JDK的一部分。

  2. 打开命令提示符(Windows)或终端(macOS/Linux)。

  3. 使用cd命令导航到包含字节码文件(.class文件)的目录。例如,如果字节码文件位于C:\Users\YourUsername\Documents\MyProject目录下,请输入cd C:\Users\YourUsername\Documents\MyProject

  4. 输入javap -c YourClassName.class命令,其中YourClassName是你要查看的字节码文件的名称(不包括扩展名)。例如,如果你要查看名为MyClass.class的文件,请输入javap -c MyClass.class

  5. 按回车键执行命令。命令将显示字节码文件的详细信息,包括类名、方法名、参数类型等。

案例:使用Javap命令打开桌面测试文件夹中的字节码文件t1.class

在这里插入图片描述

👉备注

如果jar包需要先使用 jar –xvf 命令解压

③使用Arthas工具打开字节码文件

GitHub地址

在这里插入图片描述

2.2.2 字节码文件是由哪几部分组成?

使用jclass插件打开任意一个Java 源文件,我们可以看到如下信息

在这里插入图片描述

  • 一般信息(基本信息)魔数、字节码文件对应的Java版本号,访问标识(public final等等)以及父类和接口

    在这里插入图片描述

  • 常量池保存了字符串常量、类或接口名、字段名,主要在字节码指令中使用

    在这里插入图片描述

  • 接口当前类实现的接口信息

    在这里插入图片描述

  • 字段当前类或接口声明的字段信息

    在这里插入图片描述

  • 方法当前类或接口声明的方法信息——字节码指令

    在这里插入图片描述

  • 属性类的属性,比如源码的文件名,内部类的列表等

    在这里插入图片描述

2.2.3 基础信息(一般信息)

在这里插入图片描述

前面提到的基本信息中主要包含魔数、字节码文件对应的Java版本号,访问标识(public final等等)以及父类和接口等内容,但是有两个问题值得深思

在这里插入图片描述

😥问题①:何为魔数?

使用notepad++ 随便打开两个字节码文件,我们可以看到他们之间显著的共通之处

a.打开t1.class字节码文件,如下图所示

在这里插入图片描述

b.打开MyApplication.class字节码,如下图所示

在这里插入图片描述

共通之处

以ca fe ba be打头

这就是魔数(Magic),用以校验文件类型的文件头,如果别的编译软件不支持该种类型的文件头,则解析文件时会出错。那为什么不使用文件扩展名去校验类型?文件是无法通过文件扩展名来确定文件类型的,文件扩展名可以随意修改,不影响文件的内容。故而在Java字节码文件中,将文件头称为魔数

在这里插入图片描述

😥问题②:何为Java版本号?

Java版本号主要分为主副版本号,主副版本号指的是编译字节码文件的JDK版本号,主版本号用来标识大版本号,JDK1.0-1.1使用了45.0-45.3,JDK1.2是46之后每升级一个大版本就加1;副版本号是当主版本号相同时作为区分不同版本的标识,一般只需要关心主版本号。

在这里插入图片描述

👉版本号作用

主要判断当前字节码的版本和运行时的JDK是否兼容

👉备注

1.2之后大版本号计算方法就是:主版本号 – 44 ;
比如主版本号52,那就是JDK8

之前在前文中抛出了一个版本冲突的问题

如下图所示

在这里插入图片描述

👉原因

主版本号不兼容,发生冲突

👉解决方案

1.升级JDK版本(容易引发其他的兼容性问题,并且需要大量的测试)
2.将第三方依赖的版本号降低或者更换依赖,以满足JDK版本的要求 √ 建议采用

👉总结

在这里插入图片描述

2.2.4 常量池

👉作用

避免相同的内容重复定义,节省空间

👉概述

  • 常量池中的数据都有一个编号,编号从1开始。在字段或者字节码指令中通过编号可以快速的找到对应的数据
  • 字节码指令中通过编号引用到常量池的过程称之为符号引用

👉符号引用的示意图如下所示

在这里插入图片描述

2.2.5 方法

👉先看一个简单经典的面试题

int i = 0; i = i++; 最终i的值是多少?

👉我的回答

i =i++ 是先赋值后自增,而i= ++ i 是先自增后赋值,所以最终的i是0

😚进一步发问

为什么i =i++ 是先赋值后自增,而i= ++ i 是先自增后赋值,如果根据Java的运算符优先级对比,应该是1吧,i++优先级高,先执行之后将返回结果1赋值给 i,所以最终 i应该是1。

可正确的答案是 i最终的值是0

😥why?

莫急,且听我慢慢道来

👉定义

字节码中的方法区域是存放字节码指令的核心位置,字节码指令的内容存放在方法的Code属性中

在这里插入图片描述

选中Code属性,我们可以看到它下面还有两个Table

在这里插入图片描述

  • LineNumberTable用于存储源代码中各行号与字节码指令之间的对应关系,它可以帮助调试器在执行程序时定位到源代码中的具体位置。

    在这里插入图片描述

  • LocalVariableTable主要用于存储方法的参数和方法内定义的局部变量。在程序编译为Class文件时,会在Code属性的max_locals数据项中确定该方法所需要分配的局部变量表的最大容量。

    在这里插入图片描述

我们暂时只关心LocalVariableTable,如下图所示,LocalVariableTable表中的每个项都包含以下内容:

  • 名称(Name)表示该项对应的局部变量的名称
  • 描述符(Descriptor)表示该项对应的局部变量的类型和修饰符
  • 索引(Slot)表示该项在局部变量表中的位置
  • 值(Value)表示该项对应的局部变量的值

在这里插入图片描述

除了上面的LocalVariableTable,我们还得了解一个概念——操作数栈

😥什么是操作数栈?

👉讯飞星火告诉我们

在这里插入图片描述

简单来讲,操作数栈是临时存放数据的地方

👉再看之前的源代码

 int i=0;int j= i+1;

字节码指令分析如下

在这里插入图片描述
回到前面提到的面试题

😥为什么int i = 0; i = i++; 最终i的值是0?

源代码示例如下

public static void main(String[] args) {int i=0;i=i++;System.out.println("i = " + i);
}

在这里插入图片描述

👉分析流程如下所示

在这里插入图片描述
👉举例分析

以 int i=0; i=++i; 的字节码指令展开分析,最后i的值是多少?

示例代码如下

 public static void main(String[] args) {int i=0;i=++i;System.out.println("i = " + i);}

字节码指令如下

 0 iconst_01 istore_12 iinc 1 by 15 iload_16 istore_17 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
10 new #3 <java/lang/StringBuilder>
13 dup
14 invokespecial #4 <java/lang/StringBuilder.<init> : ()V>
17 ldc #5 <i = >
19 invokevirtual #6 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
22 iload_1
23 invokevirtual #7 <java/lang/StringBuilder.append : (I)Ljava/lang/StringBuilder;>
26 invokevirtual #8 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
29 invokevirtual #9 <java/io/PrintStream.println : (Ljava/lang/String;)V>
32 return

👉流程分析如下

①将int类型的 o push 操作数栈中;
②从操作数栈中取出0,放入到局部变量表中位序为1的位置上[i],此时i=0;
③在局部变量表中为位序为1的位置上增加1,此时i=1;
④从局部变量表中位序为1的位置将数据压入到操作数栈中,此时i=0;
⑤将操作数栈中的数据[1]保存到局部变量表中位序为1的位置上,此时i=1;

👉备注

如果不清楚某一条指令的作用,可采取以下步骤

①选中指令,点击“显示JVM规范”

在这里插入图片描述
②浏览器会自动跳转至对应指令的详情页面

在这里插入图片描述


参考目录

https://www.bilibili.com/video/BV1r94y1b7eS?p=7&spm_id_from=pageDriver&vd_source=5a34715e416a427a73a3ca52397848b5


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

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

相关文章

[论文笔记]GTE

引言 今天带来今年的一篇文本嵌入论文GTE, 中文题目是 多阶段对比学习的通用文本嵌入。 作者提出了GTE,一个使用对阶段对比学习的通用文本嵌入。使用对比学习在多个来源的混合数据集上训练了一个统一的文本嵌入模型,通过在无监督预训练阶段和有监督微调阶段显著增加训练数…

MySQL安装多个实例——批处理脚本一键配置MySQL服务

1.下载mysql的免安装压缩包 官网&#xff1a;https://downloads.mysql.com/archives/community/ 2.解压并新增批处理脚本 echo off chcp 65001 setlocal enabledelayedexpansionecho MySQL版本为8.0.34REM 使用set /p命令获取用户输入的端口号 set /p "port请输入端口号…

LabVIEW开发基于图像处理的车牌检测系统

LabVIEW开发基于图像处理的车牌检测系统 自动车牌识别的一般步骤是图像采集、去除噪声的预处理、车牌定位、字符分割和字符识别。结果主要取决于所采集图像的质量。在不同照明条件下获得的图像具有不同的结果。在要使用的预处理技术中&#xff0c;必须将彩色图像转换为灰度&am…

postgresql14管理(五)-tablespace

基本概念 表空间tablespace在postgresql中&#xff0c;表示数据库对象&#xff08;比如表或索引&#xff09;的存放目录。当表被访问时&#xff0c;系统通过表空间定位到对应数据文件所在的位置。 优势&#xff1a; 1、如果数据库集群所在的初始磁盘分区或磁盘卷的空间不足&a…

企业如何选择设备管理系统?

1、需求为王&#xff0c;列出你的需求清单 每个企业的设备都不尽相同&#xff0c;自然对设备管理系统的需求也不一样。因此&#xff0c;需要充分明确自己的需求和目标&#xff0c;清晰地列出需求清单&#xff0c;然后再逐一对照供应商的产品功能&#xff0c;看是否满足自身各业…

蓝桥杯双周赛算法心得——通关(哈希+小根堆)

大家好&#xff0c;我是晴天学长&#xff0c;这是很重要的贪心思维题&#xff0c;哈希的存法和小根堆的表示很重要。 1) .通关 2) .算法思路 通关 用hash&#xff08;int[]&#xff09;存点的子节点并按输入顺序存关卡的号码&#xff08;输入顺序就是&#xff09; 列如&#…

使用 Pyro 和 PyTorch 的贝叶斯神经网络

一、说明 构建图像分类器已成为新的“hello world”。还记得当你第一次接触 Python 时&#xff0c;你的打印“hello world”感觉很神奇吗&#xff1f;几个月前&#xff0c;当我按照PyTorch 官方教程并为自己构建了一个运行良好的简单分类器时&#xff0c;我也有同样的感觉。 我…

JSON parse error: Cannot deserialize instance of `xxx` out of START_ARRAY token

报错原因 前端传参类型是数组&#xff0c;后端接收参数类型是字符串。 解决办法 前端传参类型改为字符串即可。 如下图 【修改前】 【修改后】

计算机网络-应用层(2)

一、DHCP 当需要跨越多个网段提供DHCP 服务时必须使用DHCP 中继代理&#xff0c; 就是在DHCP 客户和服务器之间转发DHCP 消息的主机或路由器。 DHCP 服务端使用UDP 的67号端口来监听和接收客户请求消息&#xff0c; 保留UDP 的68号端口用于接收来自DHCP 服务器的消息回复。 在…

HTTP 之 options预请求 nginx 解决跨域 postman调试跨域问题

一、HTTP一共有八种常见请求方法 get&#xff1a;参数在url上&#xff0c;浏览器长度有限制&#xff0c;不安全post&#xff1a;参数不可见&#xff0c;长度不受限制put&#xff1a;上传最新内容到指定位置delete&#xff1a;删除请求的url所表示的资源head&#xff1a;不返回…

代码随想录算法训练营第三十五天丨 贪心算法part06

738.单调递增的数字 思路 暴力解法 题意很简单&#xff0c;那么首先想的就是暴力解法了【超时】。 贪心算法 题目要求小于等于N的最大单调递增的整数&#xff0c;那么拿一个两位的数字来举例。 例如&#xff1a;98&#xff0c;一旦出现strNum[i - 1] > strNum[i]的情况…

高精度数字电容传感芯片-MDC04

高精度数字电容传感芯片-MDC04 简介引脚说明PCBA板寄存器说明代码实现单总线通讯时序代码单总线通讯时序代码头文件MDC04驱动代码MDC04驱动代码头文件用户APP调用函数main主程序 简介 MDC04以低成本等优势&#xff0c;可用于智能小家电液位、水箱液位、油液液位、水浸传感、食…

干式电抗器的尺寸和重量对系统有什么影响?

干式电抗器是一种用于电力系统中的无功补偿设备&#xff0c;其尺寸和重量对系统有以下几方面的影响&#xff0c;干式电抗器的尺寸和重量会影响设备的安装和布置&#xff0c;较大尺寸和重量的电抗器需要更大的安装空间&#xff0c;并且可能需要额外的支撑结构。在设计系统时需要…

代码随想录打卡第五十三天|309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费

309.最佳买卖股票时机含冷冻期 题目&#xff1a; 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖…

hdlbits系列verilog解答(32位加法器)-25

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 您将获得一个执行 16 位加法的模块 add16 。实例化其中两个以创建一个 32 位加法器。一个 add16 模块在接收到第一个加法器的进位结果后&#xff0c;计算加法结果的低 16 位&#xff0c;而第二个 add16 模块计…

windows + ubuntu + vscode开发环境配置安装

一、卸载WSL/WSL2 如果安装了windows子系统的朋友&#xff0c;可以选择继续使用。或者提前卸载WSL&#xff0c;再选择安装虚拟机。虚拟机占用内存较大&#xff0c;WSL可能对于开发的一些需求还有欠缺。根据自己的实际情况进行选择。 WIN10/11安装WSL(请参考官方资料&#xff0c…

CentOS 7.9.2009 数据盘挂载

一、linux版本&#xff1a; lsb_release -a 二、操作步骤 2.1&#xff0c;查看磁盘挂载情况&#xff0c;确认sdb是需挂载的硬盘 ## 查看磁盘挂载情况&#xff0c;确认sdb是需挂载的硬盘 lsblk 2.2&#xff0c;对硬盘sdb进行分区 ## 对硬盘sdb进行分区 fdisk /dev/sdb# 命令…

【iOS免越狱】利用IOS自动化web-driver-agent_appium-实现自动点击+滑动屏幕

1.目标 在做饭、锻炼等无法腾出双手的场景中&#xff0c;想刷刷抖音 刷抖音的时候有太多的广告 如何解决痛点 抖音自动播放下一个视频 iOS系统高版本无法 越狱 安装插件 2.操作环境 MAC一台&#xff0c;安装 Xcode iPhone一台&#xff0c;16 系统以上最佳 3.流程 下载最…

Visual Studio Professional 2019 软件安装教程(附安装包下载)

Microsoft Visual Studio 是一个非常强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;适用于 Windows 上的 .NET 和 C 开发人员。它提供了一系列丰富的工具和功能&#xff0c;可以提升和增强软件开发的每个阶段。 Visual Studio IDE 是一个创意启动板&#xff0c;可…

配置Super-VLAN下的DHCP服务器示例

组网需求 如图1所示&#xff0c;某公司拥有两个部门&#xff0c;为了节省IP地址&#xff0c;部门A和部门B规划为同一网段&#xff1b;为了提升业务安全性&#xff0c;将不同部门的用户划分到不同VLAN中。企业管理员为了方便统一管理&#xff0c;希望部门内终端通过DHCP服务器动…