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日