[笔记]Java虚拟机结构

[笔记]Java虚拟机结构

数据类型

  • 整数类型与整形值

    byte 的取值范围:-128~127(-2的7次方到2的7次方-1)

    short 的取值范围:-32768~32767(-2的15次方到2的15次方-1)

    int 的取值范围:-2147483648~2147483647(-2的31次方到2的31次方-1)

    long 的取值范围:-9223372036854774808~9223372036854774807(-2的63次方到2的63次方-1)

    char的取值范围:0~65535(包括0和65535)

  • 浮点型

    float 和 double 都是表示浮点型的数据类型,它们之间的区别在于精确度的不同。

    float(单精度浮点型)取值范围:3.402823e+38~1.401298e-45(e+38 表示乘以10的38次方,而e-45 表示乘以10的负45次方)

    double(双精度浮点型)取值范围:1.797693e+308~4.9000000e-324(同上)

  • returnAddress类型是指向某个操作码(opcode)的指针,此操作码与Java虚拟机指令相对应。

  • Java虚拟机中没有提供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,true值采用1来表示,false值采用0来表示。

  • Java虚拟机中有三种引用类型:类类型(class type)、数组类型(array type)和接口类型(interface type),这些引用类型的值分别指向动态创建的类实例,数组实例和实现了某个接口的类实例或数组实例。

  • Java虚拟机规范并没有规定null在虚拟机实现中应当怎样用编码来表示。

Run-Time Data Areas

The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits. Other data areas are per thread. Per-thread data areas are created when a thread is created and destroyed when the thread exits.

mark

运行时数据区 线程私有 分配方式 异常 Jvm参数
PC寄存器 true 线程启动时创建 --
Java栈 true 和线程同时创建 StackOverflowError/OOM -Xss表示的是Java虚拟机栈的大小
Java堆 false JVM启动时创建 OOM -Xms是 -XX:InitialHeapSize的简写 表示的是初始化堆的大小
-Xmx 是 -XX:MaxHeapSize的简写 表示的是设置堆的最大大小
运行时常量池 false 加载类后接口到虚拟机 OOM
方法区 false JVM启动时创建 OOM
本地方法栈 true 线程创建的时候 StackOverflowError

The pc Register (PC(program counter )寄存器 / 程序计数器)

线程私有线程启动时创建存储下一条要执行的指令的地址

The Java Virtual Machine can support many threads of execution at once . Each Java Virtual Machine thread has its own pc (program counter) register.At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine's pc register is undefined. The Java Virtual Machine's pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.

任意时刻,线程只能执行一个方法,即当前方法,如果线程当前执行的是本地方法,寄存器的值是undefined,否则,pc寄存器包含当前正在执行的Java虚拟机指令的地址,pc寄存器的容量至少应该能保存一个returnAddress类型的数据或者一个与平台相关的本地指针的值。

Java Virtual Machine Stacks (JAVA虚拟机栈)

线程私有和线程同时创建

Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (存储栈帧),frames may be heap allocated. The memory
for a Java Virtual Machine stack does not need to be contiguous.

栈帧可以在堆中分配,Java虚拟机栈使用的内存不需要是连续的

Java虚拟机栈可能发生如下异常:

  • 如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError异常
  • 如果Java虚拟机栈可以动态扩展,在扩展(-Xss)的时候无法申请到足够的内存,或者在创建新的内存时没有足够的内存去创建对应的Java虚拟机栈,Java虚拟机将会抛出一个OutOfMemoryError异常。

Java Heap(Java堆)

线程共享JVM启动时创建

The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated

堆是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域,-Xmx指令和-Xms可限制其大小。

Java堆可能出现的异常:

  • 实际所需的堆超过了自动内存管理系统能提供的最大容量,那Java虚拟机将会抛出一个OutOfMemoryError异常。

Method Area (方法区)

线程共享JVM启动时创建堆的逻辑组成部分(可不实现垃圾收集)在内存中可以不连续

方法区存储了每一个类的结构信息,如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容,以及一些在类、实例、接口初始化时用到的特殊方法。

可能发生的异常:

方法区的内存空间不能满足内存分配请求时,Java虚拟机将抛出一个OutOfMemoryError异常。

Run-Time Constant Pool (运行时常量池)

在方法区分配

A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file. It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time.

运行时常量池是class文件中每个类或接口的常量池表constant_pool table的运行时表示形式,它包括了从编译期可知的数值字面量到必须在运行期解析后才能获得的方法或字段引用。每一个运行时常量池都在Java虚拟机的方法区中分配,在加载类和接口到虚拟机后,就创建对应的运行时常量池。

