解析字节码的作用
- 通过反编译生成字节码文件,可以深入了解Java工作机制,但自己分析类文件结构太麻烦,除了第三方的jclasslib工具外,官方提供了javap
- javap是jdk自带的反解析工具,它的作用是根据class字节码文件,反解析出当前类对应的code区(字节码指令)、局部变量表、异常表、代码行偏移量映射表、常量池等信息
- 通过局部变量表,可以查看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用信息
java -g操作
- 解析字节码文件得到的信息中,有些信息(如局部变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等)需要在使用javac编译成class文件时,指定参数才能输出
- 直接使用javac xx.java,不会生成对应局部变量表等信息,使用javac -g xx.java可以生成相关信息,如使用eclipse或IDEA,默认情况下,在编译时会帮你生成局部变量表,指令和代码偏移量映射表等信息
javap
- 格式 javap
- classes是要反编译的class文件
- 在命令行直接输入javap或javap -help可以看到javap的options有如下选项
C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -version JavapTest.class 1.8.0_131 Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); int getNum(int); protected char showGender(); public void showInfo(); static {}; } // -public 显示公共信息 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -public JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); public void showInfo(); } // -protected C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -protected JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); protected char showGender(); public void showInfo(); } // -private || -p 大于或等于private权限 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -private JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { private int num; boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); private com.chapter09.JavapTest(boolean); private void methodPrivate(); int getNum(int); protected char showGender(); public void showInfo(); static {}; } // -package 显示非私有的信息 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -package JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); int getNum(int); protected char showGender(); public void showInfo(); static {}; } // -sysinfo C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -sysinfo JavapTest.class Classfile /C:/Users/Administrator/IdeaProjects/jvm/target/classes/com/chapter09/JavapTest.class //字节码文件路径 Last modified 2024-5-27; size 1348 bytes //日期 MD5 checksum 85dc41e7e2e7128d8899b5d131d7975f //MD5散列 Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); int getNum(int); protected char showGender(); public void showInfo(); static {}; } // -constants C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -constants JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS = 1; public com.chapter09.JavapTest(); int getNum(int); protected char showGender(); public void showInfo(); static {}; } // -s 输出内部类型签名 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -s JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; descriptor: Z protected char gender; descriptor: C public java.lang.String info; descriptor: Ljava/lang/String; public static final int COUNTS; descriptor: I public com.chapter09.JavapTest(); descriptor: ()V int getNum(int); descriptor: (I)I protected char showGender(); descriptor: ()C public void showInfo(); descriptor: ()V static {}; descriptor: ()V } // -l 输出行号和本地变量表 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -l JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); LineNumberTable: line 20: 0 line 18: 4 line 20: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this Lcom/chapter09/JavapTest; int getNum(int); LineNumberTable: line 26: 0 LocalVariableTable: Start Length Slot Name Signature 0 7 0 this Lcom/chapter09/JavapTest; 0 7 1 i I protected char showGender(); LineNumberTable: line 29: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/chapter09/JavapTest; public void showInfo(); LineNumberTable: line 32: 0 line 33: 3 line 34: 30 LocalVariableTable: Start Length Slot Name Signature 0 31 0 this Lcom/chapter09/JavapTest; 3 28 1 i I static {}; LineNumberTable: line 15: 0 line 16: 3 LocalVariableTable: Start Length Slot Name Signature } // -c 对代码进行反编译 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -l JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); LineNumberTable: line 20: 0 line 18: 4 line 20: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this Lcom/chapter09/JavapTest; int getNum(int); LineNumberTable: line 26: 0 LocalVariableTable: Start Length Slot Name Signature 0 7 0 this Lcom/chapter09/JavapTest; 0 7 1 i I protected char showGender(); LineNumberTable: line 29: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/chapter09/JavapTest; public void showInfo(); LineNumberTable: line 32: 0 line 33: 3 line 34: 30 LocalVariableTable: Start Length Slot Name Signature 0 31 0 this Lcom/chapter09/JavapTest; 3 28 1 i I static {}; LineNumberTable: line 15: 0 line 16: 3 LocalVariableTable: Start Length Slot Name Signature } C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -c JavapTest.class Compiled from "JavapTest.java" public class com.chapter09.JavapTest { boolean flag; protected char gender; public java.lang.String info; public static final int COUNTS; public com.chapter09.JavapTest(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."
":()V 4: aload_0 5: ldc #2 // String java 7: putfield #3 // Field info:Ljava/lang/String; 10: return int getNum(int); Code: 0: aload_0 1: getfield #5 // Field num:I 4: iload_1 5: iadd 6: ireturn protected char showGender(); Code: 0: aload_0 1: getfield #6 // Field gender:C 4: ireturn public void showInfo(); Code: 0: bipush 10 2: istore_1 3: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 6: new #8 // class java/lang/StringBuilder 9: dup 10: invokespecial #9 // Method java/lang/StringBuilder." ":()V 13: aload_0 14: getfield #3 // Field info:Ljava/lang/String; 17: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 20: iload_1 21: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 24: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 27: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: return static {}; Code: 0: ldc #14 // String www.lotus.com 2: astore_0 3: return } // -v 显示最全的字节码反编译数据 C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter09>javap -v JavapTest.class Classfile /C:/Users/Administrator/IdeaProjects/jvm/target/classes/com/chapter09/JavapTest.class //位置 Last modified 2024-5-27; size 1348 bytes //日期,大小 MD5 checksum 85dc41e7e2e7128d8899b5d131d7975f //MD5散列值 Compiled from "JavapTest.java" public class com.chapter09.JavapTest minor version: 0 //副版本号 major version: 52 //主版本号 flags: ACC_PUBLIC, ACC_SUPER //访问标识 Constant pool: #1 = Methodref #16.#46 // java/lang/Object." ":()V #2 = String #47 // java #3 = Fieldref #15.#48 // com/chapter09/JavapTest.info:Ljava/lang/String; #4 = Fieldref #15.#49 // com/chapter09/JavapTest.flag:Z #5 = Fieldref #15.#50 // com/chapter09/JavapTest.num:I #6 = Fieldref #15.#51 // com/chapter09/JavapTest.gender:C #7 = Fieldref #52.#53 // java/lang/System.out:Ljava/io/PrintStream; #8 = Class #54 // java/lang/StringBuilder #9 = Methodref #8.#46 // java/lang/StringBuilder." ":()V #10 = Methodref #8.#55 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #11 = Methodref #8.#56 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; #12 = Methodref #8.#57 // java/lang/StringBuilder.toString:()Ljava/lang/String; #13 = Methodref #58.#59 // java/io/PrintStream.println:(Ljava/lang/String;)V #14 = String #60 // www.lotus.com #15 = Class #61 // com/chapter09/JavapTest #16 = Class #62 // java/lang/Object #17 = Utf8 num #18 = Utf8 I #19 = Utf8 flag #20 = Utf8 Z #21 = Utf8 gender #22 = Utf8 C #23 = Utf8 info #24 = Utf8 Ljava/lang/String; #25 = Utf8 COUNTS #26 = Utf8 ConstantValue #27 = Integer 1 #28 = Utf8 #29 = Utf8 ()V #30 = Utf8 Code #31 = Utf8 LineNumberTable #32 = Utf8 LocalVariableTable #33 = Utf8 this #34 = Utf8 Lcom/chapter09/JavapTest; #35 = Utf8 (Z)V #36 = Utf8 methodPrivate #37 = Utf8 getNum #38 = Utf8 (I)I #39 = Utf8 i #40 = Utf8 showGender #41 = Utf8 ()C #42 = Utf8 showInfo #43 = Utf8 #44 = Utf8 SourceFile #45 = Utf8 JavapTest.java #46 = NameAndType #28:#29 // " ":()V #47 = Utf8 java #48 = NameAndType #23:#24 // info:Ljava/lang/String; #49 = NameAndType #19:#20 // flag:Z #50 = NameAndType #17:#18 // num:I #51 = NameAndType #21:#22 // gender:C #52 = Class #63 // java/lang/System #53 = NameAndType #64:#65 // out:Ljava/io/PrintStream; #54 = Utf8 java/lang/StringBuilder #55 = NameAndType #66:#67 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #56 = NameAndType #66:#68 // append:(I)Ljava/lang/StringBuilder; #57 = NameAndType #69:#70 // toString:()Ljava/lang/String; #58 = Class #71 // java/io/PrintStream #59 = NameAndType #72:#73 // println:(Ljava/lang/String;)V #60 = Utf8 www.lotus.com #61 = Utf8 com/chapter09/JavapTest #62 = Utf8 java/lang/Object #63 = Utf8 java/lang/System #64 = Utf8 out #65 = Utf8 Ljava/io/PrintStream; #66 = Utf8 append #67 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #68 = Utf8 (I)Ljava/lang/StringBuilder; #69 = Utf8 toString #70 = Utf8 ()Ljava/lang/String; #71 = Utf8 java/io/PrintStream #72 = Utf8 println #73 = Utf8 (Ljava/lang/String;)V { //-----------------------------------------------方法 //字段表集合信息 boolean flag; //字段名 descriptor: Z //字段描述符(字段类型) flags: //字段访问标识 protected char gender; descriptor: C flags: ACC_PROTECTED public java.lang.String info; descriptor: Ljava/lang/String; flags: ACC_PUBLIC public static final int COUNTS; descriptor: I flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL ConstantValue: int 1 //常量字段的属性:ConstantValue,保存常量的值 //-----------------------------------------------方法 public com.chapter09.JavapTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object." ":()V 4: aload_0 5: ldc #2 // String java 7: putfield #3 // Field info:Ljava/lang/String; 10: return LineNumberTable: line 20: 0 line 18: 4 line 20: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this Lcom/chapter09/JavapTest; int getNum(int); descriptor: (I)I flags: Code: stack=2, locals=2, args_size=2 0: aload_0 1: getfield #5 // Field num:I 4: iload_1 5: iadd 6: ireturn LineNumberTable: line 26: 0 LocalVariableTable: Start Length Slot Name Signature 0 7 0 this Lcom/chapter09/JavapTest; 0 7 1 i I protected char showGender(); descriptor: ()C flags: ACC_PROTECTED Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #6 // Field gender:C 4: ireturn LineNumberTable: line 29: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/chapter09/JavapTest; public void showInfo(); descriptor: ()V //方法描述符:方法的形参列表、返回值类型 flags: ACC_PUBLIC //方法的访问标识 Code: //方法Code属性 stack=3, locals=2, args_size=1 //stack:操作数栈的最大深度,locals:局部变量表的长度,args_size:方法接收参数的个数 //偏移量 操作码 操作数 0: bipush 10 2: istore_1 3: getstatic #7 //#7常量表索引 // Field java/lang/System.out:Ljava/io/PrintStream; 6: new #8 // class java/lang/StringBuilder 9: dup 10: invokespecial #9 // Method java/lang/StringBuilder." ":()V 13: aload_0 14: getfield #3 // Field info:Ljava/lang/String; 17: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 20: iload_1 21: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 24: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 27: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: return LineNumberTable: //行号表,当前字节码指令偏移量与Java源程序中代码的行号一一对应关系 line 32: 0 line 33: 3 line 34: 30 LocalVariableTable: //局部变量表,描述内部局部变量的相关信息 Start Length Slot Name Signature 0 31 0 this Lcom/chapter09/JavapTest; 3 28 1 i I static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=1, args_size=0 0: ldc #14 // String www.lotus.com 2: astore_0 3: return LineNumberTable: line 15: 0 line 16: 3 LocalVariableTable: Start Length Slot Name Signature } SourceFile: "JavapTest.java" //附加属性:当前字节码对应的源文件的文件名
- 格式 javap
还没有评论,来说两句吧...