java字节码指令简介(仅了解)

【0】README
0.1)本文全文转自 “深入理解jvm”, 旨在了解 java字节码指令 的基础知识;

【1】写在前面
1)由于jvm 采用面向操作数栈而不是寄存器的结构,所以大多数的指针都不包含操作数,只有一个操作码;
2)由于限制了jvm操作码的长度为一个字节(0~255),这意味着指令集的操作码总数不可能操作256个;

【2】字节码与数据类型
1)下表列举了jvm 所支持的与数据类型相关的字节码指令,通过使用数据类型列所代表的特殊字符替换opcode列的指令模板中的T,就可以得到一个具体的字节码指令。如果在表中指令模板与数据类型两列共同确定的格为空,则说明虚拟机不支持对这种数据类型;


【3】加载和存储指令
1)作用:用于将数据在栈帧中的局部变量表和操作数栈之间来回传输,这类指令包括如下内容:
  • 1.1)将一个局部变量加载到操作数栈:iload, iload_n, lload, lload_n, fload, fload_n, dload, dload_n, aload, aload_n;
  • 1.2)将一个数值从操作数栈存储到局部变量表:istore, istore_n, lstore_, lstore_n, fstore, fstore_n, dstore_, dstore_n, astore, astore_n;
  • 1.3)将一个常量加载到操作数栈: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_m1, iconst_i, lconst_l, fconst_f, dconst_d;
  • 1.4)扩充局部变量表的访问索引的指令:wide;
2)存储数据的操作数栈和局部变量表:主要就是由加载和存储指令进行操作;

【4】运算指令
1)作用:运算指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶;
2)算术指令汇总如下:
  • 2.1)加法指令:iadd, ladd, fadd, dadd;
  • 2.2)减法指令:isub, lsub, fsub, dsub; 
  • 2.3)乘法指令:imul, lmul, fmul, dmul;
  • 2.4)除法指令:idiv, ldiv, fdiv, ddiv; 
  • 2.5)求余指令:irem, lrem, frem, drem;
  • 2.6)取反指令:ineg, lneg, fneg, dneg;
  • 2.7)位移指令:ishl, ishr, iushr, lshl, lshr, lushr; 
  • 2.8)按位或指令:ior, lor;
  • 2.9)按位与指令:iand, land; 
  • 2.10)按位异或指令:ixor, lxor
  • 2.11)局部变量自增指令:iinc;
  • 2.12)比较指令:dcmpg, dcmpl, fcmpg, fcmpl, lcmp;
3)向最接近数舍入模式: jvm 要求在进行浮点数计算时, 所有的运算结果都必须舍入到适当的精度,非精确结果必须舍入为可被表示的最接近的精确值,如果有两种可表示的形式与该值一样接近,将优先选择最低有效位为零的;
4)向零舍入模式:将浮点数转换为整数时,采用该模式, 该模式将在目标数值类型中选择一个最接近但是不大于原值的数字作为最精确的舍入结果;
5)NaN值:当一个操作产生溢出时,将会使用有符号的无穷大表示,如果某个操作结果没有明确的数学定义的话,将会使用 NaN值来表示;而且所有使用NaN值作为操作数的算术操作,结果都会返回 NaN;(干货——这里提到了NaN值)

【5】类型转换指令
1)宽化类型转换:jvm 支持以下数值类型的宽化类型转换,即小范围类型向大范围类型的安全转换;
  • 1.1)int到long, float或double;
  • 1.2)long到float或double;
  • 1.3)float到double;
2)窄化类型转换:转换过程仅仅是丢弃除最低位N个字节外的内容, N是类型T 的数据类型长度,这将可能导致转换结果与输入值有不同的正负号;
3)将一个浮点值转换为int类型时,遵循如下的转换规则(rules):
  • r1)如果浮点值是NaN, 那转换结果是int 或 long类型的0;
  • r2)如果浮点值不是无穷大的话,浮点值使用 向零舍入模式取整,获得整数值v,且v在目标类型T(int或double)的表示范围内;
  • r3)否则,根据v的符号,转换为T所能表示的最大或最小整数;

【6】对象创建和访问指令
1)对象创建后,就可以通过对象访问指令获取对象实例或数组实例中的字段或者数组元素,这些指令(instruction)如下:
  • i1)创建类实例的指令:new;
  • i2)创建数组的指令:newarray, anewarray, multianewarray;
  • i3)访问类字段(static字段或称为类变量)和实例字段的指令: getfield, putfield, getstatic, putstatic;
  • i4)把一个数组元素加载到操作数栈的指令: baload, caload, saload, iaload, laload, faload, daload, aaload;
  • i5)将一个操作数栈的值存储到数组元素中的指令: bastore, castore, sastore, iastore, fastore, dastore, aastore;
  • i6)取数组长度指令: arrayLength;
  • i7)检查类实例类型的指令: instanceof, checkcast;
