翻译-JVM Run-Time Data Areas

官方文档: https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-2.html#jvms-2.5.3

JVM 运行时数据区

在程序的运行过程中,JVM定义了多种运行时数据区。其中一些数据区随着JVM启动而创建,随着JVM的退出而销毁(这部分就是线程共享的区域,如堆、方法区)。另外一区数据区是线程私有的,它随着线程的创建而创建,并当线程退出的时候而销毁(如虚拟机栈、本地方法栈、程序计数器)。

程序计数器(The pc Register)

JVM能支持许多线程同时执行,每个虚拟机线程都有它自己的程序计数器。不管在什么时候,每个虚拟机线程都在执行一个方法,叫做“current Method”(当前方法)。如果当前执行的方法不是native方法(本地方法),那么程序计数器记录的就是当前正在执行的指令地址。当线程执行的是native方法时,程序计数器记录的值为undefined。另外需要注意的是,PC Register所占用的空间需要足够得大,使得它能在任何平台都能记录返回地址或机器的指针。

Java虚拟机栈(Java Virtual Machine Stacks)

每个虚拟机线程都有一个私有的虚拟机栈,和线程一起创建。虚拟机栈中存储了栈帧,它类似常规语言中的栈的概念,例如C语言,它存储了方法中的局部变量和临时结果,并且在方法调用、方法返回中发挥作用。虚拟机栈除了push和pop栈帧两种操作,它无法操作数据,并且栈帧的空间是在堆中开辟的。虚拟机栈的内存空间不要求连续。
虚拟机规范允许虚拟机栈的大小可以是固定的,也可以是自动伸缩的。如果是固定大小的话,虚拟机栈的大小应该可以独立设置。如果大小可以动态伸缩,那应该提供 maximum and minimum(最大和最小如-Xss128K,本地方法栈大小也是这个)的设置。

  • 以下是虚拟机栈相关的异常条件:
    1、如果一个线程中的计算需要的虚拟机栈大小超过了允许的栈大小,虚拟机将会抛出StackOverflowError。(栈溢出)
    2、如果虚拟机栈大小可以动态伸缩,并且可用于拓展的内存不足(insufficient )。或者当创建虚拟机栈的时候无法申请到足够的内存,此时虚拟机将会抛出OutOfMemoryError异常。
堆(Heap)

虚拟机中的堆是所有的虚拟机线程共享的。所有的类实例和数组都在运行时堆中申请内存。
堆随着虚拟机的启动而创建,它会被一个自动存储管理系统进行内存管理,就是我们熟知的垃圾收集器GC(garbage collector),堆中的对象不会被显式地释放,对象的回收交由GC管理。JVM不会假定特定类型的自动存储管理系统,而是根据系统实现者的需要选择(即选择不同的GC方式)。堆的大小可以是固定的,也是可以根据虚拟机的需要自动伸缩(通过设置maximum and minimum heap,如-Xms256m -Xmx512m)。和虚拟机栈一样,虚拟机堆的内存也可以不连续。

-和堆相关的异常:
1、当计算需要开辟的对空间大于GC后所释放的空间时(就是堆空间不够用了),此时虚拟机抛出OutOfMemoryError。

方法区(Method Area)

方法区也是所有线程共享的。方法区就是 编译好的代码的存储区,或类似于操作系统中的文本段(“text” segment)。方法区里面存储着每个已加载的类的结构,例如运行时常量池、字段、方法,以及方法里的代码和构造器,包括类或接口的初始化构造器和实例构造器。
方法区随着虚拟机的启动而创建。虽然方法区在逻辑上是堆的一部分,但一般GC不会去回收和压缩它。
虚拟机规范没有规定方法区存储的位置和管理编译后的代码的策略。同样,方法区可以固定大小,也可以动态伸缩(-XX:MaxPermSize=256m 默认初始大小在64位的hotspot一般是64M)。存储的内存空间可以不连续。

  • 和方法区相关的异常:
    当方法区中可用的内存无法满足内存申请请求时,虚拟机抛出OutOfMemoryError异常.
运行时常量池(Run-Time Constant Pool)

运行时常量池是每个class文件在运行时的常量表的表示,它包含了多种常量,包括编译过程中已知的数字字符,以及运行时的方法和字段的引用。运行时常量池的功能类似于一门开发语言的标志表(symbol table),虽然这比标志表中的数据量更大。
每个运行时常量池是在方法区中开辟的,一个类或接口的运行时常量池随着类或接口的创建而创建。(当类或接口加载的时候)

  • 和方法区相关的异常:
    当创建一个类或接口时,如果运行时常量池的构造器无法申请到足够的内存,虚拟机会抛出OutOfMemoryError异常。
本地方法栈(Native Method Stacks)

本地方法栈一般使用的是常规的栈(和虚拟机栈的组成有区别,虚拟机栈是虚拟机设计的,由栈帧构成),(口语上可以成为C栈(C stacks))来支持本地方法的执行。本地方法栈通常被JVM的解释器指令使用,解释器采用的语言比如C。
不能加载本地方法或者不依赖常规栈的JVM实现不需要提供本地方法栈。如果提供了,本地方法栈一般是在虚拟机线程创建的时候创建。
本地方法栈的大小可以固定,也可以动态伸缩。

  • 与本地方法栈相关的异常:
    1、当运算需要的栈超出允许的栈大小,虚拟机抛出StackOverflowError异常。
    2、当本地方法栈可以动态伸缩,并且尝试申请内存,当可申请的内存不足。或者当创建线程的时候无法初始化本地方法栈时,JVM抛出OutOfMemoryError异常。

你可能感兴趣的:(JVM,JVM)