前言

大约5年前,想研究javaassistant,cglib等字节码操作的相关类库,来对class进行增强,当要到要操作字节码的时候,发现无法继续下去了,只能放弃。

学习jvm字码,需要理解class的组成方式,对汇编,操作栈比较了解,无奈,只好重新学习编译原理,汇编等知识,再来看jvm规范,现在理解起来,容易很多了。

Class文件规范

编译后被 Java 虚拟机所执行的代码使用了一种平台中立(不依赖于特定硬件及操作系统的)

的二进制格式来表示,并且经常(但并非绝对)以文件的形式存储,因此这种格式被称为 Class

文件格式。Class 文件格式中精确地定义了类与接口的表示形式,包括在平台相关的目标文件格

式中一些细节上的惯例

相关文档

https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

下面,我们开始解析每个字段是如何标识出来的

其中 u4, u2 代表什么意思

u 表示无符号数 后面的数字 表示 占用多少字节

u4 占用4个字节

u2 占用2个字节

  1. magic 占用4个字节,(ca fe ba be )

  1. minor_version 子版本号 ,2个字节数字

  2. major_version 主版本好 2个字节的数字

  1. constant_pool_count 常量池数目 2个字节的数字

  1. constant_pool[constant_pool_count-1] 常量池数组

  1. access_flags 访问标识 2个字节数字
  2. this_class class名称的索引,
  3. super_class 超类的名称索引
  4. interfaces_count 接口的数目
  5. interfaces[interfaces_count] 接口的数组
  6. fields_count 字段数目
  7. fields[fields_count] 字段的数组
  8. methods_count 方法的数目
  9. methods[methods_count] 方法的数组
  10. attributes_count 属性的数目
  11. attributes[attributes_count] 属性的数组

如何自己动手解一个class文件

相信大部分第一样看到上面的协议时候,能看弄,但是要自己动手解析出每个字段的含义出来,

就无法下手了,

  1. 读取class文件
 FileInputStream in= new FileInputStream("d:/my.class");
  1. 读取 magic ,(magic u4 占用4个字节)
 byte[] bytes=new byte[4];
in.read(bytes);
  1. 读取 minor_version u2 占用2个字节
 byte[] minorByte=new byte[2];
in.read(minorByte);
  1. 读取 major_version u2 占用2个字节
 byte[] majorVersion=new byte[2];
in.read(majorVersion);

看到上面的解析,是否明白了,其实还是很有规律的,只要你认真看协议文档(要看好多遍才行)

最终解析class 文档就是这样的

ClassFile classFile = new ClassFile();

        PcBufferInputStream in = new PcBufferInputStream(new FileInputStream(fileName));
classFile.setMagic(readMagic(in));
classFile.setMinorVersion(readMinorVersion(in));
classFile.setMajorVersion(readMajorVersion(in));
classFile.setConstantPoolCount(readConstantPoolCount(in));
classFile.setCpInfo(readCpInfo(in));
classFile.setAccessFlags(readAccessFlags(in));
classFile.setThisClass(readThisClass(in));
classFile.setSuperClass(readSuperClass(in));
classFile.setInterfacesCount(readInterfacesCount(in));
// u2 interfaces interfaces_count
classFile.setInterfaces(readInterfaces(in));
// u2 fields_count
classFile.setFieldsCount(readFieldsCount(in));
// field_info fields fields_count
classFile.setFields(readFields(in));
// u2 methods_count 1
// method_info methods methods_count
classFile.setMethodsCount(readMethodsCount(in));
classFile.setMethods(readMethods(in));
// u2 attribute_count 1
classFile.setAttributeCount(readAttributeCount(in));
// attribute_info attributes attributes_count
classFile.setAttributes(readAttributes(in));
classFile.setPcRecord(recordMap);
return classFile;

java class 解析源码开源地址

https://gitee.com/venus-suite/java-classViewer

如果喜欢,欢迎stars 哦

