Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >原 JVM基础命令

原 JVM基础命令

作者头像
石奈子
发布于 2018-06-13 07:28:09
发布于 2018-06-13 07:28:09
8060
举报

介绍java虚拟机的指令功能,至少能阅读java代码生成的字节码指令含义

一、概述

Java虚拟机采用基于栈的架构,其指令由操作码和操作数组成。

  • 操作码:一个字节长度(0~255),意味着指令集的操作码个数不能操作256条。
  • 操作数:一条指令可以有零或者多个操作数,且操作数可以是1个或者多个字节。编译后的代码没有采用操作数长度对齐方式,比如16位无符号整数需使用两个字节储存(假设为byte1和byte2),那么真实值是 (byte1 << 8) | byte2。

放弃操作数对齐操作数对齐方案:

  • 优势:可以省略很多填充和间隔符号,从而减少数据量,具有更高的传输效率;Java起初就是为了面向网络、智能家具而设计的,故更加注重传输效率。
  • 劣势:运行时从字节码里构建出具体数据结构,需要花费部分CPU时间,从而导致解释执行字节码会损失部分性能。

二、指令

大多数指令包含了其操作所对应的数据类型信息,比如iload,表示从局部变量表中加载int型的数据到操作数栈;而fload表示加载float型数据到操作数栈。由于操作码长度只有1Byte,因此Java虚拟机的指令集对于特定操作只提供有限的类型相关指令,并非为每一种数据类型都有相应的操作指令。必要时,有些指令可用于将不支持的类型转换为可被支持的类型。

对于byte,short,char,boolean类型,往往没有单独的操作码,通过编译器在编译期或者运行期将其扩展。对于byte,short采用带符号扩展,chart,boolean采用零位扩展。相应的数组也是采用类似的扩展方式转换为int类型的字节码来处理。 下面分门别类来介绍Java虚拟机指令,都以int类型的数据操作为例。

栈是指操作数栈

2.1 栈操作相关

load和store

  • load 命令:用于将局部变量表的指定位置的相应类型变量加载到栈顶;
  • store命令:用于将栈顶的相应类型数据保入局部变量表的指定位置;

变量进栈

含义

变量保存

含义

iload

第1个int型变量进栈

istore

栈顶nt数值存入第1局部变量

iload_0

第1个int型变量进栈

istore_0

栈顶int数值存入第1局部变量

iload_1

第2个int型变量进栈

istore_1

栈顶int数值存入第2局部变量

iload_2

第3个int型变量进栈

istore_2

栈顶int数值存入第3局部变量

iload_3

第4个int型变量进栈

istore_3

栈顶int数值存入第4局部变量

lload

第1个long型变量进栈

lstore

栈顶long数值存入第1局部变量

fload

第1个float型变量进栈

fstore

栈顶float数值存入第1局部变量

dload

第1个double型变量进栈

dstore

栈顶double数值存入第1局部变量

aload

第1个ref型变量进栈

astore

栈顶ref对象存入第1局部变量

const、push和ldc

  • const、push:将相应类型的常量放入栈顶
  • ldc:则是从常量池中将常量

常量进栈

含义

aconst_null

null进栈

iconst_m1

int型常量-1进栈

iconst_0

int型常量0进栈

iconst_1

int型常量1进栈

iconst_2

int型常量2进栈

iconst_3

int型常量3进栈

iconst_4

int型常量4进栈

iconst_5

int型常量5进栈

lconst_0

long型常量0进栈

fconst_0

float型常量0进栈

dconst_0

double型常量0进栈

bipush

byte型常量进栈

sipush

short型常量进栈

常量池操作

含义

ldc

int、float或String型常量从常量池推送至栈顶

ldc_w

int、float或String型常量从常量池推送至栈顶(宽索引)

ldc2_w

long或double型常量从常量池推送至栈顶(宽索引)

pop和dup

  • pop用于栈顶数值出栈操作;
  • dup用于赋值栈顶的指定个数的数值,并将其压入栈顶指定次数;

