当前位置: 首页 > news >正文

Android---字节码层面分析Class类文件

Java 提供了一种可以在所有平台上都能使用的一种中间代码---字节码文件(.class文件)。有了字节码,无论是那个平台只要安装了虚拟机都可以直接运行字节码文件。有了虚拟机,解除了 java 虚拟机与 java 代码之间的耦合。

Java 虚拟机当初被设计出来时就不单单只运行 java 这一种语言,目前 java 虚拟机已经可以支持很多除 java 语言以外的其它语言了,比如 Groovy, JRuby, json, skilla等。之所以可以支持其它语言,是因为这些语言经过编译之后,也可以生成能够被 JVM 解析并执行的字节码文件。而虚拟机并不关心字节码是由哪一种语言编译而来,如下图所示:

class 文件

从纵观的角度看,class 文件里只有两种数据结构:无符号数

\bullet 无符号数:属于基本的数据类型。以 u1,u2,u4,u8来分别代表 1 个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用,数量值或者字符串(UTF-8编码)。

\bullet 表:表由多个无符号数或者其它表作为数据项构成的复合数据类型。class 文件中所有的表都以“_info”结尾。整个 class 文件本质上就是一张表。

表和无符号数之间的关心

class 文件结构

无符号数和表组成了 class 中的各个结构,这些结构按照预先规定好的顺序紧密的从前向后排列,相邻的项之间没有任何间隙。当 JVM 加载某个 class 文件时,JVM 就是根据上图中的结构去解析 class 文件。加载 class 文件到内存中,并在内存中分配相应的内存空间,具体某种结构需要占用多大的空间,可以参考如下图:

实例解析:

把 test.java 编译成 test.class 文件。用十六进制编辑器打开 .class 文件(可以用在线的编辑器 HexD.it)。

package software_test;import java.io.Serializable;public class test implements Serializable, Cloneable {private int num = 1;public int add(int i) {int j = 10;num = num + i + j;return num;}}

打开 test.class 文件的内容

1. 魔数(magic number)

在 class 文件开头的四个字节是 class 文件的魔数,它是一个固定的值--0XCAFEBABE。魔数是 class 文件的标志,它是判断一个文件是不是 class 格式文件的标准。

2. 版本号

前两个字节 0000代表次版本号(minor_version),后两个字节 0034 是主版本号(major_version),对应的十进制值为52,当前 class 文件的主版本号为52,次版本号为0,所以综合版本号是52.0,也就是 jdk1.8.0。

3. 常量池

紧跟在版本号之后的是一个叫做常量池的表(cp_info)。在常量池中保存了类的各种相关信息,比如类的名称父类的名称类中的方法名参数名称参数类型等。

常量池中的每一项都是一个表,其项目类型共有14种。常量池中的每一项都会有一个 u1 大小的 tag 值,是表的标识。

JVM 解析 class 文件时,通过 tag 值来判断当前数据结构是哪一个表。例如,CONSTANT_Class_info 表:

tag:占用一个字节大小,值为为7,说明是 CONSTANT_Class_info 类型表。

name_index:是一个索引值,可以将它理解为一个指针,指向常量池中索引为 name_index 的常量表。比如 name_index = 7,则它指向常量池中第7个常量表(表与表之间是有关联的)。

再例如 CONSTANT_Utf8_info 表:

tag:值为1,表示是 CONSTANT_Utf8_info类型表。

length:表示 u1[]的长度,比如length = 5,则表示接下来的数据是 5 个连续的u1类型数据。

bytes: u1 类型数组,长度为上面第2个参数 length 的值。

面试题:Java 源文件中 String 字符串的长度 有限制吗?

有(字符串存储在Class文件的常量池中)。在 Java 代码中声明的 String 字符串最终在 class 文件中的存储格式是 CONSTANT_utf8_info因此一个字符串最大长度也就是 u2 所能代表的最大值 65536(2^16) 个,但是需要使用2个来保存null值,因此一个字符串的最大长度为 65536 - 2 = 65534。

class 文件在常量池的前面使用2个字节的容量计数器,用来代表当前类中常量池的大小。

001D 转化为十进制为29,即常量计数器的值为29。其中下标为0的常量被 JVM 留作其他特殊用途,因此 Test.class 中时间的常量池大小为这个计数器的值减1,也就是28个。

第一个常量:

0A 转化为十进制为10,通过查看常量池14种表格图,可以查到 tag=10的表类型为 CONSTANT_Methodref_info,因此常量池中的第一个常量类型为类的方法引用表。其结构如下:

也就是说,0A之后的两个直接是指向该方法所属类,再紧跟的两个字节指向此方法的名称和类型。

0006:十进制为6,表示指向常量池中的第6个常量;

000F:十进制为15,表示指向常量池中的第 15 个常量。

至此,第一个常量解读完毕!

第二个常量:

