一、运行时数据区域
1.1、程序计数器
.class文件也叫字节码文件,是虚拟机解释运行的目标文件。程序计数器就是当前线程所执行的字节码的行号指示器,属于线程私有的一块小内存。当多线程来回切换时,使用程序计数器能正确的恢复到之前执行的位置。
如果正在执行Java方法,则程序计数器记录的是正在执行的字节码指令的地址;如果是native方法,则记录空(Undefined);此区域是唯一一块不会OutOfMemoryError(OOM)的内存区域
1.2、Java栈
Java栈也是线程私有的,与线程生命周期相同,有时候也可以称为 '方法栈'。
每个方法被执行时都会生成一个栈帧,用来保存局部变量、操作数栈等。
方法调用时会产生两种异常,当调用深度大于Java虚拟机设定的阈值时会抛出StackOverflowError;当方法执行时,内存不够分配时,会抛出OutOfMemoryError异常。
Java栈分为Java虚拟机栈与本地方法栈:
- Java虚拟机栈:服务于Java方法
- 本地方法栈:服务于本地方法。native 方法
1.3、Java堆(Java Heap)
Java堆属于Java虚拟机所管理的内存最大、最核心的内存区域;此区域为所有线程共享,也是垃圾回收器最主要的工作对象。
几乎所有的对象实例都在堆上分配内存,也有很少的对象实例会在栈上分配。
从内存回收的角度看,堆又分为新生代与老年代;再细致可分为Eden区、From Survivor区、To Survivor区等
从内存分配的角度看,Java堆可分为多个本地线程分配缓冲去(Thread Local Allocation Buffer,TLAB)。
1.4、本地方法区(Non-Heap)
- 存储类信息、常量、静态变量、即时编译后的代码等
- 线程共享
- 也被称为"永久代"
1.5、运行时常量池
属于本地方法区的一部分
1.6、直接内存
并不属于Java虚拟机运行时的数据区域的一部分,但是也会频繁的使用,也会导致OOM。例如java的NIO