Java虚拟机中空间组成分为

1.程序计数器 2.Java虚拟机栈  3.本地方法栈 4.Java堆 5.方法区 6.直接内存


1、程序计数器

程序计数器是属于每个线程独占的一块较小内存空间,可以看作线程所执行的字节码的行号指示器,用于改变计算器值来选取下一条需要执行的字节码指令。

这类线程独占的内存区域成为“线程独有”,同样线程独占的还有Java虚拟机栈

Java方法在计数器中是以字节码指令地址的形式存在,而Native方法则以空的形式存在。

程序计数器是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError(OOM)的内存区域。


2、Java虚拟机栈

与程序计数器器相同,Java虚拟机栈也是属于线程独占的区域,每一个线程都会有一个独有的Java虚拟机栈。值得注意的是在Java虚拟机中,内存结构远没有平时认为的以 堆+栈 这种结构存在这么简单,栈也分为 Java虚拟机栈和本地方法栈。而往往提到的栈指代的是Java虚拟机栈中的局部变量表

Java虚拟机栈由 1.局部变量表 2.操作数栈 3.动态链接 三部分组成。常见所说的存放局部变量的栈指的的就是Java虚拟机栈中的局部变量表。

Java虚拟机栈是存在一定的深度限制,当超出限制时会触发StackOverFlowError异常。

而当Java虚拟机栈无法申请到内存时,则会抛出OOM异常。


3、本地方法栈

本地方法栈是不同与Java虚拟机栈服务于Java方法,本地方法栈是服务于Java虚拟机中的Native方法,其构造及功能类似于Java虚拟机栈。


4、Java堆

Java堆是虚拟机所管理的最大内存的,属于所有线程共享的一块区域,在虚拟机启动时创建,所有的对象实例以及数组在堆上分配(现在而言是不一定的,因为有了发展与逃逸分析技术、栈上分配、标量替换优化技术)

同时Java堆也是GC回收的主要工作区域。


5、方法区

方法区在Java虚拟机官方规范中称为堆的一个逻辑部分,但为了与堆做出区别,将方法区称为Non-heap(非堆)。

方法区与堆一样,都是属于所以线程共享的一块内存区域。

用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译的代码等。

GC可以工作但难以工作的区域(因为均为常量?)

5.1、运行时常量池

方法区的一部分,是类加载后存放类编译期生成的各种字面量和引用的地方。


6、直接内存

直接内存是属于New IO类中进行操作的一片新申请的内存空间,通过Java堆中的DirectByteBuffer对象引用并使用这片内存空间。

比较特殊的是这片空间并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存空间,是使用Native方法直接分配堆外内存,但这片空间同样可能会出现OOM情况。


 

KAI Java