09转化为十进制为9,即tag = 9,表示是字段引用表 CONSTANT_Fieldref_info,其结构如下:

同理,

0010:指向常量池中第 16 个常量,0011指向常量池中第17个常量。

至此,我们已经解析了常量池中的2个常量,剩下的26个常量也是如此。

4. 访问标志

紧跟在常量池之后的常量是访问标志,占用两个字节。访问标志代表类或者接口的访问信息。比如:该 class 文件是类还是接口,是否被定义成 public,是否是 abstract,如果是类,是否被声明成 final 等。各种访问标志如下图所示:

我们定义的 test.java 是一个普通 Java 类,不是接口、枚举或注解,并且被 public 修饰但没有被声明为 final 和 abstract,因此它所对应的 access_flags 为 0021(0X0001 和 0X0020相结合)。

5. 类索引、父类索引和接口索引计时器

访问标志后的2个字节就是类索引,类索引后的2个字节就是父类索引,父类索引后的2个字节则是接口索引计数器。如下图所示:

 综上所述,我们可以得出当前类为 Test继承自 Object 类,并实现了 “Serializable”和“Cloneable”这两个接口。 

6. 字段表

紧跟在接口索引集合后面的就是字段表,字段表的主要功能是用来描述类或者接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但不包含方法中的局部变量。其具体结构如下:

字段访问标志

其中,第7和8个常量就 num 和 i。因此可以得出,类中有一个为num,类型为 int  的变量。

7. 方法表

字段之后跟着的就是方法表常量,方法表常量应该也是以一个计数器开始的,因为一个类中的方法数量是不固定的。

上图表示 test.class中有两个方法,但是我们只在 test.java 中声明了一个 add 方法,因为默认构造器方法也被包含在方法表常量中。方法表结构如下:

访问标志

8. 属性表

在之前解析字段和方法的时候,在它们的具体结构中,都能看到有一个叫做 attributes_info 的表,这就是属性表。属性表没有一个固定结构,各种不同的属性只要满足以下结构即可:

 

相关文章:

Android---字节码层面分析Class类文件

Java 提供了一种可以在所有平台上都能使用的一种中间代码---字节码文件(.class文件)。有了字节码,无论是那个平台只要安装了虚拟机都可以直接运行字节码文件。有了虚拟机,解除了 java 虚拟机与 java 代码之间的耦合。 Java 虚拟机当初被设计出来时就不单…...

【2023研电赛】东北赛区一等奖作品:基于FPGA的小型水下无线光通信端机设计

本文为2023年第十八届中国研究生电子设计竞赛东北赛区一等奖作品分享,参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领!,分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领&a…...

JWT授权为啥要在 Authorization标头里加个Bearer 呢

这是因为 W3C 的 HTTP 1.0 规范&#xff0c;Authorization 的格式是&#xff1a; Authorization: <type> <authorization-parameters> w3c规定&#xff0c;请求头Authorization用于验证用户身份。这就是告诉我们&#xff0c;token应该写在请求头Authorization中 …...

一篇理解TCP协议

一、TCP协议概念。 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。它主要用于在计算机网络中&#xff0c;通过建立可靠的通信连接来进行数据传输。 TCP协议的特点如下&#xff1a; 可靠性&#xf…...

rk平台android12系统设置里面互联网选项中的以太网选项点击不了问题

rk平台android12系统中,系统设置中的互联网选项,当连接以太网以后,会显示以太网的选项,但是点击没作用,现在需要点击能够进入到以太网的设置界面,需要添加相关的点击事件。 首先,在packages/apps/Settings/AndroidManifest.xml中的以太网设置配置添加一个action,用于打…...

ctrl+d和ctrl+c的区别

CtrlD和CtrlC都是常用的键盘快捷键&#xff0c;但它们的功能不同。 CtrlD 在不同的操作系统和应用程序中可以有不同的功能。在Unix/Linux系统的命令行终端中&#xff0c;CtrlD的作用是发送EOF&#xff08;End of File&#xff09;信号&#xff0c;表示输入结束。在Windows系统中…...

ChatGLM2-6B微调实践

ChatGLM2-6B微调实践 环境准备安装部署1、安装 Anaconda2、安装CUDA3、安装PyTorch4、安装 ChatGLM2-6B 微调实践1、准备数据集2、安装python依赖3、微调并训练新模型4、微调后模型的推理与评估5、验证与使用微调后的模型 微调过程中遇到的问题 环境准备 申请阿里云GPU服务器&…...

YOLOv7独家改进FPN系列:结合新颖的 GhostSlimPAN 范式网络结构,进一步提升检测器性能

💡本篇内容:YOLOv7改进FPN系列:结合新颖的 GhostSlimFPN 范式网络结构,进一步提升检测器性能 重点:🔥🔥🔥YOLOv7 使用这个 核心创新点 在数据集改进做实验:即插即用: 当 Slim 遇到 YOLO 系列 💡🚀🚀🚀本博客 YOLO系列 + 改进源代码改进 适用于 YOLOv7…...