【7】操作数栈管理指令
1)如同操作一个普通数据结构中的堆栈那样,jvm提供了一些用于直接操作操作数栈的指令,包括:
  • 1.1)将一个或两个元素出栈: pop,pop2;
  • 1.2)复制栈顶一个或两个数值并将复制值或双份的复制值重新压入栈顶:dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2;
  • 1.3)将栈最顶端的两个数值交换: swap;
【8】控制转移指令
1)条件分支:ifeq, iflt, ifle, ifne, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge, if_acmpeq, if_acmpne;
2)复合条件分支:tableswitch, lookupswitch;
3)无条件分支:goto, goto_w, jsr, jsr_w, ret;

【9】方法调用和返回指令
1)方法调用指令
  • 1.1)invokevirtual:用于调用对象的实例方法, 根据对象的实际类型进行分派(虚方法分派),这也是java中最常见的方法分派方式;
  • 1.2)invokeinterface:用于调用接口方法, 它会在运行时搜索一个实现了这个接口方法的对象,找出合适的方法进行调用;
  • 1.3)invokespecial:用于调用一些需要特殊处理的实例方法, 包括实例初始化方法,私有方法和父类方法;
  • 1.4)invokestatic:用于调用类方法(static方法);
  • 1.5)invokedynamic:用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法,前面4条调用指令的分派逻辑都固化在 java 虚拟机内部,而 invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的;
2)返回指令(根据返回值的类型区分的),包括
  • 2.1)ireturn, lreturn, freturn, dreturn, areturn,另外还有一条return 指令供声明为 void 的方法,实例初始化方法以及类和接口的类初始化方法使用;
【10】异常处理指令
1)athrow指令;

【11】同步指令
1)java虚拟机支持两种同步结构:方法级的同步和 方法内部一段指令序列的同步,这两种同步都是使用管程(monitor)来支持的;
2)方法级的同步是隐式的: 即无须通过字节码指令来控制,它实现在方法调用和返回操作之中。虚拟机可以从方法常量池的方法表结构中的 ACC_SYNCHRONIZED 访问标志得知一个方法是否声明为同步方法;
3)synchronized语句块:同步一段指令集序列通常是由java 中的synchronized语句块来表示的,jvm的指令集有 monitorenter 和 monitorexit 两条指令来支持 synchronized关键字的语义;
4)看个荔枝:
// 测试 synchronized关键字的虚拟机指令集(字节码指令)
public class SynchronizedTest {public void func(CandyMachine machine) {synchronized (machine) {machine.count++;}}class CandyMachine {private int count = 0;public int getCount() {return count;}}
}

对以上代码的分析(Analysis):编译器必须确保无论方法通过何种方式完成,方法中调用过的每条 monitorenter指令都必须执行其对应的 monitorexit指令,而无论这个方法是正常ending 还是 异常ending;

【12】公有设计和私有实现
1)jvm 规范描述了jvm 应有的共同程序存储格式: Class 文件格式以及字节码指令集;
2)虚拟机实现的方式有两种(type):
  • type1)将输入的java虚拟机代码在加载或执行时翻译成另一种虚拟机的指令集;
  • type2)将输入的java虚拟机代码在加载或执行时翻译成宿主机CPU 的本地指令集, 即JIT代码生成技术(jit==just in time 即时)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是 CAS 机制

转载自 永远爱大家的 程序员小灰示例程序:启动两个线程,每个线程中让静态变量count循环累加100次。最终输出的count结果是什么呢?一定会是200吗?加了同步锁之后,count自增的操作变成了原子性操作,所以最终…

java xmpp_Java XMPP负载测试工具

java xmpp在本文中,我们将开发用Java编写的XMPP负载测试工具。 目录 1.简介 2. XMPP负载测试工具 3.先决条件 4. LoadXmppTest Java程序 4.1。 创建一个新的Maven项目 4.2。 创建主类 4.3。 XmppManager类 4.4。 建立 4.5。 负载测试 5.总结 6.参考 7.下载Maven项目…

jvm(7)-虚拟机类加载机制

【0】README0.1)本文转自“深入理解jvm”,旨在学习 虚拟机类加载机制 的基础知识;【1】概述1)类加载机制:虚拟机把描述类的数据从Class 文件加载到内存,并对数据进行校验,转换解析和初始化&…

什么是CAS机制?(进阶篇)

