`
jaesonchen
  • 浏览: 311590 次
  • 来自: ...
社区版块
存档分类
最新评论

深入虚拟机笔记之控制流

 
阅读更多

第16章 控制流

 

    条件分支:在java源码中,可以在一个方法中使用if、if-else、while、do-while、for和switch语句来指定基本的控制流。当把源码转换成字节码时,除了switch语句外,java编译器使用同样的操作码集。每一种操作码都会从栈顶弹出一个或者两个值,然后进行比较;从栈中弹出一个值的操作码把该值与0进行比较;从栈中弹出两个值得操作码对这两个值进行比较。如果比较成功(成功在不同操作码中的定义不同),java虚拟机将按照由比较操作码的操作数提供的偏移量执行分支或者调整操作。

    对于所有的条件分支,java虚拟机都通过同样的过程来决定下一条将要执行的指令。虚拟机首先执行由操作码所决定的比较;如果比较失败,虚拟机将继续执行条件分支语句后面的指令;如果比较成功,虚拟机将会使用紧随操作码后的两个操作数字节来产生一个带符号的16位偏移量;虚拟机给当前线程的PC寄存器(程序计数器)加上这个偏移量(条件分支操作码的地址)来获取目标指令地址。目标地址必须指向同一个方法中的一条指令。程序会继续从目标地址开始运行。

    if操作码从栈顶弹出两个整数,将它们进行比较;如果比较成功,就执行分支操作。其中value2是栈顶端的值,value1是value2下面的值,即第一个弹出的是比较符右边的值,第二个弹出的是比较符左边的值。

    这些操作码在比较byte、short和char时,java虚拟机首先将它们转换为int类型的值,然后在对int类型进行比较。

 

    操作码对long、float、double进行比较操作时,从栈顶弹出两个整数,将它们进行比较;这些操作码本身并不会执行分支操作,而是把代表比较结果的int类型值(0表示相等、1表示大于、-1表示小于)压入栈中。然后使用int类型的条件分支操作码进行实际分支跳转。

    用于比较float和double的操作码(fcmpg、fcmpl、dcmpg、dcmpl),不同之处在于处理NaN的方式。在java虚拟机中,如果进行比较的值之一是NaN,浮点值比较通常会失败。当至少有一个比较值是NaN时,fcmpg、dcmpg指令将1压入栈,而fcmpl、dcmpl将-1压入栈。

    对象引用和null比较时,操作码从栈顶弹出对象引用,将其与null进行比较;如果比较成功,虚拟机将会执行分支操作。

    对象引用比较时,操作码从栈中弹出两个对象引用,对它们进行比较;只有两种比较结果:如果相等,说明它们指向堆中的同一个对象;如果不相等,说明它们指向不同对象。如果比较成功,虚拟机执行分支操作。

    无条件分支操作:goto指令。

    为了执行goto指令,虚拟机首先根据紧随指令的两个操作数字节,得出一个带符号的16位偏移量(goto_w指令需要4字节得出带符号的32为偏移量),虚拟机把得到的偏移量加到当前线程的PC寄存器上;最后得到的地址必须指向当前方法中的一条指令的操作码位置。虚拟机将会在这条指令处继续执行。

    使用表的条件分支:

    条件分支和无条件分支这些控制流在java源码中以if、if-else、while、do-while、for语句表示,这些操作码也能用来表述switch语句,但java虚拟机的指令集为switch语句专门设计了两个操作码:tableswitch和lookupswitch。

    tableswitch和lookupswitch指令都包含一个默认的分支偏移量和一组可变长度的“case值/分支偏移量”对。这两条指令都会将键值从栈中弹出,它们会把键值和所有的case值进行比较;如果发现匹配项,则取与该case值相关的程序分支偏移量,如果没有发现匹配项,则取默认的程序分支偏移量。

    tableswitch和lookupswitch之间的不同之处在于,它们采用不同的方法指定case值。指令lookupswitch比tableswitch使用的范围更广,但tableswitch的效率更高。这两条指令后面都有0-3个填充字节,每个填充字节的内容都是0,这是为了使紧随在填充字节后面的字节能以4字节的整数倍(从方法开头算起)位置处开始(整个java虚拟机指令集中仅有的考虑了边界对齐的多字节指令)。

    操作码lookupswitch之后是0-3个填充字节和4字节的默认分支偏移量;接着是4字节的值(npairs),它指明了指令后附带的“case值/分支偏移量”对的数量;键值是一个int类型值(说明java语言中的switch语句需要一个类型为byte、short、char和int的键值表达式),与每一个case值相关的程序分支偏移量都是一个4字节的偏移量;“case值/分支偏移量”对必须按照case值递增的顺序依次出现。

    操作码tableswitch之后是0-3个填充字节和4字节的默认分支偏移量,接着是8字节的低、高int类型值。低、高值指明了包含在本tableswitch指令中的case值范围。在低、高值后面的是程序分支偏移量跳转表,跳转表项数为(高值 - 低值 + 1),跳转表内容为:高值、低值以及介于高值和低值之间的每一个整数case值对应的程序分支偏移量,排列顺序为case低值到高值的递增序列,序列内容为case对应的程序分支偏移量,没有对应分支偏移量的case值使用默认的分支偏移量,索引为从0开始的跳转表。

    当java虚拟机遇到一条lookupswitch指令时,它必须把键值与与每个case值进行比较,直到遇到下列情况之一时才结束查找:发现匹配的值、检索到case值大于键值(“case/分支”对按case值递增)、所有case值均检索完毕。如果没有找到匹配的值,使用默认的分支偏移量。

    当java虚拟机遇到一条tableswitch指令时,它会简单地检查键值是否位于高值和低值之间;如果不再此范围内,则使用默认的分支偏移量;如果在此范围之内,虚拟机将会选择跳转表中处于(键值 - 低值)位置处的分支偏移量。通过这种方法,虚拟机能够确定适当的程序分支,而无需对每一个case值进行检查。tableswitch适用于case值是连续的情形,可以缩短指令长度并提高效率。

  

 

 

 

 

 

 

 

 

  • 大小: 110.6 KB
  • 大小: 123.8 KB
  • 大小: 79.6 KB
  • 大小: 48.8 KB
  • 大小: 52 KB
  • 大小: 38.3 KB
  • 大小: 88.7 KB
分享到:
评论

相关推荐

    虚拟机笔记1.pdf

    ### 虚拟机笔记1.pdf - Java 相关知识点概览 #### 一、Unix 操作系统背景 - **起源与发展**: - Unix 是一个强大的多用户、多任务操作系统,支持多种处理器架构,属于分时操作系统。它最早由 Ken Thompson、...

    深入Java虚拟机JVM类加载学习笔记

    ### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...

    尚硅谷JAVA基础笔记吐血整理

    Java的基本语法包括变量声明、数据类型(包括基本数据类型和引用数据类型)、运算符、控制流(如if语句、for循环、while循环)、异常处理和方法定义等。其中,变量声明时需要指定数据类型,例如`int num = 10;`,...

    马士兵JAVA笔记(全).docx

    本资源是马士兵的JAVA笔记,涵盖了JAVA语言的基础知识,包括标识符、常量、变量、数据类型、运算符、控制流语句等。 标识符是JAVA中的一种符号,用于命名变量、方法、类等。标识符由字母、下划线、美元符、数字组成...

    大佬的java笔记

    3. Java基础语法:包括数据类型、变量、运算符、控制流(如if、for、while等)、方法、数组等。笔记中可能会详细讲解这些基础知识,帮助初学者打好Java编程的基石。 4. Java核心类库:Java的核心类库提供了丰富的...

    docs:Java知识总结:MySQL实战45讲,多线程和JVM知识总结,, SpringBoot,SpringCloud,Storm系列,微信小程序开发,ELK,《 JAVA核心技术36讲笔记》,《深入理解JVM虚拟机笔记》 ,《高级MySQL笔记》,《数据结构与算法》等等

    8. **《深入理解JVM虚拟机笔记》**:深入探讨JVM的工作原理,如内存区域、类加载机制、垃圾回收算法、性能调优策略等。 9. **《高级MySQL笔记》**:高级MySQL学习可能涉及分区、视图、触发器、存储过程、复制与集群...

    狂神说JAVA的所有笔记.zip

    首先,笔记可能涵盖了JAVA的基础知识,如数据类型、变量、运算符、流程控制(if-else、switch-case、for、while、do-while)、数组、方法等。这些内容构成了编程的基础,是每一个JAVA初学者必经的阶段。通过这些知识...

    李兴华java笔记

    《李兴华Java实战经典笔记》是一份深入探讨Java编程技术的宝贵资料,由知名IT教育专家李兴华编撰。这份笔记集合了他在教学和实践中积累的丰富经验,旨在帮助学习者掌握Java的核心概念、设计模式以及实战技巧。通过这...

    李兴华核心技术笔记 mldn

    1. **基础语法**:笔记可能详细介绍了Java的基础概念,如变量、数据类型、运算符、控制流(if语句、for循环、while循环)、方法定义和调用等。 2. **类与对象**:Java的核心在于面向对象编程,笔记可能会讲解如何...

    Java学习笔记——良葛格

    接着,笔记会深入讲解Java的语法基础,如变量、数据类型、运算符、流程控制语句(如if、for、while)以及方法的定义和调用。这部分内容对于初学者理解程序的逻辑结构至关重要。 在面向对象编程方面,良葛格的笔记会...

    java黑马笔记.rar.rar

    这样的笔记通常涵盖Java基础、进阶特性、面向对象编程、异常处理、集合框架、多线程、IO流、网络编程、JVM优化等多个方面的内容。 首先,Java基础部分会讲解语法特性,如变量声明、数据类型、运算符、流程控制(if...

    李兴华java word版全部笔记

    在输入输出(IO)部分,笔记会介绍InputStream、OutputStream、Reader、Writer等基础流的使用,以及文件操作和流的关闭。同时,笔记也将涵盖Java NIO(New IO)框架,讲解通道、缓冲区和选择器等新特性,帮助读者...

    李兴华2016年java课堂笔记

    首先,笔记中对Java基础进行了详尽的阐述,包括Java语言的语法特性、数据类型、运算符、流程控制语句等。这些内容是学习Java的第一步,理解并熟练掌握它们对于编写出规范的Java代码至关重要。例如,笔记会讲解如何...

    Java学习笔记(源码)

    3. **异常处理**:Java的异常处理机制是其强大的特性之一,学习笔记会讲解如何使用try-catch-finally语句块来捕获和处理程序运行时可能出现的错误。 4. **集合框架**:Java集合框架是存储和操作对象的重要工具,...

    张龙JAVA圣思园笔记

    笔记中可能会介绍Thread类的创建与管理,同步控制(synchronized关键字、wait/notify机制、Lock接口)、线程池(ExecutorService、ThreadPoolExecutor)等知识点。 3. **序列化**: Java序列化是将对象转换为字节...

    java学习笔记markdown

    4. **IO流**:介绍输入/输出流的概念,包括文件操作、字节流、字符流、对象序列化等。这部分内容涉及数据的读写和传输。 5. **网络编程**:讲解Socket编程,如何创建客户端和服务器进行网络通信,以及HTTP、HTTPS...

    mldn 李兴华笔记

    5. **IO流**:笔记可能涵盖了输入/输出流的使用,包括字节流和字符流,以及缓冲流、对象序列化、文件操作等相关知识。 6. **多线程**:Java提供了强大的多线程支持,笔记可能会讲解线程的创建方式(如继承Thread类...

    毕向东传智播客详细笔记

    《毕向东传智播客详细笔记》是一份深入浅出的Java学习资源,由知名IT教育专家毕向东在传智播客的授课内容整理而成。这份笔记以丰富的图文并茂的形式,为Java初学者提供了全面而细致的学习路径,是网络教学的优秀参考...

    传智博客JAVA基础笔记个人总结

    笔记将介绍基本的文件操作、字节流和字符流,以及NIO的通道、缓冲区和选择器。 6. **多线程**:Java支持多线程编程,使得程序可以同时执行多个任务。笔记会解释线程的创建、同步和通信,包括synchronized关键字、...

Global site tag (gtag.js) - Google Analytics