• Chapter 2. The Structure of the Java Virtual Machine阅读笔记


    第二章. Java虚拟机的结构

    这篇文章定义了一个抽象的java虚拟机。不包含任何的具体实现。
    为了正确地实现一个java虚拟机,你只需要正确地解析class文件并且正确地执行文件定义的操作。不属于java虚拟机定义的实现细节将不必要地限制实现者的创造力。比如,运行时数据区的内存布局,使用的垃圾回收算法,以及任何对java虚拟机指令的优化(比如,将它们翻译成机器代码)都由实现者自行决定。
    本规范所有对Unicode的引用都针对Unicode6.0.0版本。 http://www.unicode.org/.

    2.1 Class文件格式

    JVM执行的代码使用一种硬件,操作系统独立的二进制格式,一般(不是必须)存放在一个叫做class的文件格式中。class文件精确地定义了如何表示一个类或者接口,包括字节序等细节。

    2.2 数据类型

    JVM操作两种类型的数据,primitive和reference。
    JVM期望在run time之前完成几乎所有的类型检查,一般由编译器完成而不是JVM。primitive的值不需要被标记或者在运行时被检查来确认它们的类型,或者与reference类型的值区分。取而代之,通过使用为了操作特定类型而设计的JVM指令集来区分操作数的类型。比如,iadd, ladd, fadd, dadd。
    JVM明确支持对象。对象是动态分配的class实例或者数组。指向对象的引用被认为是JVM的reference类型。引用类型的值可以认为是指向对象的指针。对一个对象的多个引用是可以存在的。

    2.3 Primitive类型与值

    JVM支持三种primitive类型,分别是数字类型,布尔类型和returnAddress类型。
    数字类型包括整数和浮点数。
    整数包括:

    • byte,其值为8位有符号的二进制补码(Two's complement)整数,默认值为0。
    • short,16位,0
    • int, 32位, 0
    • long, 64位,0
    • char, 16位无符号, UTF-16,默认值\u0000
      浮点数包括
    • float,float value set and float-extended-exponent value set, 默认值+0
    • double, double value set and double-extended-exponent value set, 默认值+0
      布尔类型,默认false
      returnAddress类型是指向JVM指令的操作码的指针。primitive类型中,只有returnAddress没有与java编成语言类型直接关联。

    2.3.1 整数

    • byte: [-27~27-1]
    • char: [0, 28-1]

    2.3.2 浮点数

    IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std. 754-1985, New York).
    IEEE 754: 正负数字,正负0,正负无穷,NaN
    所有的JVM必须实现float value set和double value set。可以实现float-extended-exponent value sets和double-extended-exponent value set。
    有限非零的浮点数的表示公式:s ⋅ m ⋅ 2(e − N + 1)
    s = +1 or -1
    0 < m <= 2N
    -(2K-1-2) <= e <= (2K-1-1)
    N and K depend on the value set
    normalized value: m >= 2N-1

    Parameter float float-extended-exponent double double-extended-exponent
    N 24 24 53 53
    K 8 ≥ 11 11 ≥ 15
    Emax +127 ≥ +1023 +1023 ≥ +16383
    Emin -126 ≤ -1022 -1022 ≤ -16382

    extended value set拥有更高的精度
    float value set的元素正好是用IEEE 754可以表示的值,除了NaN(IEEE中有224-2个不同的NaN表示)。double value set同理。
    float-extended-exponent value set与IEEE 754 single extended不是对应的,double同理。本规范不指定任何特定的对于float-point value sets的表示方式,除了float-point values必须可以被class文件格式表示。
    float, float-extended-exponent, double, and double-extended-exponent value sets不是类型。使用float value set中的元素来表示float类型的一个值总是正确的。在特定的上下文,使用float-extended-exponent value set的元素作为float类型的值的实现是可以的。
    除了NaNs,float-point value sets是有序(ordered)的。
    +0 equals -0, 1.0/0.0 = +inf, 1.0/-0.0 = -inf
    NaN is unordered。test for numerical equality is false when either operand is NaN

    2.3.3 returnAddress

    returnAddress类型被用于jsr, ret和jsr_w指令。没有对应的java编程类型。

    2.3.4 boolean

    JVM没有专用于操作boolean类型的指令。java编程语言中对boolean的操作在JVM中被转化为对JVM int类型的操作。
    JVM支持boolean数组,使用newarray指令创建。boolean数组使用byte数组指令baload,bastore访问和修改。
    Oracle的JVM实现中,对于boolean数组,每个boolean元素使用使用一个byte表示。
    编译器将Java language的boolean类型映射为JVM的int类型。

    2.4 Reference Type and Values

    三种引用类型,class, array, interface。引用的值是动态创建的类的实例或者数组,或者分别实现了接口的类实例或者数组。
    array类型由一维的component type组成(长度不由component type给出)。component type可以是array类型。the component type of a component type and so on, 最终的component type不是array类型,该类型称为该array type的element type。element type可以是class, primitive, interface。
    reference类型的默认值是null。
    规范不指定null的编码值。

    2.5 Run-Time Data Areas

    JVM定义了多种run-time data areas。一些运行时数据区在JVM启动和结束分别创建销毁,其他数据区每个线程独立分配。线程的运行时数据区在线程创建和退出时创建和销毁。

    2.5.1 The pc Register

    JVM支持同时执行多个线程。每个JVM线程具有自己的pc register。任何时刻,每一个JVM线程都在执行单个方法的代码,该方法称为current method for that thread。如果那个方法不是native的,pc register包含当前被执行的JVM instruction的地址。如果是native的,pc register的值undefined。JVM的pc register具有足够的宽度来存储returnAddress或者特定平台的native pointer。

    2.5.2 JVM Stacks

    每一个JVM thread有一个私有的JVM stack,stack与thread一同创建。JVM stack存储frame。JVM Stack与传统语言,比如c的stack类似:存储local variable和partial result,用于方法调用和返回。除了push和pop frame,JVM Stack永远不会被直接操作,所以frame可能被分配在heap上。JVM Stack的memory不必连续。
    规范允许JVM Stack的size是固定的或者动态的。如果是固定的,每个thread创建时可以独立选择stack的size。
    JVM的实现需要允许programmer和user选择stack的size,或者maximum size与minimum size。
    以下异常情况与JVM stack相关:

    • 如果计算需要stack size超过限制,JVM抛出StackOverflowError
    • 对于动态stack,如果增加时,没有足够的memory,或者创建时,没有足够的memory,JVM抛出OutOfMemoryError。

    2.5.3 Heap

    所有JVM thread共享JVM Heap。所有的class实例和arrays都从heap这个run-time data area分配内存。
    heap在JVM启动时创建。heap存储的objects由GC自动管理。objects永远不需要明确释放。JVM不假设GC的类型,GC技术由实现者根据自身系统要求自行选择。heap可以是fixed和dynamic。heap的内存不需要连续。
    heap的size或者range可以指定。
    以下异常情况与heap相关:

    • 如果计算需要的heap空间多于GC能够提供的,抛出OutOfMemoryError

    2.5.5 Method Area

    JVM thread共享method area。

  • 相关阅读:
    c# webapi无法获取Session值问题解决
    深入理解java虚拟机之自动内存管理机制笔记
    数据结构总结1
    疯人院之语言、编码、计算机

    集线器/交换机
    什么是DOM?DOM和JavaScript的关系 [web开发]
    JSON轻量级的数据交换格式
    天问宇宙学第一课
    C++基础知识
  • 原文地址:https://www.cnblogs.com/N3ptuner/p/15816104.html
Copyright © 2020-2023  润新知