字节码指令

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)构成。Java虚拟机采用面向操作数栈而不是面向寄存器的架构,所以大多数指令都不包含操作数,只有一个操作码。
Java虚拟机操作码长度限制为一个字节(0-255),并且Class文件格式放弃类编译后代码的操作数长度对齐。所以虚拟机处理那些超过一个字节数据的时候,不得不在运行时从字节中重建出具体的数据的结构。这种操作会导致解释执行字节码时损失一些性能,但是这样意味着节省很多填充和间隔符号,编译代码也更加短小精干。这也是因为Java最初设计是面向网络、智能家电的技术背景,并且一直沿用至今。现在的网络带宽相比几十年前已经扩宽了很多倍,本地的计算性能也提高了无数倍。那现在这个思想是否还需要继续保持呢?在56k拨号上网、386的时代Java虚拟机针对编译时的优化或许决定了应用的成败,但是在现在5G和16甚至32核服务器以及Java虚拟机自身的发展与优化,常见的问题主要就是OOM了。

字节码与数据类型

Java虚拟机的指令集中,大多数指令都包含了其操作对应的数据类型,记得刚才说过操作码长度只有一个字节,意味着操作码总数不能超过256条。Java虚拟机支持的数据类型包含8种(byte,short,int,long,float,double,char,reference),大部分指令都不支持byte、short、和char,甚至没有任何指令支持boolean。编译期会在编译期或运行期将byte和short的数据带符号、boolean和char数据零位扩展为int类型。
指令中包含例如 const、load指令,针对int、long、float、double、reference分别为:iconst,lconst,fconst,dconst,aconst;iload、lload、fload、dload、aload。

加载和存储指令

load相关指令将一个局部变量加载到操作栈。
store相关指令将一个数值从操作数栈存储到局部变量表。
push、const相关指令将一个常量加载到操作数栈。
扩充局部变量表的访问索引的指令:wide。

运算指令

运算指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶,大体分为两种:整型数据运行指令与浮点型数据进行运算指令。
所有指令包括:加(add),减(sub),乘(mul),除(div),求余(rem),取反(neg),位移(shl,shr),按位或(or),按位与(and),按位异或(xor),局部变量自增(inc),比较(cmp)

类型转换指令

无需显式转换,宽化类型转换(小范围向大范围的安全转换):int到long、float、double;long到float、double;float到double;
需要显示转换,窄化类型转换:int到byte、char、short;long到int;float到int、long;double到int、long、float;
Java虚拟机规范中明确规定数值类型的窄化转换指令永远不可能导致虚拟机抛出运行时异常。

对象创建与访问指令

创建类实例的指令:new
访问类字段:getfield、putfield、getstatic、putstatic
检查类实例类型:instanceof、checkcast

创建数组:newarray、anewarray、multianewarray
加载数组元素到操作数栈:aload相关
将操作数栈的值存储到数组元素中的指令:astore
取数据长度:arraylength

操作数栈管理指令

将操作数栈顶一个或两个元素出栈:pop,pop2
复制栈顶元素的数值并且压入栈顶:dup、dup_x等相关
栈顶两个数值互换:swap

控制转移指令

控制转移指令可以让Java虚拟机有条件或者无条件从指定位置指令而不是下一条指令继续执行程序。从概念模型上理解,可以认为控制转移指令是在有条件或无条件的修改PC寄存器的值。
条件分支:if相关(ifeq、iflt、ifnotnull等)
复合条件分支:switch(tableswitch,lookupswitch)
无条件分支:goto,jsr(goto、goto_w、jsr、jsr_w、ret)
由于各种数据类型的比较最终都会转换为int进行比较,所以int类型的条件分支指令时最为丰富和强大的。

方法调用和返回指令

invokevirtual用于调用对象的实例方法,最常见的用法。
invokeinterface用于调用接口方法。
invokespecial用于调用特殊处理的实例方法,如实例初始化方法、私有方法、父类方法。
invokestatic用于调用静态方法。
invokedynamic用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法。
方法调用指令与数据类型无关,返回指令与数据类型有关。
指令包括:ireturn(返回值时boolean、byte、char、short、int时使用)、lreturn、freturn、dreturn、areturn、return(返回值void,实例初始化方法、类和接口的类初始化方法使用)。

异常处理指令

异常抛出都有athrow指令实现。
处理异常(catch语句)不是有字节码指令来实现的(很久之前曾经使用jsr和ret指令,现在已经不用了),而是采用异常表来完成的。

同步指令

Java中的同步关键字为synchronized语句块,指令集中有monitorenter和monitorexit两条指令支持。