java class 文件格式解析的更多相关文章

  1. (4) 深入理解Java Class文件格式(三)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/21557357 首先, 让我们回顾一下关于class文件格式的之前两篇博客的主要内容. 在  ...

  2. Java 面试知识点解析(三)——JVM篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  3. (10) 深入了解Java Class文件格式(九)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/22432599 经过前八篇关于class文件的博客, 关于class文件格式的内容也基本上讲 ...

  4. (9) 深入了解Java Class文件格式(八)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/22205831 在本专栏的第一篇文章 深入理解Java虚拟机到底是什么 中, 我们主要讲解了 ...

  5. (8) 深入理解Java Class文件格式(七)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/22091529 本专栏列前面的一系列博客, 对Class文件中的一部分数据项进行了介绍. 本 ...

  6. (7) 深入了解Java Class文件格式(六)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/21888943 经过前几篇文章, 终于将常量池介绍完了, 之所以花这么大的功夫介绍常量池, ...

  7. (6) 深入理解Java Class文件格式(五)

    前情回顾 本专栏的前几篇博文, 对class文件中的常量池进行了详细的解释. 前文讲解了常量池中的7种数据项, 它们分别是: CONSTANT_Utf8_info CONSTANT_NameAndTy ...

  8. (5) 深入理解Java Class文件格式(四)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/21658415 前情回顾   在上一篇博客深入理解Java Class文件格式(三) 中, ...

  9. (3) 深入理解Java Class文件格式(二)

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/21487287 在上一篇文章 深入理解Java Class文件格式(一) 中, 介绍了c ...

随机推荐

  1. 12.11 Exception

    12.11exception 1.类别 检查性异常:用户错误或者问题引起的异常,此类异常程序员无法预见.例如:打开一个不存在的文件,用户输入错误(在只能输数字的地方输入汉字)...... 运行时异常: ...

  2. Golang之框架篇-Windows环境bee工具运行beego

    bee工具简介及好处     bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 你可以很容易的进行 beego 项目的创建.热编译.开发.测试.和部署. 强烈推荐新手或J ...

  3. JdbcTemplate?

    JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理.

  4. List、Set、Map详解及区别

    一.List接口 List是一个继承于Collection的接口,即List是集合中的一种.List是有序的队列,List中的每一个元素都有一个索引:第一个元素的索引值是0,往后的元素的索引值依次+1 ...

  5. 学习Redis(一)

    一.NoSQL 1.NoSql介绍 1.not only SQL,非关系型数据库,它能解决常规数据库的并发.IO与性能的瓶颈 2.解决以下问题: ① 对数据库的高并发读写需求 ② 大数据的高效存储和访 ...

  6. SQL数据库之“TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)”

    一.介绍 样本:TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2) 解析:TIMESTAMPDIFF(格式,开始时间,结束时间) 二.参数解析 格式: ...

  7. ubuntu 安装 mysql mariadb

    本教程面向Ubuntu服务器,适用于Ubuntu的任何LTS版本,包括Ubuntu 14.04,Ubuntu 16.04,Ubuntu 18.04,甚至非LTS版本(如Ubuntu 17.10和其他基 ...

  8. 1. 了解Git和Github

    1. 了解Git和Github 1.1 什么是Git Git是一个免费.开源的版本控制软件 1.2 什么是版本控制系统 版本控制是一种记录一个或若干个文件内容变化,以便将来查阅特定版本修订情况得系统. ...

  9. (stm32f103学习总结)—GPIO结构

    一.GPIO基本结构 二.GPIO工作模式 输入模式 输入浮空 输入上拉 输入下拉 模拟输入 输出模式 开漏输出 开漏复用功能 推挽式输出 推挽式复用功能 库函数中所对应的代码 1 typedef e ...

  10. python模块 | 随机数模块—random模块

    python随机数模块 random - 生成伪随机数,该模块实现了各种分布的伪随机数生成器. 对于整数,从范围中有统一的选择. 对于序列,存在随机元素的统一选择.用于生成列表的随机排列的函数.以及用 ...