一、虚拟机字节码执行引擎

  1.虚拟机执行引擎由自己实现,所以可以自行制定指令集与执行引擎的体系结构,并且可以执行那些不被硬件直接支持的指令集格式。

  2.执行引擎

  • 编译执行:通过JIT编译器产生本地代码执行
  • 解释执行:通过解释器解释执行

二、运行时栈帧结构

  • 栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。
  • 对于执行引擎来说,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧。

  

  1.局部变量表

  • 编译时,在方法的Code属性的max_locals确定需要分配的局部变量表的最大容量
  • 对于实例方法,局部变量表中的0位索引的Slot默认记录方法所属对象实例的引用,即this指针
  • 根据变量作用域,Slot可以被复用,可能对垃圾回收产生影响,如果对变量赋null,在JIT编译中会被清除,最优雅的解决方法是以恰当的变量作用域来控制变量的回收时间

  2.操作数栈

  • LIFO栈
  • 最大深度为编译时写入方法表中Code属性的max_stacks
  • 可能会有不同栈间的数据共享  

  

  3.动态连接

  • 每个栈帧都包含一个指向运行时常量池中该栈帧所属性方法的引用,用来支持动态连接
  • 字节码中的方法调用指令:以常量池中指向方法的符号引用为参数
  • 符号引用解析:一部分发生在类加载或者第一次使用,即静态解析,动态解析发生在每一次运行期

  4.方法返回地址

  • 正常完成出口
  • 异常完成出口

  5.附加信息

  • 在实际开发中,一般会把动态连接,方法返回地址与其它附加信息全部归为一类,称为栈帧信息。

三、方法调用

  • 目的:确定调用方法的版本
  • 一切方法调用在Class文件里存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址(相当于直接引用)

  1.解析

  • 类加载的解析阶段,会把其中一部分符号引用转化为直接引用,前提:方法在程序运行之前只有一个可确定的调用版本,并且这个调用版本在运行期不可变
  • 编译器可知,运行期不可变:静态方法与私有方法,
  • 五条方法调用字节码指令

  1)invokestatic:调用静态方法

  2)invokespecial:调用实例构造器方法,私有方法和父类方法。

  3)invokevirtual:调用虚方法。

  4)invokeinterface:调用接口方法,会在运行时再确定一个实现此接口的对象。

  5)invokedynamic:先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法,在此之前的4条调用指令,分派逻辑是固化在Java虚拟机内部的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

  • 只要能被invokestatic与invokespecial指令调用的方法,都可以在解析阶段确定唯一的调用版本,符合这个条件的有静态方法,私有方法,实例构造器和父类方法四类,它们在类加载的时候就会把符号引用解析为该方法的直接引用。这些方法可以统称为非虚方法,与之相反,其它方法就称为虚方法(除去final方法)。
  • final方法虽然由invokevirtual调用,但是由于它无法被覆盖,没有其他版本,所以也是非虚方法

  2.分派

  • 静态分派:依赖静态类型来定位方法执行版本的分派动作称为静态分派,典型应用为方法重载

  1)Shape s = new Circle(),Shape称为静态类型,Circle称为实际类型

  • 动态分派:依赖动态类型执行方法分派,典型应用为重写

  1)动态分派时,会根据当前栈帧的局部变量表,进行挨个遍历匹配接受者(即调用者),由于invokevirtual指令执行的第一步就是在运行期确定接受者的实际类型,这个过程就是Java语言重写的本质

  • 单分派与多分派

  1)方法的接受者与方法的参数称为方法的宗量。

  2)单分派是根据一个宗亮对目标方法进行选择,多分派是根据多个宗量

  3)Java语言:静态多分派、动态单分派

  4)动态分派,优化手段:虚方法表,若方法没被重写,则地址入口与父类相同方法地址一致

  

  3.动态语言支持

  • 反射与invokedynamic指令

四、基于栈的字节码解释执行引擎

  1.解释执行

  • Java 语言中, Javac 编译器完成了程序代码经过词法分析、语法分析到抽象语法树,再遍历语法树生成线性的字节码指令流的过程
  • 解释器在JVM内部,所以Java程序的编译是半独立的实现

  

  • 中间过程:解释执行
  • 下面过程:传统编译原理程序代码到目标机器代码的生成过程

  2.基于栈指令集与寄存器指令集

  • 基于栈的指令集主要的优点就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束。
  • 栈架构指令集的主要缺点是执行速度相对来说会稍慢一些。
  • 虽然栈架构指令集的代码非常紧凑,但是完成相同功能所需的指令数量一般会比寄存器架构多,因为出栈、入栈操作本身就产生了相当多的指令数量,,栈实现在内存之中,频繁的栈访问也就意味着频繁的内存访问,相对于处理器来说,内存始终是执行速度的瓶颈。