可能的异常:

  • 当创建类或接口时,如果构造运行时常量池所需的内存空间超过了方法区能提供的最大值,那么Java虚拟机将会抛出一个OutOfMemoryError异常。

Native Method Stacks (本地方法栈)

按线程分配

Java虚拟机实现可能会使用到传统的栈(C stack)来支持native方法(使用Java以外的其他语言编写的方法)的执行,这个栈就是本地方法栈。Java虚拟机如果不支持native方法,或本身不依赖传统栈,就可以不提供本地方法栈,如果支持本地方法栈,那这个栈一般会在线程创建的时候按线程分配。

可能的异常:

  • 线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机抛出StackOverflowError异常
  • 本地方法栈在扩展的时候,无法申请到足够的内存,或者创建新线程时没有足够内存去创建对应的本地方法栈,Java虚拟机抛出OutOfMemoryError异常

栈帧

线程私有,随方法调用而创建,随方法结束而销毁

栈帧(frame)是用来存储数据和部分过程结果的数据结构,同时也处理动态链接(dynamic linking)、方法返回值和异常分派(dispatch exception)。

栈帧的存储空间由创建它的线程分配在Java虚拟机栈中,每个栈帧都有自己的本地变量表(local variable),操作数栈(operand stack)和指向当前方法所属的类的运行时常量池的引用。

本地变量表和操作数栈的容量在编译期确定,栈帧数据结构的大小仅仅取决于Java虚拟机的实现。

mark

局部变量表

每个栈帧内部包含一组称为局部变量表的变量列表。局部变量表的长度由编译期决定,存储于类或接口的二进制表示之中。

一个局部变量可以保存一个类型为 boolean, byte, char, short, int, float, reference, or returnAddress.的数据,两个局部变量可以保存一个类型为long or double的数据。

Java虚拟机使用局部变量表来完成方法调用时的参数传递。当调用实例方法时,第0个局部变量一定用来存储该实例方法所在对象的引用(this),后续的其他参数将会传递至局部变量表中从1开始的连续位置上。

操作数栈

每个栈帧内部包含一个成为操作数栈的后进先出栈,它的深度由编译期决定。一个long或者double类型的数据会占用两个单位的栈深度,其他数据类型则会占用一个单位的栈深度。

动态链接

每个栈帧内部都包含一个指向当前方法所在类型的运行时常量池的引用,以便对当前方法的代码实现动态链接。在class文件里,一个方法若要调用其他方法,或者访问成员变量,需要通过符号引用来表示,动态链接的作用就是将这些符号引用所表示的方法装换为对实际方法的直接引用。

特殊方法

JAVA编程语言中的构造器是以一个名为的特殊实例初始化方法的形式出现的。

一个类或者接口最多可以包含一个类或者接口的初始化方法,这个方法不包含参数,返回类型为void,名

字节码指令

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的操作码(opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(operand)所构成。虚拟机中的很多指令并不包含操作数,只有一个操作码。

Java虚拟机中的实际类型与运算类型

编译器会在编译期或运行期将byte和short类型的数据带符号扩展(sign-extend)为相应的int类型数据,将boolean和char类型数据零位扩展(zero-extend)为相应的int类型数据。在处理boolean、byte、short和char类型的数组时,也会转换为使用对应的int类型的字节码指令来处理。因此,操作数的实际类型为boolean、byte、char及short的大多数操作,都可以操作数的运算类型为int的指令来完成。

实际类型 运算类型 类别
boolean int 1
byte int 1
char int 1
short int 1
int int 1
float float 1
reference reference 1
returnAddress returnAddress 1
long long 2
double double 2

需要Jvm支持的指令

  • Reflection, such as the classes in the package java.lang.reflect and the class Class.

    反射,例如在java.lang.reflect包中的各个类和Class类.

  • Loading and creation of a class or interface. The most obvious example is the
    class ClassLoader.

    加载和创建类或接口的类,比如ClassLoader

  • Linking and initialization of a class or interface. The example classes cited above
    fall into this category as well.

    连接和初始化类或接口的类,刚才说的ClassLoader也属于这样的类

  • Security, such as the classes in the package java.security and other classes
    such as SecurityManager.

    安全,例如java.security包中的各个类和SecurityManager等其他类。

  • Multithreading, such as the class Thread.

    多线程,如Thread

  • Weak references, such as the classes in the package java.lang.ref

    弱引用,如java.lang.ref包中的各个类

参考资料

《Java虚拟机规范JavaSE8》第2章

posted @ 2018-09-29 16:33  龍變  阅读(140)  评论(0编辑  收藏  举报