JVM的字节码

JVM中字节码的基本指令

1.加载或存储指令

  • 将局部变量加载到操作栈中。如ILOAD(将int类型的局部变量压入栈)和ALOAD(将对象引用的局部变量压入栈)
  • 从操作栈顶存储到局部变量表。如ISTORE、ASTORE等
  • 将常量加载到操作栈顶,高频的指令。如ICONST、BIPUSH、SIPUSH、LDC等,ICONST加载的是-1~5的数,BIPUSH,即Byte Immediate PUSH,加载-128~127之间的数,即short,加载-32768~32767之间的数;LDC即Load constant,在-2147483648~2147483647或者是字符串时,JVM采用LDC指令压入栈中。

2.运算指令

    对两个操作栈帧上的值进行运算,并把结果写入操作栈顶,如IADD,IMUL等

3.类型转换指令

   显示转换两种不同的数值类型。如I2L、D2F等

4.对象创建与访问指令

   根据类进行对象的创建、初始化、方法调用相关指令

  1. 创建对象指令。如NEW、NEWARRAY等
  2. 访问属性指令。如GETFIFELF、PUTFIFLD、GETSTATIC等
  3. 检查实例类型指令。如ISTANCEOF、CHECKCAST等

5.操作栈管理指令

   JVM提供了直接控制操作栈的指令

  1. 出栈操作。如POP即一个元素,POP2即两个元素
  2. 复制栈顶元素并压入栈。如DUP

6.方法调用与返回指令

    常见指令如下:

  1. INVOKEVIRTUAL指令:调用对象的实例方法
  2. INVOKESPECIAL指令:调应实例初始化方法、私有方法、父类方法
  3. INVOKESTATIC指令:调用类静态方法
  4. RETURN指令:返回VOID类型

7.同步指令

   JVM使用方法结构中的ACC_SYNCHRONIZED标识同步方法,指令集中有MONITORENTER和MONITOREXOT支持synchronized语义


静态编译器如何把源码转化成字节码

java源文件----词法解析----token流----语法解析(将token流按照java语法规则组装成语法树)------语义分析(检查关键字的使用是否合理,类型是否匹配,作用域是否正确)------生成字节码

字节码必须通过类加载过程加载到JVM环境后方可执行。执行有三种模式:第一,解释执行,即逐条将字节码翻译成机器码并执行;第二,JIT编译执行,即将一个方法中包含的所有字节码编译成机器码后再执行;第三,JIT编译与解释混合执行(HOTPLOT).前者优势在于无需等待编译,而后者优势在于实际运行速度更快。混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间,jvm通过热点代码统计分析,识别高频的方法调用、循环体、公共模块等,基于强大的JIT动态编译技术,将热点代码转换成机器码,直接交给cpu执行。JIT的作用是将java字节码动态地编译成可以直接发送给处理器指令执行的机器码。

注意:机器自爱热机状态可以承受的负载要大于冷机状态(刚启动时),如以热机状态的流量进行切换,可能使冷机状态的服务器因无法承载流量而假死。在生产环境发布过程中,以分批的方式进行发布。

Java虚拟机具体是怎样运行java字节码的?

从虚拟机视角看,执行Java代码首先需要将它编译的class文件加载到虚拟机中,加载后的Java类会被存放于方法区中,实际运行时,虚拟机会执行方法区内的代码。

 在运行过程中,每当调用进入一个Java方法,Java虚拟机会在当前线程的Java方法栈中生成一个栈帧,用以存放局部变量以及字节码的操作数,栈帧大小是提前计算好的,Java虚拟机不要求栈帧在内存空间里连续分布,当退出当前执行的方法时,不管正常返回还是异常返回,Java虚拟机都会弹出当前线程的当前栈帧,并将之舍弃。