`

Java虚拟机运行时数据区域总结

    博客分类:
  • JVM
阅读更多

本人推荐,如果要看虚拟机的相关内容,并且英语基础不错,可以直接看https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.6.4



 

1.运行时内存数据区域

根据Java虚拟机规范的规定,Java虚拟机所管理的内存包括以下几个运行时数据区域:

程序计数器,Java虚拟机栈,本地方法栈,Java堆,方法区.

2.虚拟机管理的内存区域介绍

2.1 程序计数器(Program Counter Register,PC寄存器):程序计数器是线程私有的,也就是说每个线程中都有一个程序计数器,在虚拟机的概念模型中,字节码解析器工作时就是通过改变程序计数器的值去获取下一条要执行的字节码指令.

如果执行的是Java方法,这个计数器记录的是当前线程正在执行的字节码指令的地址;如果是Native方法(本地方法),这个计数器的值是Undefined.此内存区域是唯一一个在Java虚拟机中规范中没有规定任何OutOfMemoryError情况的区域.

 

2.2 Java虚拟机栈(Java Virtual Machine Stacks):Java虚拟机栈是线程私有,它随线程的建立而建立(生命周期与线程相同).

虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时,都会在栈中建立一个对应的栈帧.当方法调用正常结束或者异常终止,栈帧被弹出.

在Java虚拟机栈上,会出现两类异常:

如果线程请求的栈的深度超过最大栈深度(max_stacks),会抛出StackOverflowError.

如果虚拟机栈可以动态扩展,当扩展无法申请到足够的内存空间时,会抛出OutOfMemoryError异常.

 

栈帧(Stack Frame):栈帧是支持虚拟机中方法调用和方法执行的数据结构,它是虚拟机运行时数据区域Java虚拟机栈的栈元素.

栈帧中存储的有:局部变量表,操作数栈(也叫操作栈),方法返回值(return Value),当前方法所属类的运行时常量池的引用和一些额外的附加信息.栈帧中需要多大的局部变量表,需要多深操作数栈(max_stacks),在编译器就已经确定,并且写入方法表的Code属性中,当前方法-->当前栈帧.方法执行引擎运行的所有字节码指令只针对当前栈帧.

 

2.2.1 局部变量表

2.2.1.1 局部变量表是方法中一组变量值的存储空间,它里面存放的是方法的参数和方法内部的局部变量.在Java代码编译为Class文件时,就在方法的Code属max_locals数据项中确定了执行该方法所需要分配的局部变量表的最大"容量"(编译期分配完成).局部变量中的容量以Slot为单位,虚拟机允许Slot的长度随着操作系统,虚拟机,处理器而不同,但是要求只要在外观上保证在64位虚拟机和32位虚拟机上看起来一样就行(使用对齐补白).一个Slot可以存放一个32位以内的数据类型(boolean,byte,char,short,int,float,reference,returnAddress)8种.对于64位的数据类型(long,double),虚拟机会用高位对齐的方式为其分配两个连续的Slot空间.由于局部变量表建立在线程的堆栈上,是线程私有数据,无论读写两个连续的Slot是否为原子操作,都不会有数据安全问题.因为虚拟机规范中明确规定了,如果遇到无论以任何方式访问64位数据类型的两个Slot中的其中一个,都要在类加载的验证阶段抛出异常.

2.2.1.2 局部变量表的使用:在方法执行时,虚拟机使用局部变量表完成参数值到参数变量表的值传递过程.

虚拟机采用"索引定位"的方式使用局部变量表,索引值的范围从0开始到局部变量表最大的Slot数量.

如果执行的是实例方法,那局部变量表的第0个Slot中存放的是指向方法所属对象实例的引用(可以用this访问到当前对象),其余参数分配按照参数顺序排列,占用从1开始,方法参数分配完成后,再根据方法体内部定义的变量顺序和作用域分配其余的Slot.另外,Slot是可以重用的,如果当前程序计数器中记录的字节码指令地址已经超出某个变量的作用域,那这个变量对应的Slot可以交给其他变量使用.

 

2.2.2 操作数栈

2.2.2.1 操作数栈也称为操作栈(后入先出),操作数栈的最大"深度"(栈说的就是深度,局部变量表说的是容量)在编译器编译阶段就已经分配完成,并且写入方法的Code属性max_stacks,在方法执行的任何时候,都不会超过操作栈的最大深度.其中,32位的数据类型所占操作栈容量为1,64位数据类型所占栈容量为2.编译器在编译程序代码的时候,必须保证操作数栈中元素的数据类型与字节码指令的序列"严格"匹配,在类校验阶段的数据流分析中还要验证这一点.

2.2.2.2 操作数栈执行过程:当一个方法开始执行的时候,这个方法的操作数栈是空的.在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容(入栈和出栈).例如,int类型的加法运算(int a=98;int b=2;int c=a+b),先使用iload_0和

iload_1指令将两个int型局部变量(98和2)推送至操作数栈中,然后执行iadd加法指令(将操作数栈顶两个int操作数出栈,相加计算结果,然后并把计算结果入操作数栈栈顶),最后使用istore_2指令,将操作数栈顶的int型数值出栈,并存入局部变量表的第2个Slot中.

2.2.2.3 在Java虚拟机的概念模型中,两个栈帧是相互独立的.但是在实际情况中,有些虚拟机的实现中可以令两个栈帧出现重叠,实现数据共用(让下面栈帧的操作数栈与上面的局部变量表重叠在一起,无需进行额外的参数复制传递).另外,Java虚拟机的解释执行引擎被称为"基于栈的执行引擎",这里的栈就是操作数栈.

 

2.2.3 栈帧信息

2.2.3.1 栈帧信息:在实际开发中,我们把动态连接,方法返回值,附加信息全部归为一类,叫栈帧信息.

2.2.3.1.1 动态连接:每一个栈帧中都有一个指向运行时常量池的引用,该引用指向栈帧所对应的正在执行的方法所属类的运行时常量池.(这句话在zzm的jvm深入理解里面翻译是错误的,原英文是The reference points to the constant pool for the class of the method being executed for that frame.)

持有这个引用就是为了支持在方法调用过程中实现动态连接.动态连接是相对于"静态分析"来说的.在类加载阶段和第一次使用符号引用的时候,把符号引用转换为直接引用的转化就叫做"静态解析".

动态连接是在程序执行的时候,将符号引用转化为直接引用,这叫动态连接.

2.2.3.1.2 方法返回值:方法调用返回有两种方式,一种是正常调用完成(Normal Method Invocation Completion),一种是异常调用完成(Abrupt Method Invocation Completion,英文原意是突然,异常阻断).

对于正常调用返回,如果有返回值,会将方法返回值返回到方法调用者(方法的返回值和返回类型由对应指令确定,如返回int类型,对应指令是ireturn).在正常调用返回时,当前栈帧需要帮忙恢复调用者的栈帧的局部变量表和操作数栈,把返回值压入

调用者栈帧的操作数栈中,并调整调用者的程序计数器的值指向方法调用完成后的下一条指令地址.

如果是异常调用完成(如虚拟机内部出现异常,或者方法调用中使用athrow指令显式抛出异常),如果异常未被当前方法捕获,方法就会退出,不会向调用者返回任何值.

2.2.3.1.3 附加信息:虚拟机规范中允许在具体的虚拟机实现中,可以增加一些规范里没有描述的信息到栈帧中,如调试相关的信息.这些信息叫附加信息.

 

2.3 本地方法栈

在Java虚拟机中,没有规定本地方法栈的具体实现(也可以不实现).Java虚拟机一般使用C-linkage模型实现Java本地调用(JNI),因此我们把本地方法栈也叫"Cstacks".本地方法栈也是线程私有的,同线程的生命周期相同.

它服务于本地方法(Native Method),本地方法(Native Method)可以反过来调用虚拟机中的Java方法,在这种情况下,线程会离开本地方法栈,在Java虚拟机栈上开辟一个新的栈帧.

 

2.4 非堆内存

非堆内存包含永久代(Permanent Generation)和代码缓存区(Code Cache).

2.4.1永久代(Permanent Generation)中包含两部分,一部分是方法区(Method Area),一部分是字符串常量(interned strings,被拘禁,被固定的字符串--字符串常量).

2.4.1.1 方法区(Method Area):方法区随着虚拟机的启动而创建(The method area is created on virtual machine start-up),它存储了每个类的信息,比如,

①类加载器的引用(Classloader Reference)

②运行时常量池(字符串常量,数值型常量,类引用,成员变量引用,实例方法引用等)

③成员变量数据(成员变量名,类型,修饰符,属性表):包含实例变量和类变量(static,静态变量)

④成员方法数据(方法名,返回值类型,参数类型(按顺序),修饰符,属性表)

⑤方法代码:经过编译器编译成字节码指令后,存放在方法属性表集合(attributes)中一个名为Code的属性中,Code中包含(字节码,操作数栈大小,局部变量大小,局部变量表,异常表[开始点,结束点,异常处理代码的程序计数器(PC)偏移量,被捕获的异常类对应的常量池下标]).

所有线程共享同一个方法区,因此访问方法区数据的和动态链接的过程必须线程安全的。如果两个线程试图访问一个还未加载的类的字段或方法,必须只加载一次,而且两个线程必须等它加载完毕才能继续执行。

2.4.1.2 驻留字符串(字符串常量):在JDK1.7的HotSpot中,已经把字符串常量部分移除了方法区.

2.4.2 代码缓存区(Code Cache)用于编译和存储那些被 JIT编译器编译成原生机器码的方法。Java字节码是解释执行的,但它没有在JVM的主机CPU上执行机器码那么快.为了提升性能,Hotspot VM会找到执行频繁的热点代码,并把它们编译成本地代码,保存在非堆内存的代码缓存区中.

 

2.5 堆内存

堆被用来在运行时分配类实例、数组.数据和对象不能在Java虚拟机栈上分配,因为栈帧被设计为创建以后无法调整大小,栈帧只存储指向堆中对象或数组的引用.

对象总是堆上分配,只能由垃圾回收器回收.堆是垃圾收集器管理的重点区域.

为了支持垃圾回收机制,堆被分为了下面三个区域:新生代(Young Generation,经常被分为 Eden 和 Survivor[From Survivor空间和To Survivor空间]),老年代(Old Generation),永久代(Permanent Generation).

 

  • 大小: 119.4 KB
分享到:
评论

相关推荐

    java虚拟机运行时数据区分析

    Java虚拟机运行时数据区分析 Java虚拟机(JVM)是一种抽象的计算机,它提供了一个运行Java字节码的环境。JVM将Java源代码编译为字节码,并在运行时执行这些字节码。为了更好地理解JVM的工作原理,我们需要了解JVM的...

    Java虚拟机运行时数据区域汇总

    在深入学习Java编程语言的过程中,理解Java虚拟机(JVM)的运行时数据区域是至关重要的。JVM的运行时数据区是程序运行时存储数据的地方,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆以及方法区。以下是这些...

    Java虚拟机规范中文版.pdf

    Java虚拟机(JVM)是实现Java技术的关键组件,它为Java程序提供了一个运行环境。Java程序在编写后会被编译成一种称为字节码的中间表示形式,这种字节码可以跨平台运行,因为JVM负责将字节码转换成机器代码。JVM的...

    java虚拟机

    Java虚拟机(JVM,Java Virtual Machine)是Java平台的核心组成部分,它负责执行Java程序,为Java代码提供了跨平台的运行环境。Java虚拟机的概念始于Sun Microsystems,现在由Oracle公司继续发展和维护。JVM的设计...

    Java虚拟机规范中文版

    《Java虚拟机规范》是Java技术的核心文档之一,它详细描述了Java虚拟机(JVM)的行为,包括其内部结构、数据类型、执行模型、指令集、运行时数据区、垃圾回收机制和安全管理等内容。该规范是Java平台实现的基石,对...

    Java运行原理与Java虚拟机.pdf

    ### Java运行原理与Java虚拟机 #### 一、Java运行原理概述 Java作为一种跨平台的编程语言,其独特之处在于它的编译和解释过程。Java程序的执行涉及到两个主要步骤:首先是编译阶段,其次是解释执行阶段。 1. **...

    Java虚拟机内存管理总结

    Java虚拟机内存管理总结 Java虚拟机(JVM)中的内存管理是指Java语言中对象的分配和释放问题。Java中的内存管理可以分为两部分:对象的分配和释放。 对象的分配是由程序完成的,程序员需要通过关键字new为每个对象...

    java虚拟机的详细原理

    1. **启动**:当一个包含`public static void main(String[] args)`方法的类被加载时,Java虚拟机就会启动。`main()`方法是程序的入口点,Java虚拟机通过调用这个方法来开始执行程序。 - **主方法**:`main()`...

    JDK15java虚拟机规范

    运行时数据区域包括PC寄存器、Java虚拟机栈、堆、方法区、运行时常量池和本地方法栈。PC寄存器存储下一条将要执行的指令地址。Java虚拟机栈存储局部变量和方法的调用信息。堆是运行时数据区,存储所有对象的实例。...

    JAVA虚拟机解读入门

    《JAVA虚拟机解读入门》是一本面向初学者的指南,旨在带领读者深入理解Java虚拟机(JVM)的工作原理和内部机制。JVM是Java语言的核心组成部分,它为Java程序提供了一个跨平台的运行环境,使得“一次编写,到处运行”...

    Java 虚拟机.pdf

    Java 虚拟机(JVM)是Java编程语言的核心...总结来说,理解JVM的运行时数据区域、垃圾收集机制以及相关参数设置对于优化Java应用的性能至关重要。开发者需要根据应用的具体需求调整JVM配置,确保程序高效、稳定地运行。

    深入java虚拟机笔记

    ### 深入Java虚拟机知识点总结 #### 第一章 Java体系结构介绍 - **Java体系结构概述**:本章主要介绍了Java体系结构的基本概念及其组成部分。Java体系结构旨在为开发者提供一个统一、高效且跨平台的应用开发环境。...

    java虚拟机.doc

    Java虚拟机 Java虚拟机(Java Virtual Machine,JVM)是Java技术栈的核心组件之一。它负责将Java字节码文件转换为机器码,并执行这些机器码以实现...这些区域都是Java虚拟机运行所必需的,它们之间的关系紧密相连。

    Java虚拟机规范 深入java虚拟机

    《Java虚拟机规范》是Java开发人员理解和优化Java应用程序的关键资源。它详细阐述了Java虚拟机(JVM)的工作原理,包括内存管理、类加载机制、字节码执行以及垃圾回收等核心概念。深入理解这些知识点对于提升程序...

    Java虚拟机规范SE8英文

    - **类型与Java虚拟机**:指令集设计考虑了不同类型的数据操作。 - **加载和存储指令**:用于从局部变量表或栈中加载值或将值存储到局部变量表或栈中。 - **算术指令**:执行基本的算术运算,如加减乘除等。 - **...

    Java虚拟机的安装程序

    4. **运行时数据区**:JVM划分了不同的内存区域,包括堆、栈、方法区、程序计数器、本地方法栈等。其中,堆是对象实例的存储区域,栈则用于存储方法调用的信息。 5. **执行引擎**:这是JVM的核心,负责解释或即时...

    深入java虚拟机 高清pdf 高清高清高清

    它详尽地探讨了Java虚拟机的工作原理、内存管理、类加载机制、字节码执行以及性能优化等多个核心主题,旨在帮助开发者提升程序的运行效率和稳定性。 1. **Java虚拟机概述**:Java虚拟机是Java平台的核心组件,它...

Global site tag (gtag.js) - Google Analytics