Java虚拟机-字节码指令
字节码指令
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虚拟机-字节码指令的更多相关文章
- 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性
我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...
- java虚拟机字节码执行引擎
定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...
- Java虚拟机--字节码指令集
1. 字节码指令集简介: Java虚拟机的指令由一个字节长度的,代表着某种特定操作含义的操作码(Opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(Operands)所构成.虚拟机中许多指 ...
- Java虚拟机-字节码执行引擎
概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...
- 虚拟机字节码指令表 JVM
虚拟机字节码指令表 标签(空格分隔): Java基础 JVM 记录虚拟机字节码指令,方便分析.以下内容来自<深入理解Java虚拟机> 字节码 助记符 指令含义 0x00 nop 什么都不做 ...
- 第32篇-解析interfacevirtual字节码指令
在前面介绍invokevirtual指令时,如果判断出ConstantPoolCacheEntry中的_indices字段的_f2属性的值为空,则认为调用的目标方法没有连接,也就是没有向Constan ...
- 第34篇-解析invokeinterface字节码指令
与invokevirtual指令类似,当没有对目标方法进行解析时,需要调用LinkResolver::resolve_invoke()函数进行解析,这个函数会调用其它一些函数完成方法的解析,如下图所示 ...
- [四] java虚拟机JVM编译器编译代码简介 字节码指令实例 代码到底编译成了什么形式
前言简介 前文已经对虚拟机进行过了简单的介绍,并且也对class文件结构,以及字节码指令进行了详尽的说明 想要了解JVM的运行机制,以及如何优化你的代码,你还需要了解一下,java编译器到底是 ...
- 深入理解java虚拟机(六)字节码指令简介
Java虚拟机指令是由(占用一个字节长度.代表某种特定操作含义的数字)操作码Opcode,以及跟随在其后的零至多个代表此操作所需参数的称为操作数 Operands 构成的.由于Java虚拟机是面向操作 ...
随机推荐
- javascript生成规定范围的随机整数
Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选择的数,在该范围内(近似)均匀分布. 我 ...
- Ubuntu分区方案
swap: 4G(跟你自己内存一样大):主分区:空间起始位置:用于交换空间 /boot: 300M(太小会导致软件无法升级):逻辑分区:空间起始位置:EXT4:/boot /: 30G:主分区:空间起 ...
- python学习(内置函数)
1.id()返回对象的内存地址 a = 1 print id(a) print id(1) 2.int()用于将数据类型转换为整型 a = " b = 2 print int(a) + b ...
- Java学习笔记之面向对象
面向对象概念 面向对象编程 &面向过程编程 面向对象:关心是谁来做 面向过程:关心的是怎么做 面向对象总结成一句话:就是分工与协作,干活的是对象 生活中: 对象 -----抽象-------- ...
- 【Python秘籍】numpy到tensor的转换
在用pytorch训练神经网络时,我们常常需要在numpy的数组变量类型与pytorch中的tensor类型进行转换,今天给大家介绍一种它们之间互相转换的方法. 一.numpy到tensor 首先我们 ...
- 小白学 Python(6):基础运算符(下)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...
- VAD树结构体的属性以及遍历
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html VAD树的属性以及遍历 前面学习过的PFNDATABSAE是管理物 ...
- netty源码解析(4.0)-26 ByteBuf内存池:PoolArena-PoolSubpage
PoolChunk用来分配大于或等于一个page的内存,如果需要小于一个page的内存,需要先从PoolChunk中分配一个page,然后再把一个page切割成多个子页-subpage,最后把内存以s ...
- Python的Argparse模块是什么?
近日在阅读代码的过程中遇到了Argparse模块,记得前段时间已经看了,可是过了两周现在又忘了, 看来写代码一定要钻研到底搞清楚其中原委才行,本文主要参考Python3.6系列官方文档 ...
- < 配置jupyer notebook遇到的问题 - 500 : Internal Server Error >
< anaconda配置jupyer notebook遇到的问题 - 500 : Internal Server Error > 问题描述: 我的jupyer notebook是在anac ...