1.程序计数器(PC)
是一块较小的内存区域,可以看做用来记录线程当前所执行的字节码的行号。每个线程都会有一个程序计数器。
如果线程执行的是一个java方法,则这个计数器记录的是正在执行的字节码指令的地址;如果执行的是native方法,则其记录的值为null。
2.虚拟机栈
和程序计数器一样,虚拟机栈也是每个线程私有的。
虚拟机栈描述的是java方法执行的内存模型。
关于栈帧:
每进入一个java方法,会创建一个栈帧。栈帧存储了局部变量表(包括各种基本数据类型和对象引用)、操作数栈、动态链接、方法出口等信息。
异常情况:
如果线程执行的方法层级过多,导致栈的深度大于虚拟机允许的最大深度,会抛出StackOverflowError。
另一种情况,如果虚拟机开启了虚拟机栈的动态扩展,但是内存不足,会抛出OutOfMemoryError。
3.本地方法栈
基本和虚拟机栈一样,只不过它描述的是native方法的内存模型。
4.java堆
java堆是所有线程共享的一块内存区域,在虚拟机启动时创建。
用来存放对象示例,几乎所有对象的实例都在这块内存空间里面存储。它是垃圾管理器GC的主要区域。从内存回收的角度可以分为新生代和老生带。
java虚拟机规范中描述:所有的对象实例以及数据都要在堆上分配。但是这并不绝对。
5.方法区
是所有线程共享的内存区域。
用来存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虚拟机规范中,它属于堆的一个逻辑组成部分。
别名也叫非堆、永生带、永久带。
6.运行时常量池
属于方法区的一部分。用来存储class文件中的常量信息。
7.直接内存
属于堆外内存空间。在NIO中,一如了一种基于通道(channel)与缓冲区(buffer)的I/O方式,它可以使用native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。避免了在java堆和native堆中来回复制数据。它也已有OutOfMemoryError出现。