Java虚拟机运行时数据区

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。
Java虚拟机运行时数据区

1.Java堆(线程共享)

  Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存在对象的实例,几乎所有的对象实例和数组都在这里分配内存。
  Java堆是垃圾回收器管理的主要区域,很多时候也称为”GC’‘堆。由于现代收集器基本采用分代收集算法,所以Java堆还可以细分为:新生代和老年代。再细致一点新生代还可以分为Eden空间、From Survivor空间和To Survivor空间。(这一部分在另一章垃圾回收算法会细讲)
  Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。如果在堆中没有内存可以完成实例分配,并且堆也无法扩展,将会抛出e

2.方法区(线程共享)

  方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。它用于存储已经被虚拟机加载的类信息、常量、静态变量(static)、即时编译器编译后的代码等数据。这个区域垃圾收集行为比较少出现,但并非数据进入方法区就永久存在。这个区域内存回收的主要是针对常量池的回收和对类型的卸载。根据虚拟机规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
  运行时常量池(Runtime Constant Pool)是方法区的一部分。受方法区限制当常量池无法满足内存分配需求时,将抛出OutOfMemoryError异常。JDK1.7及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。同时在 jdk 1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域

3.Java虚拟机栈(线程私有)

  Java虚拟机栈是线程私有的,它的生命周期和线程相同,描述的是Java方法执行的内存模型。每个java方法在执行的时候都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用到结束,都对应着一个栈帧在虚拟机栈中入栈和出栈的过程。当线程请求的栈的深度大于虚拟机所允许的深度将抛出*Error异常,当扩展无法申请到足够的内存会抛出OfMemoryError异常。

4.本地方法栈(线程私有)

  本地方法栈和虚拟机栈发挥的作用非常相似,区别在于虚拟机展执行Java方法(字节码)服务,本地方法栈则为虚拟机使用的Native服务。本地方法栈也会抛出*Error和OutOfMemoryError异常。

5.程序计数器(线程私有)

  程序计数器是一块比较小的内存空间。是当前线程执行字节码文件的行号指示器。每个线程都会有一个独立的程序计数器。字节码解释器是工作就是通过改变这个计数器的值来选择需要执行的字节码指令,分支、循环、跳转、异常处理、线程回复等基础功能都需要依赖程序计数器完成。
  如果线程正在执行一个Java方法,程序计数器记录的是正在执行的虚拟机的字节码指令的地址;如果正在执行Native方法,程序计数器值则为空。
该区域是唯一一个虚拟机规范中没有规定任何OutOfMemoryError情况的区域