栈顶操作

含义

pop

栈顶数值出栈(不能是long/double)

pop2

栈顶数值出栈(long/double型1个,其他2个)

dup

复制栈顶数值,并压入栈顶

dup_x1

复制栈顶数值,并压入栈顶2次

dup_x2

复制栈顶数值,并压入栈顶3次

dup2

复制栈顶2个数值,并压入栈顶

dup2_x1

复制栈顶2个数值,并压入栈顶2次

dup2_x2

复制栈顶2个数值,并压入栈顶3次

swap

栈顶的两个数值互换,且不能是long/double

注意:dup2对于long、double类型的数据就是一个,对于其他类型的数据,才是真正的两个,这个的2代表的是2个slot的数据。

2.2 对象相关

字段调用

字段调用

含义

getstatic

获取类的静态字段,将其值压入栈顶

putstatic

给类的静态字段赋值

getfield

获取对象的字段,将其值压入栈顶

putfield

给对象的字段赋值

方法调用

方法调用

作用

解释

invokevirtual

调用实例方法

虚方法分派

invokestatic

调用类方法

static方法

invokeinterface

调用接口方法

运行时搜索合适方法调用

invokespecial

调用特殊实例方法

包括实例初始化方法、父类方法

invokedynamic

由用户引导方法决定

运行时动态解析出调用点限定符所引用方法

方法返回

方法返回

含义

ireturn

当前方法返回int

lreturn

当前方法返回long

freturn

当前方法返回float

dreturn

当前方法返回double

areturn

当前方法返回ref

对象和数组

  • 创建类实例: new
  • 创建数组:newarray、anewarray、multianewarray
  • 数组元素 加载到 操作数栈:xaload (x可为b,c,s,i,l,f,d,a)
  • 操作数栈的值 存储到数组元素: xastore (x可为b,c,s,i,l,f,d,a)
  • 数组长度:arraylength
  • 类实例类型:instanceof、checkcast

2.3 运算指令

运算指令是用于对操作数栈上的两个数值进行某种运算,并把结果重新存入到操作栈顶。Java虚拟机只支持整型和浮点型两类数据的运算指令,所有指令如下:

运算

int

long

float

double

加法

iadd

ladd

fadd

dadd

减法

isub

lsub

fsub

dsub

乘法

imul

lmul

fmul

dmul

除法

idiv

ldiv

fdiv

ddiv

求余

irem

lrem

frem

drem

取反

ineg

lneg

fneg

dneg

其他运算:

  • 位移:ishl,ishr,iushr,lshl,lshr,lushr
  • 按位或: ior,lor
  • 按位与: iand, land
  • 按位异或: ixor, lxor
  • 自增:iin
  • 比较:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

2.4 类型转换

类型转换用于将两种不同类型的数值进行转换。

(1) 对于宽化类型转换(小范围向大范围转换),无需显式的转换指令,并且是安全的操作。各种范围从小到大依次排序: int, long, float, double。

(2)对于窄化类型转换,必须显式地调用类型转换指令,并且该过程很可能导致精度丢失。转换规则中需要特别注意的是当浮点值为NaN, 则转换结果为int或long的0。虽然窄化运算可能会发生上/下限溢出和精度丢失等情况,但虚拟机规范明确规定窄化转换U不可能导致虚拟机抛出异常。

类型转换指令:i2b, i2c,f2i等等。

2.5 流程控制

控制指令是指有条件或无条件地修改PC寄存器的值,从而达到控制流程的目标

  • 条件分支:ifeq、iflt、ifnull、ifnonnull等
  • 复合分支:tableswitch、lookupswitch
  • 无条件分支:goto、goto_w、jsr、jsr_w、ret

2.6 同步与异常

异常:

Java程序显式抛出异常: athrow指令。在Java虚拟机中,处理异常(catch语句)不是由字节码指令来实现,而是采用异常表来完成。

同步:

方法级的同步和方法内部分代码的同步,都是依靠管程(Monitor)来实现的。

