javap 与字节码指令
来源:互联网 发布:查找淘宝用户购买记录 编辑:程序博客网 时间:2024/06/04 19:44
javap 常用指令
-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_SUPERConstant 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字节码指令:
加载和存储指令:
将一个局部变量加载到操作栈的指令包括有:iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>将一个数值从操作数栈存储到局部变量表的指令包括有:istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>将一个常量加载到操作数栈的指令包括有:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>扩充局部变量表的访问索引的指令:wide
运算指令:
加法指令:iadd、ladd、fadd、dadd减法指令:isub、lsub、fsub、dsub乘法指令:imul、lmul、fmul、dmul除法指令:idiv、ldiv、fdiv、ddiv求余指令:irem、lrem、frem、drem取反指令:ineg、lneg、fneg、dneg位移指令:ishl、ishr、iushr、lshl、lshr、lushr按位或指令:ior、lor按位与指令:iand、land按位异或指令:ixor、lxor局部变量自增指令:iinc比较指令:dcmpg、dcmpl、fcmpg、fcmpl、lcmp
类型转换指令:
Java虚拟机对于宽化类型转换直接支持,并不需要指令执行,包括:
int类型到long、float或者double类型long类型到float、double类型float类型到double类型窄化类型转换指令包括有:i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l和d2f。但是窄化类型转换很可能会造成精度丢失。
对象创建与操作指令:
创建类实例的指令:new创建数组的指令:newarray,anewarray,multianewarray访问类字段(static字段,或者称为类变量)和实例字段(非static字段,或者成为实例变量)的指令:getfield、putfield、getstatic、putstatic把一个数组元素加载到操作数栈的指令:baload、caload、saload、iaload、laload、faload、daload、aaload将一个操作数栈的值储存到数组元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore取数组长度的指令:arraylength检查类实例类型的指令:instanceof、checkcast
操作数栈管理指令:
Java虚拟机提供了一些用于直接操作操作数栈的指令,包括:pop、pop2、dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2和swap;
控制转移指令:
条件分支:ifeq、iflt、ifle、ifne、ifgt、ifge、ifnull、ifnonnull、if_icmpeq、if_icmpne、if_icmplt, if_icmpgt、if_icmple、if_icmpge、if_acmpeq和if_acmpne。复合条件分支:tableswitch、lookupswitch无条件分支:goto、goto_w、jsr、jsr_w、ret
方法调用和返回指令:
invokevirtual指令用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),这也是Java语言中最常见的方法分派方式。invokeinterface指令用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法(§2.9)、私有方法和父类方法。invokestatic指令用于调用类方法(static方法)。而方法返回指令则是根据返回值的类型区分的,包括有ireturn(当返回值是boolean、byte、char、short和int类型时使用)、lreturn、freturn、dreturn和areturn,另外还有一条return指令供声明为void的方法、实例初始化方法、类和接口的类初始化方法使用
抛出异常指令:
athrow
备注:
在非静态方法中,aload_0 表示将this 加载到操作数栈
在static 方法中,aload_0表示将方法中地第一个参数(局部变量表中的第一位),加载到操作数栈中。
参考:
http://www.yangyong.me/java-class%E6%96%87%E4%BB%B6%E5%92%8C%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4-%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8Bclass%E6%96%87%E4%BB%B6/
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
- javap 与字节码指令
- 关于Java虚拟机中的字节码指令javap
- Eclipse中使用javap命令打出字节码虚指令
- javap -c 字节码含义
- javap指令
- javap生成的字节码的意思
- javap反编译和查看字节码文件
- class文件字节码分析工具:javap
- 使用javap命令查看字节码
- 使用javap反编译Java字节码文件
- 使用javap反编译Java字节码文件
- javap 反编译Java class字节码
- javap反编译java字节码文件
- Javap查看Class指令
- Javap查看Class指令
- javap反编译指令
- Javap查看Class指令
- 类分解器JavaP--分析Java字节码
- 淘淘商城系列——首页跳转到搜索页面
- Linux下ll输出后用grep搜索注意
- html一些基础标签
- 如何给jqGrid表格按照字段进行分组
- python入门基础语法
- javap 与字节码指令
- 《数据结构学习与实验指导》2-7:素因子分解
- progressbar
- RTP/RTCP协议介绍
- (OK) ip-str.c
- B-1014
- 将独立 的mongod数据库转换成副本模式,可以只需要一台机器一个实例
- python实时得到鼠标的位置
- 基于Unity3D(UGUI)的背包系统<四>完结篇