jvm运行时数据区域

jvm在执行Java程序时,会把它所管理的内存划分为若干个不同的数据区域:

  • 程序计数器:是一块较小的内存空间,记录正在执行的虚拟机字节码指令的地址。如:线程切换后能恢复到正确的执行位置,因此每条线程都需要一个独立的程序计数器。如果线程执行的是一个Java方法,则计数器记录得是正在执行的虚拟机字节码指令的地址;如果执行的Native方法,这个计数器值则为空(Undeifined)。此内存区域是唯一一个没有规定任何OutOfMemoryError(OOM)情况的区域。
  • Java虚拟机栈:描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成对应着一个栈帧在虚拟机栈中入栈到出栈的过程。局部变量表存放了编译器可知的各种哥基本数据类型、对象引用(reference类型,不等同于对象本身)等。其中64位长度的long和double类型的数据会占用两个局部变量的空间(Slot),其余的数据类型只占用一个。

         局部变量表所需的内存空间在编译期间完成分配,局部变量所需空间是完全确定的,方法运行期间不会改变局部变量表的大小。

         两种异常:StackOverflowError,线程请求的栈深度大于虚拟机所允许的深度。当前大部分虚拟机栈都可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

  • 本地方法栈:作用类似于虚拟机栈,虚拟机栈为执行的Java方法(也就是字节码)服务,本地方法栈为虚拟机使用到的Native方法(虚拟机规范中对本地方法使用的语言、使用方式于数据结构并无强制规定)服务。异常类型同上。
  • Java堆:线程共享,用于存放对象实例。在物理上内存空间不必一定连续,逻辑上连续即可。异常类型:OOM
  • 方法区:线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。异常类型:OOM
  • 运行时常量池:方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池,用于存放编译期生成的各种字面量和符号引用。运行时常量池还具备一个重要特征是动态性,Java语言并不要求常量只有编译期才能产生,运行期间也可能将新的常量放入池中,如String的intern()方法。
  • 直接内存:NIO可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
原文地址:https://www.cnblogs.com/jixiegongdi/p/13410027.html