Java虚拟机-字节码指令的更多相关文章

  1. 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性

    我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...

  2. java虚拟机字节码执行引擎

    定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...

  3. Java虚拟机--字节码指令集

    1. 字节码指令集简介: Java虚拟机的指令由一个字节长度的,代表着某种特定操作含义的操作码(Opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(Operands)所构成.虚拟机中许多指 ...

  4. Java虚拟机-字节码执行引擎

    概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...

  5. 虚拟机字节码指令表 JVM

    虚拟机字节码指令表 标签(空格分隔): Java基础 JVM 记录虚拟机字节码指令,方便分析.以下内容来自<深入理解Java虚拟机> 字节码 助记符 指令含义 0x00 nop 什么都不做 ...

  6. 第32篇-解析interfacevirtual字节码指令

    在前面介绍invokevirtual指令时,如果判断出ConstantPoolCacheEntry中的_indices字段的_f2属性的值为空,则认为调用的目标方法没有连接,也就是没有向Constan ...

  7. 第34篇-解析invokeinterface字节码指令

    与invokevirtual指令类似,当没有对目标方法进行解析时,需要调用LinkResolver::resolve_invoke()函数进行解析,这个函数会调用其它一些函数完成方法的解析,如下图所示 ...

  8. [四] java虚拟机JVM编译器编译代码简介 字节码指令实例 代码到底编译成了什么形式

      前言简介   前文已经对虚拟机进行过了简单的介绍,并且也对class文件结构,以及字节码指令进行了详尽的说明 想要了解JVM的运行机制,以及如何优化你的代码,你还需要了解一下,java编译器到底是 ...

  9. 深入理解java虚拟机(六)字节码指令简介

    Java虚拟机指令是由(占用一个字节长度.代表某种特定操作含义的数字)操作码Opcode,以及跟随在其后的零至多个代表此操作所需参数的称为操作数 Operands 构成的.由于Java虚拟机是面向操作 ...

随机推荐

  1. Failure to transfer org.springframework:spring-jcl:jar:5.0.7.RELEASE from

    错误信息: Failure to transfer org.springframework.boot:spring-boot-maven-plugin:pom:1.5.4.RELEASE from h ...

  2. js二次作业

    task 1:完成省城市的三级联动(包括湖南省),附代码和效果图.<!DOCTYPE html> <html> <head> <title>完成省城市的 ...

  3. Cobalt Strike之信息收集、木马钓鱼

    System Profiler使用 System Profiler 模块,搜集目标的各类机器信息(操作系统版本,浏览器版本等) Attacks->web drive-by->System ...

  4. JVM 中发生内存溢出的 8 种原因及解决办法

    1. Java 堆空间 2. GC 开销超过限制 3. 请求的数组大小超过虚拟机限制 4. Perm gen 空间 5. Metaspace 6. 无法新建本机线程 7. 杀死进程或子进程 8. 发生 ...

  5. PHP代码审计基础-高级篇

    高级篇主要讲 1. 熟知各个开源框架历史版本漏洞. 2. 业务逻辑漏洞 3. 多线程引发的漏洞 4. 事务锁引发的漏洞 在高级篇审计中有很多漏洞正常情况下是不存在的只有在特殊情况下才有 PHP常用框架 ...

  6. vue系列文章 --- 源码目录结构整理(三)

    vue的版本是:^2.6.10 结构如下: |----- vue | |--- dist # 打包之后的目录vue文件 | | |--- vue.common.dev.js | | |--- vue. ...

  7. [UWP]使用GetAlphaMask制作阴影

    1. 前言 最近常常接触到GetAlphaMask,所以想写这篇文章介绍下GetAlphaMask怎么使用.其实GetAlphaMask的使用场景十分有限,Github上能搜到的内容都是用来配合Dro ...

  8. windows设置本地域名解析

    1.首先找到host文件:C:\Windows\System32\drivers\etc 2.打开host文件: # Copyright (c) 1993-2009 Microsoft Corp. # ...

  9. 变量 + 数据类型(数字 + 字符串)(day03整理)

    目录 一.上节课回顾 四 编程语言分类 (一) 机器语言 (二)汇编语言 (三) 高级语言 (四) 网络瓶颈效应 五.执行python程序两种方式 (一) 交互式(jupytre) (二) 命令行式( ...

  10. (记录)Jedis存放对象和读取对象--Java序列化与反序列化

    一.理论分析 在学习Redis中的Jedis这一部分的时候,要使用到Protostuff(Protobuf的Java客户端)这一序列化工具.一开始看到序列化这些字眼的时候,感觉到一头雾水.于是,参考了 ...