您的位置 首页 java

Java运行时数据区域

Java虚拟机 在执行Java程序的时候会把它所管理的内存划分为几个不同的数据区域。这些区域有各自不同的用途以及相应的创建和销毁时间,有的区域随着虚拟机进程的启动而存在,有些区域则是随着用户 线程 的启动和结束而建立和销毁。Java虚拟机规范规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域。

Java运行时数据区域

其中,堆和方法区是由所有 线程共享 的数据区;虚拟机栈、本地方法栈、 程序计数器 线程私有 的数据区。下面分别介绍各个分区。

Java 开发人员来说,Java堆(Java Heap)是我们经常听到的一个概念了,它是Java虚拟机所管理的内存中最大的一块,并且是所有线程共享的一块内存区域,在Java虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例。 Java虚拟机规范 对Java堆的描述是:“所有的对象实例以及数组都应当在堆上分配”(原文:The heap is the runtime data area from which memory for all class instances and arrays is allocated.)

Java堆跟垃圾收集器密切相关,更准确的说,Java堆是垃圾收集器管理的内存区域。Java堆经常会和“新生代”、“老年代”、“永久代”、“Eden区”等名词概念同时出现,这是因为从内存垃圾回收的角度来看,现代垃圾收集器大部分都是基于分代手机理论设计的。这些区域划分只是大部分垃圾收集器的共同特性或设计风格,并不是Java虚拟机具体实现的固有内存布局,且Java虚拟机规范中也没有对Java堆做这样的划分。随着技术的不断发展,垃圾收集器技术也有了很大发展,HotSpot里面也出现了不采用分代设计的新垃圾收集器,所以,类似这样的说法“Java虚拟机的堆内存分为新生代、老年代、永久代……”已经显得不太严谨了。

从内存分配的角度看,Java堆内存可以划分多个线程私有的分配缓冲区TLAB(Thread Local Allocation Buffer),这个在之前的文章也有提到过,TLAB是为了提升对象的分配效率。无论怎样划分,无论哪个区域,存储的都只能是对象的实例,划分的目的只是为了更好地回收内存或者更快地分配内存。

当前主流的Java虚拟机都是按照可扩展来实现Java堆的,启动Java虚拟机时,通过参数-Xmx和-Xms设定Java堆空间的最大值和最小值。如果Java堆中没有内存分配给新的对象,Java虚拟机将会抛出 OutOfMemory Error异常。

百度 翻译中,将heap翻译为:“堆;(凌乱的)一堆;大量;破旧的汽车;老爷车”。通过我们对Java堆的了解,是不是觉得这个命名特别贴切呢?

我们还是通过一张图来说明Java Heap。

Java运行时数据区域

上图中已对Java Heap做了相应的注解说明。其中有些关于垃圾回收的名词概念,简单解释如下:

  • Full GC:对整个Java Heap和方法区进行垃圾回收。
  • Minor GC:对新生代进行垃圾收集。
  • Major GC:对老年代进行垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另请注意:“Major GC”这个说法有点混淆,在有的资料上可能是指整堆收集,可结合上下文去理解。
  • CMS:全称Concurrent Mark Sweep,是在JDK5发布时,HotSpot推出的一款在强交互应用中可称为具有划时代意义的垃圾收集器。这款垃圾收集器是HotSpot虚拟机中第一款真正意义上支持并发的垃圾收集器,它首次实现了让垃圾收集线程与用户线程同时工作。

关于垃圾收集的详细内容,在这里先暂不展开,请大家持续关注后续文章。

方法区

方法区(Method Area)也是所有线程共享的内存区域,它有一个别名叫Non-Heap,目的是与Java Heap区分开来。方法区用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

方法区与永久代(Permanent Generation)的关系:本质上这两者并不是等价的。JDK8以前,HotSpot虚拟机设计者选择把垃圾收集器的分代设计扩展至方法区,这样使得垃圾收集器能够像管理Java堆一样管理这部分内存。对于其他虚拟机来说,是不存在永久代的概念的。因为这个原因,有极少数方法,例如 String .intern()方法,导致不同虚拟机下有不同的表现。到JDK8的时候,HotSpot已经完全废弃了永久代的概念,改用在本地内存中实现的Meta Space来代替。

