JVM的内存区域
-
运行时数据区域
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。主要分为堆、虚拟机栈、本地方法栈、程序计数器、方法区。按照线程是否私有划分:分为线程私有区域和线程共享区域。线程公有区域:堆、方法区。线程私有区域:虚拟机栈、程序计数器、本地方法栈。 -
虚拟机栈
虚拟机栈具有先进后出的数据结构(FILO,first-input-last-output),是基于线程的,在线程运行方法的过程中,虚拟机栈存储当前线程运行方法所需的数据、指令、返回地址,栈的生命周期和线程是一样的。在虚拟机中,栈的默认大小是1M(大部分操作系统),可通过-Xss调整大小。
线程在执行方法的时候,每执行一个方法,就会生成一个栈帧,并入栈,一旦方法执行完毕,则出栈。栈帧分为四个区域:局部变量表、操作数栈(类比虚拟机的高效缓存区)、动态连接、返回地址。
局部变量表:存放局部变量(即方法中申明的变量)。
操作数栈:首先它是栈。是JVM执行引擎的工作区域。方法的执行前后,它都是空的。
动态连接:应对多态
返回地址:程序未发生异常,返回程序计数器中的地址;程序发生异常,返回异常处理器表确定的地址 -
程序计数器
当前线程执行字节码的行号指示器。JVM中唯一不会OOM的区域。 -
本地方法栈:与虚拟机栈功能类似,JVM执行本地方法时管理本地方法的调用。概念上是两个区域,但是可以认为是一个区域,HotSpot将这两区域合二为一了。
-
方法区
JVM对内存的逻辑划分,JDK7之前,用永久代实现的方法区,JDK8是以元空间实现。永久代使用的是虚拟内存,元空间使用的是本地内存(每个项目的不一致导致JVM无法判断,方法区应该设置多大,元空间解决了此烦恼) -
堆
JVM中最大的内存区域,程序员申请的几乎所有的对象都存在于堆中(遵循逃逸规则的小对象会在栈中,这是JVM的一种优化) -
直接内存(堆外内存)
JVM申请内存区域,机器所剩余的内存叫直接内存。Unsafe、DirectByteBuffer等手段可以使用直接内存。