• 第七章 JVM体系结构与工作方式


    JVM能跨计算机体系结构来执行Java字节码,主要是由于JVM屏蔽了与各个计算机平台的软件和硬件之间的差异。

    7.1 JVM体系结构

      7.1.1 何谓JVM

        模拟一个计算机来达到一个计算机所具有的计算功能。

        以计算为中心来看计算机的体系结构可以分为如下几个部分。

    •  指令集    计算机能识别的机器语言的命令集合。
    •  计算单元  能够识别并且控制指令执行的功能模块。
    •  寻址方式  地址的位数,最小地址和最大地址范围,以及地址的运行规则。
    •  寄存器定义 包括操作数寄存器,变址寄存器,控制寄存器等的定义,数量和使用方式。
    •  存储单元 能够存储操作数和保存操作结构的单元,如内核级缓存,内存和磁盘等。

    每一个汇编语句可以翻译成一条机器指令。

    CPU架构是否影响指令集?因为在汇编语言中都是对寄存器和段的直接操作的命令,所以不同的芯片架构设计一定会对应不同的机器指令集合。

    JVM和实体机有何区别?

    • 一个抽象规范:这个规范约束了JVM到底是什么?有哪些组成部分
    • 一个具体实现:不同的厂商按照抽象的规范实现
    • 一个运行中的实例:当用其运行一个JAVA程序时,它就是一个运行中的实例,每一个运行中的实例,都是一个JVM实例。

      7.1.2 JVM体系结构详解

    • 类加载器:JVM启动时或者在类运行时将需要的class加载到JVM种。
    • 执行引擎:执行class文件中包含的字节码指令,相当于实际机器上的CPU。
    • 内存区:将内存分成若干个区以模拟实际机器上的存储、记录和调度功能模块,如实际机器上的各种功能的寄存器或PC指针的记录器等。
    • 本地方法调用:调用C或C++实现的本地方法的代码返回结果。

               1 类加载器:每个被JVM转载的类都有一个对应的java.lang.Class类的实例来表示该类型,该实例可以唯一表示被JVM装载的class类,这个实例在JAVA堆中,

       2 执行引擎:JVM核心,作用是解析JVM字节码指令,得到执行结果。JAVA虚拟机规范定义了执行引擎遇到每条字节码指令时应该处理什么,得到什么结果。但是

             没有规定用何种方式。所以各JVM厂商自己决定。

              执行引擎也就是执行一条条代码的一个流程,代码包含在方法体内,所以执行引擎本质上就是执行一个个方法所串起来的流程。JVM同时运行多个线程,

              每个线程就是一个执行引擎的的实例。这些执行引擎有的执行用户程序,有的执行JVM内部程序(垃圾回收)

       3 JAVA内存管理:方法区,Java堆,JAVA栈,PC寄存器和本地方法区。其中方法区和JAVA堆是所有线程共享的,可以被所有执行引擎实例共享,每个新的执行引擎实例被

                 创建的时候会创建JAVA栈和一个PC寄存器。如果当前正在执行一个JAVA方法,那么当前这个JAVA栈中保存的是该线程中方法调用的状态,包括方法参数,局部

                 变量,方法返回值以及运算的中间结果。PC指向下一条指令。

    7.2 JVM工作机制

      JVM如何执行字节码命令的,也就是执行引擎是如何工作的 。

      不管是何种指令集都是只有几种基本的元素:加 减 乘 求余 求模等。这些又可以进一步分解成二进制位运算:与 或 异或等。这些运算都是通过指令来完成,而指令的核心目的就是确定需要运算的种类(操作符)和运算需要的数据(操作数),以及从哪里(寄存器或栈)获取操作数,将操作结果放在什么地方(寄存器或栈)。这种不同的操作方式又将指令划分成:一地址指令,二地址指令,三地址指令和零地址指令。相应的指令集会有对应的架构实现,如基于寄存器的架构实现或者基于栈的架构实现,这里的基于什么实现是指在一个指令中的操作数是如何存取的。

      7.2.1 机器如何执行代码

      JVM执行字节码指令是基于栈的结构, 也就是所有的操作数必须先入栈,然后根据指令中的操作码选择从栈顶弹出若干个元素进行计算后再将结果入栈。

      在JVM中操作数可以存放在每一个栈帧的本地变量集中,每个方法在调用时,给分配本地变量集,这个本地变量集在编译的时候就确定了,所以操作数入栈就是常量入栈或者从本地变量集中取变量入栈。这和基于寄存器的操作不同:操作数要频繁的入栈和出栈,比如进行加法,如果两个操作数都在本地变量集中,那么一个加法操作需要5次栈操作;如果是基于寄存器的话,只需要将两个操作数放入寄存器进行加法运算后再将结果放入寄存器就可以。不需要这样多的数据移动操作。那么JVM为什么基于栈来设计呢?

      7.2.2 JVM为何选择基于栈的结构

     理由:一是JVM要设计成平台无关的,在有很少或没有寄存器的机器上同样可以正确的执行JAVA代码,基于寄存器的架构很难做到通用。

             二是为了指令的紧凑性,

      7.2.3 执行引擎的结构设计

      每当创建一个新的线程时,JVM会为这个线程创建一个JAVA栈,同时分配一个PC寄存器,并且这个PC寄存器会指向这个线程第一行可执行代码。每当调用一个新方法时,会创建一个新的栈帧结构,栈帧会保存这个方法的一些元信息,如在这个方法中定义的局部变量,一些用来支撑常量池的解析,正常方法返回和异常处理。

      

     常量区:  类型信息 类型的常量池( constant pool) 
    域(Field)信息 
    方法(Method)信息 
    除了常量外的所有静态(static)变量 

      7.2.4 执行引擎的执行过程

      7.2.5 JVM方法调用栈

      JVM的方法调用分为两种:一种是JAVA方法调用;另一种是本地方法调用。

  • 相关阅读:
    hibernate的缓存机制
    [poj 3159]Candies[差分约束详解][朴素的考虑法]
    POJ 2773 Happy 2006
    给定一个循环链表,实现一个算法返回这个环的开始结点
    使用jQuery创建模态窗口登陆效果
    实战数据结构(3)_两个单链表间的合并操作
    sql的强大功能(看一条sql解决的复杂业务)
    uva 10905 Children's Game (排序)
    JFinal学习 & Gradle配置续 & Tomcat配置
    Gradle项目学习 & HttpAsyncClient学习 & CountDownLatch学习
  • 原文地址:https://www.cnblogs.com/liufei1983/p/7398005.html
Copyright © 2020-2023  润新知