-help –help -? 输出此用法消息 -version 版本信息 -v -verbose 输出附加信息 -l 输出行号和本地变量表 -public 仅显示公共类和成员 -protected 显示受保护的/公共类和成员 -package 显示程序包/受保护的/公共类 和成员 (默认) -p -private 显示所有类和成员 -c 对代码进行反汇编 -s 输出内部类型签名 -sysinfo 显示正在处理的类的 系统信息 (路径, 大小, 日期, MD5 散列) -constants 显示静态最终常量 -classpath 指定查找用户类文件的位置 -bootclasspath 覆盖引导类文件的位置
反编译 class 字节码 javap -v class,例如:
class test{ int c; int a; public static void main(String args[]){ test t = new test(); t.get(5); } test(){ super(); c = 1; a = 0; } public int get(int b){ a = b; c = a; return this.a; } }使用javap -v 反编译字节码显示的为:
Last modified 2017-6-20; size 437 bytes MD5 checksum a42a0734a405dcc441a98574b1ac0f69 Compiled from "test.java" class test SourceFile: "test.java" minor version: 0 major version: 51 flags: ACC_SUPER Constant pool: #1 = Class #21 // test #2 = Methodref #1.#22 // test."<init>":()V #3 = Methodref #1.#23 // test.get:(I)I #4 = Methodref #7.#22 // java/lang/Object."<init>":()V #5 = Fieldref #1.#24 // test.c:I #6 = Fieldref #1.#25 // test.a:I #7 = Class #26 // java/lang/Object #8 = Utf8 c #9 = Utf8 I #10 = Utf8 a #11 = Utf8 main #12 = Utf8 ([Ljava/lang/String;)V #13 = Utf8 Code #14 = Utf8 LineNumberTable #15 = Utf8 <init> #16 = Utf8 ()V #17 = Utf8 get #18 = Utf8 (I)I #19 = Utf8 SourceFile #20 = Utf8 test.java #21 = Utf8 test #22 = NameAndType #15:#16 // "<init>":()V #23 = NameAndType #17:#18 // get:(I)I #24 = NameAndType #8:#9 // c:I #25 = NameAndType #10:#9 // a:I #26 = Utf8 java/lang/Object { int c; flags: int a; flags: public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #1 // class test //创建一个test 对象,并将其放入操作数栈中 3: dup // 复制刚刚放入的引用(栈中存在两个相同的引用),放入栈中 4: invokespecial #2 // Method "<init>":()V //使用栈顶的引用调用Constant pool中#2方法即 test 的构造方法,并将引用弹出 7: astore_1 // 将this引用保存到局部变量表 索引1 的位置,然后引出栈 8: aload_1 //将 局部变量表中 1 的值,压入栈中(即对应局部变量 t) 9: iconst_5 // 将5 压入栈中 10: invokevirtual #3 // Method get:(I)I //调用使用局部变量调用其get方法,并从栈顶 中取出 方法的参数 13: pop 14: return LineNumberTable: line 5: 0 line 6: 8 line 7: 14 test(); flags: Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #4 // Method java/lang/Object."<init>":()V //构造方法调用父类的super 方法,此处调用的是Object 空的构造方法 4: aload_0 //将局部变量中的第0位(this)加载到,栈中 5: iconst_1 //将1 压入栈顶 6: putfield #5 // Field c:I //将 1 赋值给c 9: aload_0 //将局部变量中的第0位(this)加载到,栈中 10: iconst_0 //将0 压入栈顶 11: putfield #6 // Field a:I //将 0 赋值给a 14: return LineNumberTable: line 9: 0 line 10: 4 line 11: 9 line 12: 14 public int get(int); flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 //aload_0 局部变量中的第0位一般为 this,见备注 1: iload_1 //取出局部变量中 的第1位(int类型),压入栈中 2: putfield #6 // Field a:I //将 第一个局部变量赋值给 a 5: aload_0 6: aload_0 7: getfield #6 // Field a:I //获取this.a 的值,并将其压入栈中 10: putfield #5 // Field c:I //将this.a 赋值给 this.c 13: aload_0 14: getfield #6 // Field a:I //获取this.a 的值,并将其压入栈中 17: ireturn //返回this.a LineNumberTable: line 14: 0 line 15: 5 line 16: 13 } 这个class文件包含三个主要内容: - Constant Pool 包含当前类的符号 - Method 主要包含 - 方法签名和访问标识 - 字节码 - LineNumberTable 包含源码到字节码的映射,供debug使用 - LocalVariableTable 包含当前frame里的local variable,这里只有一个this变量(这里没有输出来)。其他常见的class字节码指令:
Java虚拟机对于宽化类型转换直接支持,并不需要指令执行,包括:
int类型到long、float或者double类型 long类型到float、double类型 float类型到double类型 窄化类型转换指令包括有:i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l和d2f。但是窄化类型转换很可能会造成精度丢失。备注: 在非静态方法中,aload_0 表示将this 加载到操作数栈 在static 方法中,aload_0表示将方法中地第一个参数(局部变量表中的第一位),加载到操作数栈中。
参考: http://www.yangyong.me/java-class文件和虚拟机字节码指令-如何查看class文件/
http://blog.csdn.net/congwiny/article/details/18867981
http://hubingforever.blog.163.com/blog/static/17104057920117822653653
http://www.itluobo.com/2016/04/20/bytecode/
jvm 栈讲解: http://blog.csdn.net/a616413086/article/details/51272309 http://www.sohu.com/a/147500099_467808