五、类加载器

  1.Tomcat

  

  2.OSGI:运行时生成类加载体系结构

  3.字节码生成与动态代理技术

  4.Restrotranslator:Java逆向移植工具

  • 基本原理是将新特性在编译时进行替换,如包装对象,更换为Integer.valueOf()

参考:

  https://gavinzhang1.gitbooks.io/java-jvm-us/content/xu_ni_ji_zi_jie_ma_zhi_xing_yin_qing.html

深入理解Java虚拟机6-chap8-9-斗者3星的更多相关文章

  1. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  2. 《深入理解 java虚拟机》学习笔记

    java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.

  3. (1) 深入理解Java虚拟机到底是什么?

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机   作为一个Java程序员,我们每天都在写Java ...

  4. 深入理解java虚拟机(7)---线程安全 & 锁优化

    关于线程安全的话题,足可以使用一本书来讲解这些东西.<Java Concurrency in Practice> 就是讲解这些的,在这里 主要还是分析JVM中关于线程安全这块的内容. 1. ...

  5. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  6. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  7. 深入理解java虚拟机(4)---类加载机制

    类加载的过程包括: 加载class到内存,数据校验,转换和解析,初始化,使用using和卸载unloading过程. 除了解析阶段,其他过程的顺序是固定的.解析可以放在初始化之后,目的就是为了支持动态 ...

  8. 深入理解java虚拟机(1)------内存区域与内存溢出

    在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻. 而Java确把这一工作交给了虚拟机来处理. 我们首先来看看关于内存的问题. 1.问题: 1)java ...

  9. 什么是HotSpot VM & 深入理解Java虚拟机

    参考 http://book.2cto.com/201306/25434.html 另外,这篇文章也是从一个系列中得出的: <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> ...

  10. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

随机推荐

  1. 【iCore1S 双核心板_FPGA】例程十七:基于双口RAM的ARM+FPGA数据存取实验

    实验现象: 核心代码: module DUAL_PORT_RAM( input CLK_12M, inout WR, input RD, input CS0, :]A, :]DB, output FP ...

  2. Oracle分析函数-统计(sum、avg、max、min)

    很多需求中都涉及到统计:均值.累计.范围均值.相邻记录比较等.这些操作会统计多次,或有明确的统计范围,或返回的记录统计的数据集不同... 根据场景不同可分为如下几类: 1. 全统计 2. 滚动统计 3 ...

  3. Android打开各种类型的文件方法总结

    很简单,通过调用系统的intent,我们可以打开各种文件,不熟悉的朋友可以了解下action.datatype.uri的相关知识. 通用方法如下: public static Intent openF ...

  4. QT系统托盘应用程序

    在QT中QSystemTrayIcon类提供了创建系统托盘程序的功能. QSystemTrayIcon类为系统托盘中的应用程序提供图标.现代操作系统通常会在桌面上提供一个称为系统托盘(system t ...

  5. [hadoop] kettle spoon 基础使用 (txt 内容抽取到excel中)

    spoon.bat 启动kettle. 测试数据 1. 新建转换 输入中选择文本文件输入 双击设置文本输入 字符集.分隔符设置 获取对应的字段,预览记录. 拖入 excel输出,设置转换关系 设置输出 ...

  6. vb编程中的选择结构语句的写法

    1996年,Bohra和Jacopin提出了结构化算法的3中种基本结构:顺序结构.选择结构和循环结构 目前已经得到证明,无论多么复杂的程序,都是由上面的3种基本结构中的一种或者多种的组合构成 在此笔者 ...

  7. python基础类型—集合

    一,集合. 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把一个列表变成集合,就自动去重了. ...

  8. I - The lazy programmer 贪心+优先队列

    来源poj2970 A new web-design studio, called SMART (Simply Masters of ART), employs two people. The fir ...

  9. 删除或修改本地Git保存的账号密码

    win10 系统下进入 控制面板 > 用户帐户 > 管理你的凭据 选择 [Windows 凭据] git 保存的用户信息在普通凭据列表里 >>编辑>>>完成

  10. GetLastError获取到错误代码的含义

    在写win32的时候我们会用到GetLastError()函数来获取程序错误信息,那我们如何从返回的数字得到错误信息. 这里推荐一个博客,总结了所以返回数字的错误信息: http://blog.csd ...