相对而言,垃圾收集行为在方法区是比较少出现的,但并非数据进入了方法区就可以“永久”存在了。方法区内存回收目标主要是针对常量池的回收和对类型的卸载,通常回收效果较差,特别是类型的卸载条件很苛刻。

Java运行时数据区域

关于本地内存、直接内存的说明:

  • Java虚拟机在运行时对于虚拟机没有直接管理的物理内存,也会有一定的利用,这些被利用的物理内存成为本地内存。本地内存不受虚拟机内存参数的限制,只受物理内存容量的限制。

  • 直接内存不是虚拟机运行时数据区的一部分,是在Java堆之外,直接向系统申请的内存区域。直接内存使用NIO,通过存在堆中的Direct byte Buffer操作Native内存,读写性能高。直接内存不受 JVM 管理,但物理内存不足时还是报OutOfMemoryError异常。

  • Java程序内存 = Java堆内存 + 本地内存

虚拟机栈

Java虚拟机栈(VM Stack)是线程私有空间,其 生命周期 与线程相同。虚拟机栈体现了Java线程的内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame),用来存储 局部变量 表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。虚拟机栈示意图如下。

Java运行时数据区域

对应上图中栈帧结构各模块说明如下。

  • 局部变量表:用于存放int、long、 short float 、double、 char 、byte、 boolean 八种基本数据类型数值以及reference、returnAddress,主要是方法参数,以及方法体内的局部变量。存放以变量槽(slot)为最小单位(32bit),除double和long这两种基本数据类型需要2个slot存储(也因此会出现线程安全问题),其余几种可以用1个slot存储。基本数据类型存储数值本身,引用数据类型存储指向堆(Java Heap)内存的引用指针。returnAddress类型目前已经很少见了,它是为 字节码 指令jsr、jsr_w和ret服务的,指向了一条字节码指令的地址,某些很古老的Java虚拟机曾经使用这几条指令来实现异常处理时的跳转,但现在也已经全部改为采用异常表来代替了。局部变量表示意图如下。

Java运行时数据区域

  • 操作数栈:可以理解为PC寄存器,作为用于存储计算的临时数据存储区,当 CPU 执行load指令时能将数据加载进入操作数栈。在方法的执行过程中,会有各种字节码指令往操作数栈中写入和读取数据,也就是入栈和出栈操作。比如在做算术运算的时候通过将运算涉及的操作数压入栈顶后调用运算指令来进行的。还有在调用其他方法的时候,也是通过操作数栈来进行方法参数的传递。Java虚拟机的解释执行引擎被称为“基于栈的执行引擎”,这里所说的“栈”就是指操作数栈。

  • 动态链接:由于 OOP 思想中存在多态的概念,使得编译器在编译源代码时无法确定对象类型,只有在运行时才能确定对象,指向常量池中方法的引用。

  • 方法出口:记录方法结束时的出栈地址,可能是正常执行结束时的返回地址或者由于报错结束时的异常地址。一般来说,方法正常结束时,主调方法的PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个 计数器 值;而方法异常结束时,返回地址是要通过异常处理器表来确定的,栈帧中就一般不会保存这部分信息。

  • 附加信息:Java虚拟机规范允许虚拟机实现增加一些规范里没有描述的信息到栈帧之中,例如与调试、性能收集相关的信息,这部分信息完全取决于具体虚拟机的实现。只是在概念上,附加信息是栈帧结构的一部分。

本地方法栈

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是类似的,区别是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈是为虚拟机使用到的本地方法(Native Method)服务。HotSpot虚拟机是将本地方法栈与虚拟机栈合二为一。

程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。虚拟机字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖程序计数器来完成。

由于CPU在执行的时候会存在线程时间片切换的概念,所以CPU执行指令的时候是会中断的,程序计数器会记录当前线程执行停止的字节码指令位置(行号),以便于再次切换到该线程时能恢复到正确的执行位置。每个线程都需要有一个独立的程序计数器,各线程之间计数器互不影响,所以程序计数器所对应的内存区域是 线程私有 的。

最后,一图概览Java运行时数据区域。

欢迎大家点赞、收藏、发表评论···

文章来源:智云一二三科技

文章标题:Java运行时数据区域

文章地址:https://www.zhihuclub.com/174383.shtml

关于作者: 智云科技

热门文章

网站地图