Java运行时数据区

Java虚拟机定义了一些程序运行期间会使用到的数据区域,其中一些会随着JVM的启动而创建,随着JVM的退出而销毁;另外一些则与线程的运行一一对立的,这些数据区域会随着线程的开始而创建,随着线程的结束而销毁。下面是一张Java运行时的数据区模型图:

总的来说,Java运行时数据区域可以分为两个部分:线程共享的区域和线程独享的区域。下面一一对之进行总结。

一、线程共享区域:线程共享区域是指各个线程都会使用到的一块空间区域,它们会在这里申请空间、使用空间。根据具体提供功能不同,可以划分为两个部分,分别是Java堆、方法区。下面分别总结。

1、Java堆:Java堆是在虚拟机启动的时候就被创建,它存储了被自动内存管理系统(也即常说的垃圾收集器)所管理的各种对象,这些对象无需也无法被显示地销毁。我们创建的类的实例以及数组对象就存放在这个区域。Java堆所使用的内存不需要保证是连续的。Java堆可能出现的异常有:如果所需的堆超过了自动内存管理系统能提供的最大容量,则Java虚拟机会抛出一个OutOfMemoryError异常。

2、方法区:方法区也是供各个线程共享的运行时存储区,它存储了每一个类的结构下信息,例如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容等。方法区也是随着虚拟机的启动而被创建,它是Java堆的逻辑组成部分,但是JVM可以选择在这个区域不实行垃圾搜集和压缩。同样,如果方法区的内存不能满足内存分配需求,则JVM将会抛出OutOfMemoryError异常。

3、运行时常量池:它是Class文件中每一个类或接口的常量池表的运行时的表示形式。它包涵了若干不同的常量,从编译期可知的数值字面量到必须在运行期解析后才能获得的方法或字段引用。每个运行时常量池都在Java虚拟机的方法区分配,在类和接口加载到虚拟机后,就会创建对应的运行时常量池。当创建类和接口时,如果构造运行时常量池所需的内存空间超过了方法区所提供的最大值,JVM将会抛出OutOfMemoryError异常。

二、线程独享区域:线程独享区域是每个线程都会单独拥有的一块区域,这块区域是属于线程内部的,它是用于存储描述自身内部信息的区域。同样,根据其提供 主要功能不同,一个线程内部具有的不同数据存储区域可以分为以下几个部分:

1、PC寄存器:PC(program counter)寄存器是用于记录正在执行线程的内存地址的,因为一个线程不可能一直独享CPU,当线程进行CPU切换时,必须要记录下来当前线程的内存地址,以便在重新启动线程时恢复以前的内存地址,在任意时刻,一条线程只会执行一个方法的代码,这个正在被执行的方法被成为该线程的当前方法(current method)。如果这个方法不是native的,那么PC寄存器会保存JVM正在执行的字节码指令的地址;如果该方法是native的,那么PC寄存器的值是undefined。

2、本地方法战:JVM可能会使用传统的栈(通常称为 C stack)来支持native方法(指使用Java以外的其他语言编写的方法)的执行,这个栈就是本地方法栈(native method stack)。JVM规范允许本地方法栈实现成为固定大小或者根据计算来动态扩展和收缩。若采用固定大小的本地方法栈,则每一个线程的本地方法容量可以在创建栈的时候独立选定。

3、Java虚拟机栈:也就是常说的“Java栈”,每一个JVM线程都有自己私有的Java虚拟机栈,该栈是与线程同时创建,用于存储栈帧。它的作用是用于存储一些尚未计算好的结果,此外,它在方法的调用和返回中也具有重要的作用。JVM规范既允许java虚拟机栈被是现成固定大小,也允许根据计算来扩展和收缩。若采用固定大小的Java虚拟机栈,则每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。Java虚拟机栈可能发生的异常有:如果线程请求的栈容量超过java虚拟机栈所允许的最大容量,则java虚拟机会抛出StackOverflowError异常;如果java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存或则创建新的线程时没有足够的内存去创建对应的虚拟机栈,则java虚拟机会抛出OutOfMemoryError异常。

4、栈帧:栈帧(frame)是用来存储数据和部分过程结果的数据结构。同时也是用来处理动态链接(dynamic linking)、方法返回值和异常分派。栈帧随着方法的调用而被创建,随着方法的结束而被销毁(无论是方法正常完成还是异常完成)。栈帧的存储空间是由创建它的线程分配在java虚拟机栈中的。每一个栈帧都有自己的本地变量表(local variable)、操作数栈(operand stack)、指向当前方法所属的类的运行时常量池的引用。在某个线程执行过程中的某个时间点上,只有目前正在执行的那个方法的栈帧是活动的,这个栈帧被成为当前栈帧(current frame),这个栈帧对应的方法称为当前方法(current method)、定义这个方法的类称为当前类(current class)。注意:栈帧是线程本地私有的数据,不能在一个栈帧之中引用另外一个线程的栈帧。

5、局部变量表:也叫本地变量表,它是用于存储局部变量的列表。栈帧中的局部变量表的长度是由编译期决定,并存储与类或接口的二进制表示中。一个局部变量可以保存一个类型为boolean、byte、char、short、int、float的数据类型。两个局部变量可以保存一个类型为long或double的数据。JVM使用局部变量表来完成方法调用时的参数传递。

6、操作数栈:每个栈帧内部均包含一个操作数栈,栈帧在刚被创建的时候,操作数栈是空的。JVM提供一些字节码指令来从局部变量表或者对象的实例中复制常量或变量到操作数栈中,也提供了相关指令从操作数栈中取走数据、操作数据以及把操作结果重新入栈。任意时刻,操作数栈都会有一个确定的栈深度,一个long、double类型的数据会占用两个深度的栈深度,其他数据则会占用一个栈深度。