Java语言使用synchronized语句块,那么Java虚拟机的指令集中通过monitorenter和monitorexit两条指令来完成synchronized的功能。为了保证monitorenter和monitorexit指令一定能成对的调用(不管方法正常结束还是异常结束),编译器会自动生成一个异常处理器,该异常处理器的主要目的是用于执行monitorexit指令。

2.7 小结

在基于堆栈的的虚拟机中,指令的主战场便是操作数栈,除了load是从局部变量表加载数据到操作数栈以及store储存数据到局部变量表,其余指令基本都是用于操作数栈的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JVM 常用指令速查手册,建议收藏!
昨天在群里闲聊技术,提到了反编译和指令码。对于反编译和 JVM 的几个指令我解释了它们的各自所包含的意义。有人就问我,我是如何记住的。其实我也没记住这些指令,只不过,我总结了一个 JVM 常用指令速查手册,今天分享给大家!
业余草
2020/02/14
1K0
初识jvm运行java代码
指令集,其实就是一系列指令的集合。例如我们需要给一个局部变量赋予1这个值,即这个动作:int a = 1; 在我们看来,这很简单,但对于机器来说需要很多个动作。所以Java虚拟机指令集就是将这些常用的动作集中起来,定义成一系列指令,方便我么能使用。
全栈程序员站长
2022/08/05
5570
初识jvm运行java代码
[三] java虚拟机 JVM字节码 指令集 bytecode 操作码 指令分类用法 助记符
计算机指令就是指挥机器工作的指示和命令,程序就是一系列按一定顺序排列的指令,执行程序的过程就是计算机的工作过程。
noteless
2018/09/11
9.1K0
[三] java虚拟机 JVM字节码 指令集 bytecode 操作码 指令分类用法 助记符
[JVM] JVM自动内存管理机制(一)
文本主要就JVM结构和字节码文件,进行分析来展开JVM的学习,后续系列文章会从JVM的多个方面的进行知识总结。
架构探险之道
2019/09/09
5270
[JVM] JVM自动内存管理机制(一)
JVM 字节码指令表
字节码 助记符 指令含义 0x00 nop 什么都不做 0x01 aconst_null 将 null 推送至栈顶 0x02 iconst_m1 将 int 型 -1 推送至栈顶 0x03 iconst_0 将 int 型 0 推送至栈顶 0x04 iconst_1 将 int 型 1 推送至栈顶 0x05 iconst_2 将 int 型 2 推送至栈顶 0x06 iconst_3 将 int 型 3 推送至栈顶 0x07 iconst_4 将 int 型 4 推送至栈顶 0x08 iconst_5 将
兜兜毛毛
2019/10/23
1.8K0
JVM指令集及各指令的详细使用说明
一、JVM指令助记符 1)操作数栈 变量到操作数栈:iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_ 操作数栈到变量:istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_ 常数到操作数栈:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,
汤高
2018/03/28
2.2K0
JVM学习第三天(JVM的执行子系统)之字节码指令
早上看了Class类文件结构,晚上继续来看字节码指令,毕竟谁也不是一步登天的(说白了还是穷);
彼岸舞
2020/09/30
5390
Java字节码 顶
Java字节码对于虚拟机,就好像汇编语言对于计算机,属于基本执行指令。每一个Java字节码指令是一个byte数字,并且有一个对应的助记符。
算法之名
2020/05/26
8070
JVM指令的速记
在学习的JVM的时候,最重要的是认识JVM的指令,JVM指令很多,为了方便记忆,可以根据前缀和功能进行分类:
付威
2020/05/06
1.1K0
jvm之字节码指令集解读(上)
Java字节码指令集是一组计算机指令,用于在Java虚拟机上执行Java程序。这些指令编码了操作码、操作数和控制信息,可以用于执行Java语言程序的所有操作,如变量赋值、方法调用、控制流与异常处理等。Java字节码指令集可以直接被Java虚拟机读取和解释,并且保证了Java程序在不同平台上的可移植性。
一个风轻云淡
2023/10/15
3510
jvm之字节码指令集解读(上)
Javap -c 字节码解析
栈和局部变量操作 将常量压入栈的指令 aconst_null         将null对象引用压入栈 iconst_m1         将int类型常量-1压入栈 iconst_0         将int类型常量0压入栈 iconst_1         将int类型常量1压入栈 iconst_2         将int类型常量2压入栈 iconst_3         将int类型常量3压入栈 iconst_4         将int类型常量4压入栈 iconst_5         将int类
房上的猫
2018/05/17
7040
【JVM进阶之路】十二:字节码指令
在前面的 【JVM进阶之路】三:探究虚拟机对象 里,提到了对象的初始化过程,对象初始化用的是new指令——这就是字节码指令。在【JVM进阶之路】十一:Class文件结构 中已经学习了JVM 字节码是JVM能直接识别的语言,了解了字节码文件的文件结构。接下来,我们进一步学习字节码的相关指令。
三分恶
2021/05/18
8670
【JVM进阶之路】十二:字节码指令
从JAVA字节码到方法运行
很简单的两行代码,如果是你遇到这样的问题,你会怎样去把问题解释清楚?是利用Java运算符顺序将式子拆解,然后一步步运算,还是其他什么办法?在思索一会儿之后,决定还是通过字节码指令来看看这两行代码是怎么运行的。
叫我阿柒啊
2022/05/09
4870
从JAVA字节码到方法运行
如何从字节码角度分析Java问题
很简单的两行代码,如果是你遇到这样的问题,你会怎样去把问题解释清楚?是利用Java运算符顺序将式子拆解,然后一步步运算,还是其他什么办法?
叫我阿柒啊
2022/05/09
5840
如何从字节码角度分析Java问题
jvm之类文件详解(四)
Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何 分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。 当遇到需要占用 8 位字节以上空间的数据项时,则会按照高位在前(Big-Endian)的方式分割成若干个 8 位字节进行存储。 Class 文件只有两种数据类型:无符号数和表 链接:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
周杰伦本人
2022/10/25
2010
jvm之类文件详解(四)
JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器
字节码文件被装载子系统装载到JVM中,字节码执行引擎负责执行这些字节码文件。 装载子系统和执行引擎都是C++的实现。
小小工匠
2021/08/17
3510
字节码原理浅析 —— 基于栈的执行引擎
虚拟机常见的实现方式有两种:Stack based 的和 Register based。比如基于 Stack 的虚拟机有Hotspot JVM、.net CLR,这种基于 Stack 实现虚拟机是一种广泛的实现方法。而基于 Register 的虚拟机有 Lua 语言虚拟机 LuaVM 和 Google 开发的安卓虚拟机 DalvikVM。
架构狂人
2023/08/16
5690
字节码原理浅析 —— 基于栈的执行引擎
写Java不懂Java系列之加载和存储
很多Java工程师语法用的很666,但是真的让他说说Java是怎样编译运行的,我相信他会懵逼!!!
shysh95
2021/01/28
4250
写Java不懂Java系列之加载和存储
Java 字节码指令,让我发了疯疯疯!
听我说,听我说,学 Java 准没错,毕竟岗位多薪资高!但涌进来的人越多,就意味着越来越卷,要想不被卷到,就必须得疯狂的学习,学什么呢?Java 字节码指令就是一块硬骨头。
沉默王二
2021/04/23
4750
Java 字节码指令,让我发了疯疯疯!
动画:深度解析JVM运行时数据区 之 线程独占区
策划了很久了,一直在想用什么样的方式讲解知识点,能让大家一目了然,更容易的学到知识,并且还能加深记忆。思考良久,所以想到用动画的形式来展示。首次尝试,也希望大家多提出宝贵意见。后续可能会添加故事以及录音讲解的形式跟大家分享。
互扯程序
2020/05/19
1.2K0
相关推荐
JVM 常用指令速查手册,建议收藏!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文