浅谈javap命令拆解字节码文件
作者:20481024
这篇文章主要介绍了拆解字节码文件javap命令,对反编译感兴趣的同学可以参考下
目的拆解分析反编译字节码 解析成人能够理解的结构 ,然后再对字节码文件进一步分析
源代码
public class test { private static int classV =2; public static void main(String[] args) { classV =200; int localV =4; localV =400; } }
二进制
idea bin_ed插件查看。
看不懂 那就使用人能看的懂的汇编语言查看类文件结构和代码指令。
javap 指令和选项
0:无选项
打印package, protected and public fields, and methods public class com.example.test { public com.example.test(); public static void main(java.lang.String[]); static {}; }
1:辅助指令
-help
–help
-?
2:代码行号和方法的局部变量表
-l
public class com.example.test { //默认构造方法 public com.example.test(); //代码行号:命令偏移位置 LineNumberTable: line 3: 0 //局部变量表 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/example/test; public static void main(java.lang.String[]); //代码行号:命令偏移位置 LineNumberTable: line 6: 0 line 7: 6 line 8: 8 line 9: 12 //局部变量表 LocalVariableTable: Start Length Slot Name Signature 0 13 0 args [Ljava/lang/String; //方法参数 8 5 1 localV I。/局部变量localV //静态代码块 static {}; LineNumberTable: line 4: 0 }
3 用级别过滤方法 属性 类
-public
-protected
-private
-p
4.反汇编 出汇编指令
javap -c
//纯汇编指令 public class com.example.test { public com.example.test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: sipush 200 3: putstatic #2 // Field classV:I 6: iconst_4 7: istore_1 8: sipush 400 11: istore_1 12: return static {}; Code: 0: iconst_2 1: putstatic #2 // Field classV:I 4: return }
5 显示verbose详细信息
javap -v
Classfile /Users/zhangshanxue/Downloads/akka-quickstart-java/target/classes/com/example/test.class //javap -sysinfo显示下面3行 Last modified 2021-4-5; size 507 bytes MD5 checksum 24a0c74751aafd61d0f7f69be9c161db Compiled from "test.java" public class com.example.test //即1.8 对照表和原因见附录1 //u2类型 即每个占用两个字节 minor version: 0 major version: 52 //类标志 见附录2 //u2类型access_flags 通过位与表示多个权限 flags: ACC_PUBLIC, ACC_SUPER //常量池。class文件结构重点 //u2 2两个字节 表示数量 //pool 常量池 //constant_pool_count 和constant_pool[]表示为常量池中内容 //后面大部分内容依赖此常量池 Constant pool: #1 = Methodref #4.#22 // java/lang/Object."<init>":()V #2 = Fieldref #3.#23 // com/example/test.classV:I #3 = Class #24 // com/example/test #4 = Class #25 // java/lang/Object #5 = Utf8 classV #6 = Utf8 I #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 Lcom/example/test; #14 = Utf8 main #15 = Utf8 ([Ljava/lang/String;)V #16 = Utf8 args #17 = Utf8 [Ljava/lang/String; #18 = Utf8 localV #19 = Utf8 <clinit> #20 = Utf8 SourceFile #21 = Utf8 test.java #22 = NameAndType #7:#8 // "<init>":()V #23 = NameAndType #5:#6 // classV:I #24 = Utf8 com/example/test #25 = Utf8 java/lang/Object { public com.example.test(); descriptor: ()V flags: ACC_PUBLIC Code: //代码汇编指令 stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return //Javap -l显示下面信息 //行号和上面对应的指令偏移位置 LineNumberTable: line 3: 0 LocalVariableTable: //局部变量表 在指令偏移位置start start+length之间有效 Start Length Slot Name Signature 0 5 0 this Lcom/example/test; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: //代码汇编指令 stack=1, locals=2, args_size=1 0: sipush 200 3: putstatic #2 // Field classV:I 6: iconst_4 7: istore_1 8: sipush 400 11: istore_1 12: return //Javap -l显示下面信息 //行号和上面对应的指令偏移位置 LineNumberTable: line 6: 0 line 7: 6 line 8: 8 line 9: 12 LocalVariableTable: Start Length Slot Name Signature 0 13 0 args [Ljava/lang/String; 8 5 1 localV I static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=0, args_size=0 0: iconst_2 1: putstatic #2 // Field classV:I 4: return //行号和上面对应的指令偏移位置 LineNumberTable: line 4: 0 }
附录1
1.1从45开始因为正式发布之前可能 其他版本号可能已经被用了
1.5改为5.0 也是差不多原因 为了表示重要性更名
Corresponding major version 指定版本 和"Supported major versions"兼容范围
附录2
附录3
直接分析字节码块
1为了方便交流表达class文件的结构
使用u1 u2 u4 u8无符号数表示字节数使用*_info 结尾表示池(数组cp_info、field_info、method_info、attribute_info
ClassFile { //表示java class的文件格式 固定为cafe baby 4个字节 u4 magic; //主版本号和次版本号共同决定了类文件格式的版本 //u2类型 即每个占用两个字节 //56包含56以后support for N.0 and N.65535 u2 minor_version; //主版本号56(java12)之前 minjor只支持0 u2 major_version; //常量池数量 u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; //this_class、super_class、interfaces指向常量池的CONSTANT_Class_info u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; //指向常量池structures:CONSTANT_Fieldref_info 结构 field_info fields[fields_count]; u2 methods_count; //指向常量池CONSTANT_Methodref_info 结构 method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
附录4
常量池字节码结构和常量池结构部分对应关系
以上就是拆解字节码文件javap命令的详细内容,更多关于拆解字节码文件javap命令的资料请关注脚本之家其它相关文章!
您可能感兴趣的文章:
- 学会Java字节码指令,成为技术大佬
- Java之字节码以及优势案例讲解
- Java字节码增强技术知识点详解
- 详解Java动态字节码技术
- 详解Java字节码编程之非常好用的javassist
- Java字节码中jvm实例用法
- Javassist如何操作Java 字节码
- Java中invokedynamic字节码指令问题
- java获取版本号及字节码编译版本方法示例
- java 获取字节码文件的几种方法总结
- java 中如何获取字节码文件的相关内容
- java字节码框架ASM操作字节码的方法浅析
- java字节码框架ASM的深入学习
- Java 将字符串动态生成字节码的实现方法
- 通过java字节码分析学习对象初始化顺序
- Java字节码的增强技术