虚拟机栈:线程私有。通常所说的“栈”,java方法执行的线程内存模型,每个方法被执行时,java虚拟机都会创建一个栈帧,存储局部变量表(各种基本数据类型,对象引用),操作数栈,动态链接,方法出口等。
每个方法从调用到执行完毕,对应着一个栈帧在虚拟机中从入栈到出栈的过程。
本地方法栈:线程私有。服务于虚拟机使用到的本地方法。《java虚拟机规范》对本地方法栈中方法使用的语言,方式及数据结构等没有规定,由各虚拟机自行实现。Hot Spot虚拟机将本地方法栈和虚拟机 合 二为一了。
堆:线程共有。存放对象实例。通常所说的“堆”。所有对象实例及数组都应该在堆上分配。 不过由于即时编译器,以及逃逸分析技术的强大,栈上分配,标量替换等优化手段 使得所有实例对象都在堆上分配也不那么绝对了。
对象实例的堆内存分配: 指针碰撞,空闲列表。
方法区:线程共有。存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。jdk8之前,具体来说,在jdk6及之前的版本中,HotSpot虚拟机把垃圾收集的分代设计扩展到方法区,并使用永久代来实现方法区。jdk7的hotspot,将原本放在永久代的字符串常量池,静态变量等移出了。到了jdk8,则完全废除了永久代的概念。将jdk7中永久代还剩余的部分,主要是类型信息,全部移到了元空间中。
运行时常量池: 方法区的一部分。Class文件中除了类的版本,字段,方法,接口等描述信息外,还有常量池表,用于存放编译器生成的各种字面量与符号引用,这部分内容在类加载后会存到方法区的运行时常量池中。运行池相较于Class的常量池,据有动态性。不仅可以保存编译期产生的常量,运行期间也可以将新的常量放入池中。这种特性 ,用的多的为 String.intern()方法。
直接内存:直接内存并不是java虚拟机运行时数据区的一部分,也不是《java虚拟机规范》中定义的内存区域。也叫堆外内存。不过这部分内存也被频繁的使用,也可能导致OOM.