JVM系列之七:字节码执行

时间:2022-05-01 17:33:05

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

 JVM系列之七:字节码执行

 

200压人操作数栈,然后将操作数栈弹出到Int型变量2

 JVM系列之七:字节码执行

 

 

50压人操作数栈,然后将操作数栈弹出到Int型变量3

 JVM系列之七:字节码执行

Int型变量1的值加载到操作数栈,将Int型变量2的值加载到操作数栈

 JVM系列之七:字节码执行

对操作数栈里面的值做整数的加法操作,之后将Int型变量3的值加载到操作数栈

 JVM系列之七:字节码执行

对操作数栈里面的值做整数的除法操作,将操作数栈里的值作为方法的返回值返回

 JVM系列之七:字节码执行

常用的字节码

常量入栈

– 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(xi l f d a)

· 分别表示intlongfloatdoubleobject ref

– xload_n(n0 1 2 3)

– xaload(xi l f d a b c s)

· 分别表示int, long, float, double, obj ref ,byte,char,short

n 从数组中取得给定索引的值,将该值压栈

· iaload

· 执行前,栈:..., arrayref, index

· 它取得arrayref所在数组的index的值,并将值压栈

· 执行后,栈:..., value

出栈装载入局部变量

– xstore(xi l f d a)

· 出栈,存入局部变量

– xstore_n(n 0 1 2 3)

· 出栈,将值存入第n个局部变量

– xastore(xi 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   如果小于,则跳转

– ifge  如果大于0,则跳转

– if_icmpeq 如果两个int相同,则跳转

 

方法调用

– invokevirtual

– invokespecial

– invokestatic

– invokeinterface

– xreturn(x为 i l f d a 或为空)

 

JIT及其相关参数

· 字节码执行性能较差,所以可以对于热点代码编译成机器码再执行,在运行时的编译,叫做JIT Just-In-Time

· JIT的基本思路是,将热点代码,就是执行比较频繁的代码,编译成机器码。

 JVM系列之七:字节码执行

JIT

当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为“Hot Spot Code”(热点代码),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码)

热点代码

调用的方法。被多次调用的循环体。

两个计数器

方法调用计数器:方法调用次数

回边计数器:方法内循环次数

相关参数

– -XX:CompileThreshold=1000

· 通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码。

· 默认值为1000

– -Xint

· 解释执行

– -Xcomp

· 全部编译执行

– -Xmixed

默认,混合