12. Java异常及异常处理处理

Java —— 异常及处理 1. 异常2. 异常体系3. 常见Exception4. 异常处理4.1 try finally catch关键字4.2 throws和throw 自定义异常4.3 finally&#xff0c;final&#xff0c;finalize三者的区别 1. 异常 异常&#xff1a;在程序执行过程中发生的意外状况&#xff0c;可能导致程…...

自定义hooks函数

体会1 1、js文件中定义useXX函数 export function usetestY() {const count ref(10);const doubleCount computed(() > count.value * 2);return {count,doubleCount,}; } 2、在vue文件中使用useXX函数 import { usetestY } from ./data;const { count, doubleCount } …...

Linux系统及Docker安装RabbitMq

目录 一、linux系统安装 1、上传文件 2、在线安装依赖环境 3、安装Erlang 4、安装RabbitMQ 5、开启管理界面及配置 6、启动 7、删除mq 二、docker安装 1、上传mq.tar包或使用命令拉取镜像 2、启动并运行 3、访问mq 一、linux系统安装 1、上传文件 2、在线安装依赖环…...

山东省赛二阶段第一部分解题思路

提交攻击者的IP地址 192.168.1.7 这个直接awk过滤一下ip次数&#xff0c;这个ip多得离谱&#xff0c;在日志里面也发现了它的恶意行为&#xff0c;后门&#xff0c;反弹shell 识别攻击者使用的操作系统 Linux 找出攻击者资产收集所使用的平台 shodan 提交攻击者目…...

WebGoat 靶场 JWT tokens 四 五 七关通关教程

文章目录 webGoat靶场第 四 关 修改投票数第五关第七关 你购买书&#xff0c;让Tom用户付钱 webGoat靶场 越权漏洞 将webgoat-server-8.1.0.jar复制到kali虚拟机中 sudo java -jar webgoat-server-8.1.0.jar --server.port8888解释&#xff1a; java&#xff1a;这是用于执行…...

【单元测试】如何使用 JUnit5 框架?

JUnit5 单元测试框架使用教程 一、Junit5 是什么&#xff1f; Junit5是一个用于在Java平台上进行单元测试的框架。JUnit 5 框架主要由三部分组成&#xff1a;JUnit Platform、JUnit Jupiter 和 JUnit Vintage。 JUnit Platform&#xff1a;定义了测试引擎的 API&#xff0c;是…...

C#封装、继承和多态的用法详解

大家好&#xff0c;今天我们将来详细探讨一下C#中封装、继承和多态的用法。作为C#的三大面向对象的特性&#xff0c;这些概念对于程序员来说非常重要&#xff0c;因此我们将对每个特性进行详细的说明&#xff0c;并提供相应的示例代码。 目录 1. 封装&#xff08;Encapsulati…...

数据结构与算法(持续更新)

线性表 单链表 单链表的定义 由于顺序表的插入删除操作需要移动大量的元素&#xff0c;影响了运行效率&#xff0c;因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素&#xff0c;不需要使用地址连续的存储单元&#xff0c;因此它…...

HDLbits: ece241 2014 q4

module top_module (input clk,input x,output z ); reg [2:0] Q;always(posedge clk)beginQ[0] < Q[0] ^ x;Q[1] < (~Q[1]) & x;Q[2] < (~Q[2]) | x;z < ~(| Q[2:0]); //错误&#xff01;&#xff01;&#xff01;&#xff01;endendmodule 正确答案&#xf…...

LuatOS-SOC接口文档(air780E)-- gmssl - 国密算法

sm.sm2encrypt(pkx,pky,data)# sm2算法加密 参数 传入值类型 解释 string 公钥x,必选 string 公钥y,必选 string 待计算的数据,必选,最长255字节 返回值 返回值类型 解释 string 加密后的字符串, 原样输出,未经HEX转换 例子 local originStr "encryptio…...

【线性代数及其应用 —— 第一章 线性代数中的线性方程组】-1.线性方程组

所有笔记请看&#xff1a; 博客学习目录_Howe_xixi的博客-CSDN博客https://blog.csdn.net/weixin_44362628/article/details/126020573?spm1001.2014.3001.5502思维导图如下&#xff1a; 内容笔记如下&#xff1a;...

vue实现拖拽排序

在业务中列表拖拽排序是比较常见的需求&#xff0c;常见的JS拖拽库有Sortable.js&#xff0c;Vue.Draggable等&#xff0c;大多数同学遇到这种需求也是更多的求助于这些JS库&#xff0c;其实&#xff0c;使用HTML原生的拖放事件来实现拖拽排序并不复杂&#xff0c;结合Vue的tra…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...