Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分成若干不同的数据区域,这些区域各有各的用途,以及创建和销毁的时间。
根据《Java虚拟机规范》规定,Java虚拟所管理的内存将会包含以下几个运行时数据区域。
- 程序计数器
- Java虚拟机栈
- 本地方法栈
- Java堆
- 方法区
- 运行时常量池
程序计数器(Program Counter Register)
程序计数器是一块较小的内存空间,它可以当成是当前线程所执行的字节码的行号指示器。通过改变这个程序计数器的值来选取下一条需要执行的字节码指令,这个计数器还可以完成分支、循环、跳转、异常处理、线程恢复等基础功能。
—
我们所知的Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,因此,在任何一个确定时刻,一个处理器只会执行一条线程的指令。那么线程切换后是如何恢复到正确位置呢?,因此各个线程都需要一个”线程私有”的区域————程序计数器。Java虚拟机栈(Java Virtual Machine Stacks)
Java虚拟机栈描述的是Java方法执行的内存模型。每个方法在执行时会创建一个栈帧(Stack Frame)用于储存局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用至执行完成的过程,对应一个栈帧在虚拟机栈中入栈到出栈的过程。
—
经常会有人把内存区分为堆内存(Heap)和栈内存(Stack),其实Java内存区域的划分实际上远比这个要复杂但来说一下,这个栈内存指的就是虚拟机栈,或者说是虚拟机栈中局部变量表部分。本地方法栈(Native Method Stack)
本地方法栈与上面的虚拟机栈所发挥的作用是非常相似的,不过虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用的Native方法服务。
- Java堆(Java Heap)
Java堆的唯一目的就是存放对象实例,几乎所有的对象实例都在这分配内存(包括数组)。
它是Java虚拟机所管理的内存中最大的一块,被所有线程所共享,且在虚拟机启动时创建。 - 方法区(Method Area)
方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT)编译后的代码等数据。
虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名——Non-Heap(非堆),目的应该就是与Java堆区分开来。 运行时常量池(Runtime Constant Pool)
Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这一部分内容将在类加载后进入方法区的运行时常量池中存放,因此,运行时常量池是方法区的一部分。