转载自 永远爱大家的 程序员小灰 这一期我们来深入介绍之前遗留的两个问题: Java当中CAS的底层实现 CAS的ABA问题和解决方法 首先看一看AtomicInteger当中常用的自增方法 incrementAndGet: public final int incrementAndGet() {for (;;) {int cur…

c++ 前缀 变量命名_前缀命名

c 前缀 变量命名如果您是第一次查看Takes或Cactoos的源代码,很可能会像其他命名约定一样被命名约定触发,这意味着大多数类名都有两个字母的前缀: BkSafe , RqFake , RsWithStatus , TkGzip等。 老实说&…

jvm(8)-虚拟机字节码执行引擎

【0】README0.1)本文转自 “深入理解jvm”,旨在学习 虚拟机字节码执行引擎 的基础知识;【1】概述1)物理机和虚拟机的执行引擎: 物理机的执行引擎是直接建立在处理器,硬件,指令集和操作系统层面上…

什么是大数据

转载自 玻璃猫 程序员小灰大数据是具有海量、高增长率和多样化的信息资产,它需要全新的处理模式来增强决策力、洞察发现力和流程优化能力。Big data is high volume, high velocity, and/or high variety information assets that require new forms of processing…

java 记录考勤记录_Java 14:记录

java 记录考勤记录Java 14是在几周前问世的,它引入了Record类型,它是一个不变的数据载体类,旨在容纳一组固定的字段。 请注意,这是一种预览语言功能 ,这意味着必须使用--enable-preview标志在Java编译器和运行时中显式…

漫画:什么是HashMap

转载自 玻璃猫 程序员小灰众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。 HashMap数组每一个元素的初始值都…

jvm(10)-早期(编译期)优化

【0】README 0.1)本文部分文字描述转自 “深入理解jvm”,旨在学习 早期(编译期)优化 的基础知识; 0.2)本文部分文字描述转自: http://www.cnblogs.com/zhouyuqin/p/5223180.html 【1】概述 …

etl介绍与etl工具比较_ETL万岁

etl介绍与etl工具比较提取转换负载是从一个数据系统中提取数据并加载到另一个数据系统中的过程。 涉及的数据系统称为源系统和目标系统。 来自源系统的数据形状与目标系统不匹配,因此需要进行一些转换以使其兼容,该过程称为Transformation 。 转换是由m…

漫画:高并发下的HashMap

转载自 玻璃猫 程序员小灰上一期我们介绍了HashMap的基本原理, 这一期我们来讲解高并发环境下,HashMap可能出现的致命问题。HashMap的容量是有限的。当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会…

jvm(11)-晚期(运行期)优化

【0】README 0.1)本文部分文字描述转自 “深入理解 jvm”,旨在学习 晚期(运行期)优化 的基础知识; 【1】概述 1)即时编译器(JITjust in time compiler)定义:为了提高…

java 新功能_Java 14的新功能

java 新功能2020年3月17日,Oracle发布了名为Java 14的Java新版本,其中包括许多新功能,工具,安全性,调试和更新的文档方面的改进。 但是,Oracle还向您提供Java的较旧版本,因为它具有向后兼容性&a…

漫画:什么是ConcurrentHashMap

转载自 玻璃猫 程序员小灰————————————————————————前两期我们讲解了HashMap的基本原理,以及高并发场景下存在的问题。没看过的小伙伴可以点击下面链接:漫画:什么是HashMap? 漫画:高并发下的H…

jvm(12)-java内存模型与线程

【0】README0.1)本文部分文字描述转自“深入理解jvm”,旨在学习“java内存模型与线程” 的基础知识;【1】概述1)并发处理的广泛应用是使得 Amdahl 定律代替摩尔定律称为计算机性能发展源动力的根本原因;2)A…

junit mockito_从工作中清除代码–使用JUnit 5,Mockito和AssertJ编写可执行规范

junit mockito可执行规范是也可以用作设计规范的测试。 通过启用通用语言(在DDD世界中,这也称为无处不在的语言 ),它们使技术和业务团队能够进入同一页面。 它们充当代码的未来维护者的文档。 在本文中,我们将看到一种…

漫画:什么是红黑树

转载自 玻璃猫 程序员小灰————————————二叉查找树(BST)具备什么特性呢?1.左子树上所有结点的值均小于或等于它的根结点的值。 2.右子树上所有结点的值均大于或等于它的根结点的值。 3.左、右子树也分别为二叉排序树。下图中这棵树…

jvm(13)-线程安全与锁优化

【0】README 0.1)本文部分文字转自“深入理解jvm”, 旨在学习 线程安全与锁优化 的基础知识; 0.2)本文知识对于理解 java并发编程非常有用,个人觉得,所以我总结的很详细; 【1】概述 【2】线程安…

apache ignite_Kubernetes集群上的Apache Ignite和Spring第3部分:测试应用程序

apache ignite在上一个博客中,我们为Ignite应用程序创建了Kubernetes部署文件。 在此博客上,我们将在Kubernetes上部署Ignite应用程序。 我将在此使用minikube。 让我们先构建 mvn clean install 我将创建一个简单的Docker映像,因此需要Doc…