Javap
– class文件反汇编工具
– javap –verbose Calc
java 文件
public class Calc {
public int calc() {
int a = 500;
int b = 200;
int c = 50;
return (a + b) / c;
}
}
编译后Class文件
public int calc();
Code:
Stack=2, Locals=4, Args_size=1
0: sipush 500
3: istore_1
4: sipush 200
7: istore_2
8: bipush 50
10: istore_3
11: iload_1
12: iload_2
13: iadd
14: iload_3
15: idiv
16: ireturn
}
简单的字节码执行过程
以上节的例子为例:
首先将500压人操作数栈,然后将操作数栈弹出到Int型变量1
将200压人操作数栈,然后将操作数栈弹出到Int型变量2
将50压人操作数栈,然后将操作数栈弹出到Int型变量3
将Int型变量1的值加载到操作数栈,将Int型变量2的值加载到操作数栈
对操作数栈里面的值做整数的加法操作,之后将Int型变量3的值加载到操作数栈
对操作数栈里面的值做整数的除法操作,将操作数栈里的值作为方法的返回值返回
常用的字节码
常量入栈
– aconst_null null对象入栈
– iconst_m1 int常量-1入栈
– iconst_0 int常量0入栈
– iconst_5
– lconst_1 long常量1入栈
– fconst_1 float 1.0入栈
– dconst_1 double 1.0 入栈
– bipush 8位带符号整数入栈
– sipush 16位带符号整数入栈
– ldc 常量池中的项入栈
局部变量压栈
– xload(x为i l f d a)
· 分别表示int,long,float,double,object ref
– xload_n(n为0 1 2 3)
– xaload(x为i l f d a b c s)
· 分别表示int, long, float, double, obj ref ,byte,char,short
n 从数组中取得给定索引的值,将该值压栈
· iaload
· 执行前,栈:..., arrayref, index
· 它取得arrayref所在数组的index的值,并将值压栈
· 执行后,栈:..., value
出栈装载入局部变量
– xstore(x为i l f d a)
· 出栈,存入局部变量
– xstore_n(n 0 1 2 3)
· 出栈,将值存入第n个局部变量
– xastore(x为i l f d a b c s)
· 将值存入数组中
· iastore
· 执行前,栈:...,arrayref, index, value
· 执行后,栈:...
· 将value存入arrayref[index]
通用栈操作(无类型)
– Nop
· 空指令
– pop
· 弹出栈顶1个字长
– dup
· 复制栈顶1个字长,复制内容压入栈
类型转化(举例)
– i2l
· 将int转为long
· 执行前,栈:..., value
· 执行后,栈:...,result.word1,result.word2
· 弹出int,扩展为long,并入栈
– i2f
– l2i
– l2f
– l2d
– f2i
– f2d
整数运算
– iadd
– ladd
– isub
– lsub
– idiv
– ldiv
– imul
– lmul
– iinc
浮点运算
– fadd
– dadd
– fsub
– dsub
– fdiv
– ddiv
– fmul
– dmul
对象操作指令
– new
– getfield
– putfield
– getstatic
– putstatic
条件控制
– ifeq 如果为0,则跳转
· 参数 byte1,byte2
· value出栈 ,如果栈顶value为0则跳转到(byte1<<8)|byte2
· 执行前,栈:...,value
· 执行后,栈:...
– ifne 如果不为0,则跳转
– iflt 如果小于0 ,则跳转
– ifge 如果大于0,则跳转
– if_icmpeq 如果两个int相同,则跳转
方法调用
– invokevirtual
– invokespecial
– invokestatic
– invokeinterface
– xreturn(x为 i l f d a 或为空)
JIT及其相关参数
· 字节码执行性能较差,所以可以对于热点代码编译成机器码再执行,在运行时的编译,叫做JIT Just-In-Time
· JIT的基本思路是,将热点代码,就是执行比较频繁的代码,编译成机器码。
JIT
当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为“Hot Spot Code”(热点代码),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码)
热点代码
调用的方法。被多次调用的循环体。
两个计数器
方法调用计数器:方法调用次数
回边计数器:方法内循环次数
相关参数
– -XX:CompileThreshold=1000
· 通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码。
· 默认值为1000
– -Xint
· 解释执行
– -Xcomp
· 全部编译执行
– -Xmixed
默认,混合