Transform+ASM插桩系列——熟悉Java字节码

Posted 许主任在上班

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Transform+ASM插桩系列——熟悉Java字节码相关的知识,希望对你有一定的参考价值。

前言

为什么要学习Java字节码呢,因为我们学的是插桩字节码技术,这块技术的根底就是字节码,要学会字节码的阅读和字节码的编写,虽然现在很多工具可以帮我们阅读和编写,但最根本的知识还是要理解的。万层楼高从地起,打好基础是关键。

字节码和ClassFile关系

ClassFile是以.class结尾的二进制文件,而该二进制文件中存储的内容就是16进制的Java字节码,在我们学习的插桩技术中,本质就是修改Java字节码文件,也就是要修改ClassFile,读懂Java字节码的基础就是要读懂ClassFile的意思

ClassFile解读

ClassFile是字节码存储文件,规定了规范,我们只需要按照规范的内容进行解析和解读即可知道表达的意思,我们通过简单的例子来演示

1、Hello Word

简单的写一段HelloWord代码,

package hensen;

public class Demo 
    public static void main(String[] args) 
        System.out.println("Hello World.");
    

通过javac生成class文件,通过Editor010读取里面的十六进制格式的内容

通过javap -v 查看class文件的结构,这个接口是java帮我们打印出来的,下面我们就看看怎么解析的

2、ClassFile结构解析

Class文件的格式,解析出来的结构如下

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];

  • u1: 表示占用1个字节,2个16进制字符
  • u2: 表示占用2个字节,4个16进制字符
  • u4: 表示占用4个字节,8个16进制字符
  • u8: 表示占用8个字节,16个16进制字符

3、字节码解析案例

(一)魔数

CAFE BABE

第1 - 4个字节表示magic魔数,魔数的作用是Class文件的标识,虚拟机会判断这个文件是否为一个能被虚拟机接受的Class文件

(二)文件版本

0000 0034
  • 第5 - 6个字节表示minor_versionJDK的次版本号
  • 第7 - 8个字节表示major_versionJDK的主版本号
JDK版本次版本号主版本号十进制
JDK1.70000003351
JDK1.80000003452

(三)常量池

接着是到了常量池的解析

001D
  • 前2个字节表示常量池个数,其值为29,表示一共有29 - 1 = 28个常量
  • 后N个字节表示常量池的具体内容

确定常量池数量后,要确定常量池内容

cp_info 
    u1 tag;
    u1 info[];

常量池的内容都会有个统一个格式,前1个字节表示类型,后面的字节表示常量池的值

0A 00 06 00 0F
字段长度字段值说明
CONSTANT_Methodref_infou1tag(0x0A)类中方法的符号引用
u2class_index指向声明方法的类描述符CONSTANT_Class_info的索引项
u2name_and_type_index指向名称及类型描述符CONSTANT_NameAndType的索引项

通过常量池寻表,可以发现,该常量项第2-3个字节表示类信息,第4-5个字节表示名称及类描述符

  • class_index:0x06(#6)
  • name_and_type_index:0x0F(#15)

以上是关于Transform+ASM插桩系列——熟悉Java字节码的主要内容,如果未能解决你的问题,请参考以下文章

Transform+ASM插桩系列——Transform+ASM的实战

Transform+ASM插桩系列——Transform+ASM的实战

Android Gradle 中的字节码插桩之ASM

看这一篇,你也可以自如的掌握字节码插桩

看这一篇,你也可以自如的掌握字节码插桩

Android ASM 插桩实践