kaka
2017-11-03 13:49:56
java字节码分析工具classpy
先附上这个开源工具的地址:https://github.com/zxh0/classpy
我是怎么知道这个工具的呢,前几天我突然想看看foreach底层的实现原理,于是我写了一个demo想看看字节码是什么样的,demo如下;
import java.util.ArrayList;
import java.util.List;
/**
* @author kaka
* @create 2017-10-26 15:10
**/
public class ForeachTest {
List<Integer> integerList = new ArrayList<>();
Integer[] args = new Integer[12];
public void foreachTest(){
for(Integer i : args){
}
}
}
编译后的class文件如果你用文本编辑器打开会是下面这样子的
用命令javap -verbose className可以反编译字节码,比如:
javap -verbose ForeachTest,得到的内容如下
警告: 二进制文件ForeachTest包含com.suninfo.service.test.monitor.ForeachTest
Classfile /E:/workspace/suninfo-api/src/test/java/com/suninfo/service/test/monitor/ForeachTest.class
Last modified 2017-10-26; size 590 bytes
MD5 checksum f2817ab03d0e82d8b278c5a8e7a9d7a3
Compiled from "ForeachTest.java"
public class com.suninfo.service.test.monitor.ForeachTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #8.#24 // java/lang/Object."<init>":()V
#2 = Class #25 // java/util/ArrayList
#3 = Methodref #2.#24 // java/util/ArrayList."<init>":()V
#4 = Fieldref #7.#26 // com/suninfo/service/test/monitor/ForeachTest.integerList:Ljava/util/List;
#5 = Class #27 // java/lang/Integer
#6 = Fieldref #7.#28 // com/suninfo/service/test/monitor/ForeachTest.args:[Ljava/lang/Integer;
#7 = Class #29 // com/suninfo/service/test/monitor/ForeachTest
#8 = Class #30 // java/lang/Object
#9 = Utf8 integerList
#10 = Utf8 Ljava/util/List;
#11 = Utf8 Signature
#12 = Utf8 Ljava/util/List<Ljava/lang/Integer;>;
#13 = Utf8 args
#14 = Utf8 [Ljava/lang/Integer;
#15 = Utf8 <init>
#16 = Utf8 ()V
#17 = Utf8 Code
#18 = Utf8 LineNumberTable
#19 = Utf8 foreachTest
#20 = Utf8 StackMapTable
#21 = Class #14 // "[Ljava/lang/Integer;"
#22 = Utf8 SourceFile
#23 = Utf8 ForeachTest.java
#24 = NameAndType #15:#16 // "<init>":()V
#25 = Utf8 java/util/ArrayList
#26 = NameAndType #9:#10 // integerList:Ljava/util/List;
#27 = Utf8 java/lang/Integer
#28 = NameAndType #13:#14 // args:[Ljava/lang/Integer;
#29 = Utf8 com/suninfo/service/test/monitor/ForeachTest
#30 = Utf8 java/lang/Object
{
java.util.List<java.lang.Integer> integerList;
descriptor: Ljava/util/List;
flags:
Signature: #12 // Ljava/util/List<Ljava/lang/Integer;>;
java.lang.Integer[] args;
descriptor: [Ljava/lang/Integer;
flags:
public com.suninfo.service.test.monitor.ForeachTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/util/ArrayList
8: dup
9: invokespecial #3 // Method java/util/ArrayList."<init>":()V
12: putfield #4 // Field integerList:Ljava/util/List;
15: aload_0
16: bipush 12
18: anewarray #5 // class java/lang/Integer
21: putfield #6 // Field args:[Ljava/lang/Integer;
24: return
LineNumberTable:
line 10: 0
line 11: 4
line 12: 15
public void foreachTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=5, args_size=1
0: aload_0
1: getfield #6 // Field args:[Ljava/lang/Integer;
4: astore_1
5: aload_1
6: arraylength
7: istore_2
8: iconst_0
9: istore_3
10: iload_3
11: iload_2
12: if_icmpge 26
15: aload_1
16: iload_3
17: aaload
18: astore 4
20: iinc 3, 1
23: goto 10
26: return
LineNumberTable:
line 14: 0
line 17: 26
StackMapTable: number_of_entries = 2
frame_type = 254 /* append */
offset_delta = 10
locals = [ class "[Ljava/lang/Integer;", int, int ]
frame_type = 248 /* chop */
offset_delta = 15
}
SourceFile: "ForeachTest.java"
ok,现在用classpy打开看看,关于classpy环境依赖下载地址上有说明,首先保证你的环境里配置了gradle,然后进入到classpy目录下执行命令:
1.编译:gradle uberjar
2.启动:gradle run
以上两步可以打开classpy界面,顺便手动打开下上面编译的class文件,如下
是不是很清晰,左侧就是标准的字节码总览图,和下面的java字节码总览图对比下:
挺好用的工具,感谢开源世界!
评论
最近浏览
testjava1122
2019年11月5日
暂无贡献等级
a464216394 LV2
2019年6月6日
ncaihua LV7
2019年5月17日
zhuce0001
2019年1月29日
暂无贡献等级
Dz______ LV2
2018年8月3日
上世纪风景 LV11
2018年7月16日
依然在路上 LV17
2018年7月9日
JamesOne LV2
2018年4月19日
wgc_jy LV21
2018年2月2日
pengboss LV12
2018年2月2日





