解析class字节码文件获取魔数和版本号

写在前面

本文看下如何获取class字节码文件的魔数和版本号信息。

1:正文

需要对class字节码的结构有一定的了解,可以参考这篇文章 。

直接看代码:

package org.example;import java.math.BigInteger;public class TTTT {//取部分字节码:java.lang.Stringprivate static byte[] classData = {-54, -2, -70, -66, 0, 0, 0, 52, 2, 26, 3, 0, 0, -40, 0, 3, 0, 0, -37, -1, 3, 0, 0, -33, -1, 3, 0, 1, 0, 0, 8, 0,59, 8, 0, 83, 8, 0, 86, 8, 0, 87, 8, 0, 110, 8, 0, -83, 8, 0, -77, 8, 0, -49, 8, 0, -47, 1, 0, 3, 40, 41, 73, 1,0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 1, 0, 20, 40, 41,76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 3, 40, 41, 86, 1, 0, 3,40, 41, 90, 1, 0, 4, 40, 41, 91, 66, 1, 0, 4, 40, 41, 91, 67, 1, 0, 4, 40, 67, 41, 67, 1, 0, 21, 40, 68, 41, 76,106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 4, 40, 73, 41, 67, 1, 0, 4};public static void main(String[] args) {// 显示值是按照有符号数来展示的,为了获取原始的无符号数对应的值,需要与上0xFF,即11111111,这样就转换为无符号数了(不知道为啥啊,反正就这样!!!)。System.out.println("* byte字节码与运算原值(-54)换行后(-54 & 0x0FF):" + (-54 & 0x0FF));//校验魔数readAndCheckMagic();//校验版本号readAndCheckVersion();}/*** 前四个字节是魔术!!!* 校验魔数* <p>* 很多文件格式都会规定满足该格式的文件必须以某几个固定字节开头,这几个字节主要起到标识作用,叫作魔数(magic number)。* 例如;* PDF文件以4字节“%PDF”(0x25、0x50、0x44、0x46)开头,* ZIP文件以2字节“PK”(0x50、0x4B)开头* class文件以4字节“0xCAFEBABE”开头*/private static void readAndCheckMagic() {System.out.println("\r\n------------ 校验魔数 ------------");// 从class字节码中读取前四位,就是魔数,u4类型byte[] magic_byte = new byte[4];System.arraycopy(classData, 0, magic_byte, 0, 4);// 将4位byte字节转成16进制字符串String magicNumberInHex = new BigInteger(1, magic_byte).toString(16);System.out.println("class文件魔数16进制表示为:" + magicNumberInHex);// magicNumberInHex 是16进制的字符串,cafebabe,因为java中没有无符号整型,所以如果想要无符号只能放到更高位中long magic_unsigned_int32 = Long.parseLong(magicNumberInHex, 16);System.out.println("魔术转换为无符号表示(Java没有无符号数,所以转long来表示)magic_unsigned_int32:" + magic_unsigned_int32);//魔数比对,一种通过字符串比对,另外一种使用假设的无符号16进制比较。如果使用无符号比较需要将0xCAFEBABE & 0x0FFFFFFFFL与运算System.out.println("0xCAFEBABE & 0x0FFFFFFFFL(这样也可以转换为正整数表示):" + (0xCAFEBABE & 0xFFFFFFFFL));// 通过比较字节码中获取的和cafebabe的实际值,得出是否是一个class字节码文件(当然不一定合法,因为后续还有很多内容)if (magic_unsigned_int32 == (0xCAFEBABE & 0x0FFFFFFFFL)) {System.out.println("class字节码魔数无符号16进制数值一致校验通过");} else {System.out.println("class字节码魔数无符号16进制数值一致校验拒绝");}}/**** 校验版本号* <p>* 魔数之后是class文件的次版本号和主版本号,都是u2类型。假设某class文件的主版本号是M,次版本号是m,那么完整的版本号可以* 表示成“M.m”的形式。次版本号只在J2SE 1.2之前用过,从1.2开始基本上就没有什么用了(都是0)。主版本号在J2SE 1.2之前是45,* 从1.2开始,每次有大版本的Java版本发布,都会加1{45、46、47、48、49、50、51、52}*/private static void readAndCheckVersion() {System.out.println("\r\n------------ 校验版本号 ------------");//从class字节码第4位开始读取,读取2位byte[] minor_byte = new byte[2];// u2 5,6两个字节是minor version信息System.arraycopy(classData, 4, minor_byte, 0, 2);//将2位byte字节转成16进制字符串String minor_hex_str = new BigInteger(1, minor_byte).toString(16);System.out.println("小版本号16进制表示:" + minor_hex_str);//minor_unsigned_int32 转成无符号16进制int minor_unsigned_int32 = Integer.parseInt(minor_hex_str, 16);System.out.println("小版本号十进制整数表示:" + minor_unsigned_int32);//从class字节码第6位开始读取,读取2位byte[] major_byte = new byte[2];// u2 7,8两个字节是major version信息System.arraycopy(classData, 6, major_byte, 0, 2);//将2位byte字节转成16进制字符串String major_hex_str = new BigInteger(1, major_byte).toString(16);System.out.println("主版本号16进制表示:" + major_hex_str);//major_unsigned_int32 转成无符号16进制int major_unsigned_int32 = Integer.parseInt(major_hex_str, 16);System.out.println("主版本号整数表示:" + major_unsigned_int32);System.out.println("完整版本号:" + major_unsigned_int32 + "." + minor_unsigned_int32);}}

详细的看注释吧,有什么不明白的可留言!
运行如下:

* byte字节码与运算原值(-54)换行后(-54 & 0x0FF):202------------ 校验魔数 ------------
class文件魔数16进制表示为:cafebabe
魔术转换为无符号表示(Java没有无符号数,所以转long来表示)magic_unsigned_int32:3405691582
0xCAFEBABE & 0x0FFFFFFFFL(这样也可以转换为正整数表示):3405691582
class字节码魔数无符号16进制数值一致校验通过------------ 校验版本号 ------------
小版本号16进制表示:0
小版本号十进制整数表示:0
主版本号16进制表示:34
主版本号整数表示:52
完整版本号:52.0Process finished with exit code 0

写在后面

参考文章列表

class字节码文件结构是什么样子的? 。

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

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

相关文章

探索Perl的文件系统抽象层:驾驭文件操作的无形之手

探索Perl的文件系统抽象层&#xff1a;驾驭文件操作的无形之手 在Perl编程中&#xff0c;文件系统抽象层&#xff08;File System Abstraction Layer&#xff0c;简称FSAL&#xff09;是一种允许开发者以统一的方式处理不同文件系统特性的机制。FSAL隐藏了底层文件系统的具体实…

信通院发布!首个大模型混合云标准

近日&#xff0c;中国信通院发布了首个大模型混合云标准&#xff0c;通过定位当前大模型混合云的能力水平&#xff0c;为基于混合云的大模型服务实践提供指引&#xff0c;并明确未来提升方向。同时&#xff0c;中国信通院基于标准展开大模型混合云能力成熟度专项测试&#xff0…

智能家居全在手机端进行控制,未来已来!

未来触手可及&#xff1a;智能家居&#xff0c;手机端的全控时代 艾斯视觉的观点是&#xff1a;在不远的将来&#xff0c;家&#xff0c;这个温馨的港湾&#xff0c;将不再只是我们休憩的场所&#xff0c;而是科技与智慧的结晶。想象一下&#xff0c;只需轻触手机屏幕&#xf…

VMware 上的 Debian Linux 虚拟机无法听到蓝牙耳机的声音解决方案

项目场景&#xff1a; 在Debian上安装QQ音乐&#xff0c;用来摸鱼 问题描述 在安装完QQ音乐后&#xff0c;发现虚拟机无法听到声音&#xff0c;音乐有在正常播放&#xff0c;但是蓝牙耳机没有听到任何声音&#xff1a; 原因分析&#xff1a; 感觉是虚拟机的声卡没有配置&…

用Python实现欧几里得算法

欧几里得算法是求两个数的最大公约数的一种方法。 """ 欧几里得算法是求两个数的最大公约数的一种方法。 """def compute_gcd(a, b):"""使用欧几里得算法计算两个整数的最大公约数。参数:a (int): 第一个整数。b (int): 第二个整…

WiFi通信——STM32通过ESP8266-01S与阿里云通信

嵌入式设计中常用的无线通信方式主要由蓝牙、WiFi、Zigbee、Lora、NB-IOT等等。这些是最常用的&#xff0c;也是在实际项目开发中根据项目的数据通信特点来选择相应的无线通信方式。本设计主要是讲解WiFi在嵌入式开发中的使用。 1.ESP8266的三种模式 1.1 STA模式(Station) 工…

FPGA开发——独立仿真和联合仿真

一、概述 我们在进行FPGA开发的过程之中&#xff0c;大部分情况下都是在进行仿真&#xff0c;从而验证代码实现结果的正确与否&#xff0c;这里我们引入了独立仿真和联合仿真进行一个简单介绍。 联合仿真&#xff1a;一般我们在进行仿真之前需要在相应的软件中建立相应的工程…

昇思25天学习打卡营第01天|昇思MindSpore大模型基础j介绍

昇思MindSpore和华为昇思MindSpore大模型学习打卡系列文章&#xff0c;本文仅供参考~ 文章目录 前言一、昇思MindSpore是什么&#xff1f;二、执行流程三、设计理念四、层次结构五、Huawei昇腾AI全栈 前言 随着计算机大模型的不断发展&#xff0c;Ai这门技术也越来越重要&#…

【LeetCode 随笔】C++入门级,详细解答加注释,持续更新中。。。

文章目录 58.【简单】最后一个单词的长度&#x1f31f; &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留的每一刻&#xff0c;都…

使用vfbox网关实现modbus opc profinet iec61850等协议间的转换

在当今物联网&#xff08;IoT&#xff09;与工业自动化日益融合的时代背景下&#xff0c;协议转换网关作为连接不同设备与系统之间的桥梁&#xff0c;扮演着至关重要的角色。VFBox协议转换网关&#xff0c;作为这一领域内的佼佼者&#xff0c;以其高效、灵活、可靠的性能&#…

学习周报:文献阅读+HEC RAS案例

目录 摘要 Abstract 文献阅读&#xff1a;通过HEC RAS软件为罗马尼亚布加勒斯特市的Dmbovița河水管理的水力模型 文献摘要 讨论|结论 理论知识 边界条件计算 流量计算方式 曼宁公式 (Mannings Equation) 连续性方程 (Continuity Equation) 能量方程 (Energy Equatio…

API资源对象CRD、认识Operator-理论知识和认识Operator-初次上手(2024-07-17)

一、API资源对象CRD Kubernetes 自定义资源定义&#xff08;Custom Resource Definition&#xff0c;简称 CRD&#xff09;是一种强大的 Kubernetes API 扩展机制&#xff0c;允许你定义和创建自己的资源类型&#xff0c;以满足您的应用程序或基础设施需求。 CRD 的核心思想是…

Linux基础 -- 用户态原子操作之3种实现

Linux 用户态的原子操作实例 在Linux用户态编程中&#xff0c;原子操作通常使用内建的原子操作函数或GCC提供的内置函数来实现。这些操作可以保证在多线程环境中数据的同步和一致性。以下是几个常见的原子操作示例&#xff1a; 1. 使用 <stdatomic.h> 中的原子操作 C1…

LeetCode 2766题: 重新放置石块(原创)

【题目描述】 给你一个下标从 0 开始的整数数组 nums &#xff0c;表示一些石块的初始位置。再给你两个长度 相等 下标从 0 开始的整数数组 moveFrom 和 moveTo 。 在 moveFrom.length 次操作内&#xff0c;你可以改变石块的位置。在第 i 次操作中&#xff0c;你将位置在 moveF…

vue新建项目时异常解决-@babel/helper-create-regexp-features-plugin@^7.25.0.

问题&#xff1a; 本地vue新增项目时报错了&#xff1a; 4238 error code ETARGET 4239 error notarget No matching version found for babel/helper-create-regexp-features-plugin^7.25.0. 4240 error notarget In most cases you or one of your dependencies are reques…

基于Pytorch框架的深度学习densenet121神经网络鸟类行为识别分类系统源码

第一步&#xff1a;准备数据 5种鸟类行为数据&#xff1a;self.class_indict ["bowing_status", "grooming", "headdown", "vigilance_status", "walking"] &#xff0c;总共有23790张图片&#xff0c;每个文件夹单独放一…

Leetcode 2824. 统计和小于目标的下标对数目

2824. 统计和小于目标的下标对数目 2824. 统计和小于目标的下标对数目 一、题目描述二、我的想法 一、题目描述 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target &#xff0c;请你返回满足 0 < i < j < n 且 nums[i] nums[j] < target 的下标对…

从零搭建pytorch模型教程(八)实践部分(二)目标检测数据集格式转换

前言 图像目标检测领域有一个非常著名的数据集叫做COCO&#xff0c;基本上现在在目标检测领域发论文&#xff0c;COCO是不可能绕过的Benchmark。因此许多的开源目标检测算法框架都会支持解析COCO数据集格式。通过将其他数据集格式转换成COCO格式可以无痛的使用这些开源框架来训…

【计算机网络】静态路由实验

一&#xff1a;实验目的 1&#xff1a;掌握通过静态路由方法实现网络的连通性。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS-C服务器、网线、Windows 2019/2003操作系统的计算机等。 软件&#xff1a;记事本、WireShark、Chrome浏览器等。 三&#xff1a;实验方…

Spring集成ES

RestAPI ES官方提供的java语言客户端用以组装DSL语句,再通过http请求发送给ES RestClient初始化 引入依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </d…