6、动态链接:每个栈帧都包含这样一个引用,该引用是指向当前方法所在类型的运行时常量池,其作用是对当前代码实现动态链接。一个方法要调用其他方法,或则访问成员变量,需要通过符号引用(symbolic reference)来表示,动态链接的作用就是将这些以符号引用所表示的方法转换为对实际方法的直接引用。由于对其他类中的方法和变量进行了晚期绑定(late binding),所以即便那些类发生变化,也不会影响调用它们的方法。

以上总结自《Java虚拟机规范》,感觉内容还是挺多的,加油!

时间: 2024-10-12 16:35:55

Java运行时数据区的相关文章

Jvm基础-Java运行时数据区

最近在看<深入理解Java虚拟机>,里面讲到了Java运行时数据区,这是Jvm基本知识,把读书笔记记录在此.这些知识属于常识,都能查到的,如果我有理解不对的地方,还请指出. 首先把图贴上来,图来自JVM Runtime Data Areas(运行时数据区),感谢. 由上图可知,Java运行时数据区域包括程序计数器.Java虚拟机栈.本地方法栈.Java堆.方法区. 1. 程序计数器 程序计数器用来记录下一条字节码指令,因为CPU是要轮转的,在切换回来之后,Java能够找到下一条要执行的指令.如

深入理解Java运行时数据区

前情回顾 在本专栏的前12篇博客中, 我们主要大致介绍了什么是JVM, 并且详细介绍了class文件的格式. 对于深入理解Java, 或者深入理解运行于JVM上的其他语言, 深入理解class文件格式都是必须的. 如果读者对class文件的格式不是很熟悉, 在阅读本博客下面的文章之前, 建议先读一下前面的12篇博客, 或者参考其他资料, 熟悉class文件的格式. 在深入理解Java虚拟机到底是什么 这篇博客中, 我们有提到过, JVM就是一个特殊的进程, 我们执行的java程序, 都运行在一个

【JVM学习】2.Java虚拟机运行时数据区

来源: 公众号: 猿人谷 这里我们先说句题外话,相信大家在面试中经常被问到介绍Java内存模型,我在面试别人时也会经常问这个问题.但是,往往都会令我比较尴尬,我还话音未落,面试者就会"背诵"一段(Java虚拟机是由堆.方法区.虚拟机栈,吧啦吧啦...),估计心里还一脸自豪的想幸好哥提前在网上搜过,早有准备.每每这个时候,我都不忍心打断,因为"背诵"的真的太顺畅了! 这也怪不得面试者,首先Java虚拟机方面的知识,对中高级程序猿来说,工作中正面接触Java虚拟机的东西

JVM内存结构(运行时数据区)

前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些内存区域被统一叫做运行时数据区.Java运行时数据区大致可以划分为5个部分.在这里要特别指出,我们现在说的JVM内存划分是概念模型.如下图所示: JVM运行时数据区分为5种: 程序计数器 虚拟机栈(java栈) 堆 方法区 本地方法栈 程序计数器 程序计数器是一块较小的内存空间,它可

Java虚拟机 运行时数据区

Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随线程的开始和结束而创建和销毁. Java虚拟机所管理的内存将会包括以下几个运行时数据区域 程序计数器(Program Counter Register) 它是一块较小的内存空间,它的作用可以看做是当先线程所执行的字节码的信号指示器. 每一条JVM线程都有自己的PC寄存器,各条线程之间互不影响,独立存

Java虚拟机运行时数据区

PS:时间一晃好久了,距离上一篇文章过去许久了,出自两个方面的原因,其一,公司的项目接近尾声,用户提出的需求功能需要马上的解决:其二,出自整天加速完善和修改需求功能,下班之后几乎不想再继续下去了,懒散情绪有了. 扯淡话题结束了,开始继续学习笔记文章的整理,每天一小步,久而久之就是巨大的一步.今天要扯的话题是Java虚拟机的运行时数据区. Java虚拟机(JVM)是 由JDK提供的一个软件程序,而其任务就是执行Java程序,下面给出虚拟机执行Java的过程图. 从图中可以看出由Java源文件编译出

深入理解java:1.3.1 JVM内存区域的划分(运行时数据区)

了解Java GC机制,必须先清楚在JVM中内存区域的划分. JVM的体系结构如下:JVM的类加载系统.执行引擎系统.垃圾回收器都是去访问  运行时数据区. JVM管理的内存区域分为几个模块: (未完待续...)

Java 虚拟机运行时数据区介绍

引言 Java 虚拟机(Virtual Machine)在执行 Java 程序时, 会将它所管理的内存划分为不同的数据区,这些分块有不同的功能,理解它们各自的特点,对于深入理解java程序运行机制和调优Java代码,具有重要意义.其实个人觉得,理解 Java 虚拟机的原理,也没想象中的复杂(也许我的想法有点天真啊^_^),它的运行机制,就像一个小型操作系统,这也许就是虚拟机的来源吧. Java VM运行时数据区结构图 运行时数据区域解释 本地方法栈 该区域所发挥的作用与虚拟机栈类似,只不过它是为

《深入理解Java虚拟机》笔记01 -- 运行时数据区

运行时数据区示意图 1. 程序计数器 占用一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.主要用来记录线程执行到哪条语句了,分支.循环.跳转.异常处理.线程恢复等功能都需要依赖这个计数器来完成. 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址:如果正在执行的时Native方法,这个计数器值则为空.此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域. 2. Java 虚拟机栈 线程私有,生命