天天看点

java虚拟机中运行时的内存分配

一、程序计数器

可以看做当前线程的字节码的行号指示器,根据指示器显示的值来执行下一条字节码指令,每一条Java虚拟机线程都有自己的pc寄存器,通过改变这个计数器的值来选取下一条需要执行的指令,分支、循环、跳转、异常处理等。任意时刻java虚拟机只会执行一个方法的代码,如果是native的寄存器的值为undefined(未定义),不是native方法寄存器的值为正在执行的虚拟机字节码指令的地址的地址。

二、虚拟机栈

JAVA虚拟机栈是线程私有的,他和生命周期和线程相同,JAVA虚拟机栈是虚拟机描述JAVA方法的内存模型,每个方法执行时会创建一个栈帧,栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用执行到执行对应着帧栈从入栈到出栈的过程。

2、1 局部变量表:

局部变量表属于java虚拟机栈的组成部分,用于存放各种编译期可知的数据类型,long和double占2个局部变量空间,其他数据类型(boolean,byte,char,short,int,float,reference,returnaddress)占用一个局部变量空间。

三、本地方法栈

本地方法栈与JAVA虚拟机栈的区别是,他是执行java方法的服务。java虚拟机实现过程中可能用到传统的C栈(C Stack)来支持native方法(用其他语言编写的方法),这个栈就是本地方法栈。HotSpot虚拟机直接把本地方法栈和JAVA虚拟机栈和二为一。

四、堆

堆提供一个可以供个个线程共享的内存区域,java虚拟机堆在虚拟机启动时就被创建了,几乎所有对象的分配都要在堆上分配,堆是垃圾回收期管理的主要区域,堆可以建立在物理上不连续的存储空间中,内存可扩展。

五、方法区

虽然在java虚拟机规范中将方法区规定为堆的逻辑组成部分,但是它有一个别名,(No Heap)非堆、就是用来将它 和堆区分开来。方法区用于存储虚拟机加载的类信息,常量,静态变量,既时编译后的代码等数据部分虚拟机对此区域不进行垃圾回收。

5、1 运行时常量池

运行常量池是方法区的一部分,用于存储编译期生成的各种字面量和符号引用。(各类被加载时会检查常量池中时候定位到类的符号引用,若没有则先加载到运行常时量池)

七、直接内存

直接内存并不是虚拟机运行时数据区域的一部分,也不是虚拟机规范中定义的内存区域。JDK1.4中新增了NIO(New Input/Output)类,引入一种基于通道与缓冲区(Buffer)的IO操作,可以使用Native函数库直接分配堆外内存。然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能。因为避免了在java堆和Native堆中来回复制数据。

如图所示:

java虚拟机中运行时的内存分配