栈: 栈内存、虚拟机栈、或者说是虚拟机栈中的局部变量表。
用于存放编译期可知的各种 基本数据类型、对象引用类型[ 她可能是一个引用指针、也可能指向一个代表对象的句柄 ]
局部变量表所需的内存空间在编译器完成分配。本地方法栈:为虚拟机找到的native方法服务
堆:虚拟机栈内存最大的一块,启动时候创建,所有线程共享的内存区域,此内存区域的唯一目的就是存放对象实例、
[虚拟机规范中描述:所有的对象实例以及数组都要分配在堆上],物理上不连续的内存空间,
堆是gc管理的主要区域,采用分代收集算法,[年轻代、老年代、持久代] (分代是为了更好的回收内存|更快的分配内存)
通过-Xmx -Xms来配置
年轻代 -> [Eden区 Survivor区(from、to 大小严格一致)]
新的对象首先放在Eden区,Survivor区作为Eden和Tenure(终生代)的缓冲,可以向Tenure转移活动的对象。
Tenure中存放生命周期长久的对象
Young和Tenure组成了堆内存红色部分是容易混淆的,我们来看一个堆 OOM的监控截图
方法区:与堆一样,是一个线程共享的内存区域,他用于存储已经被虚拟机加载的类、常量、静态变量、即时编译器变异后的代码等。
虚拟机规范把方法区描述为堆的一个逻辑部分,但他有一个别名叫 NonHeap(非堆) 有人称为永久代(Permanent Generation)
垃圾收集行为在这个区域出现得比较少, 主要的回收目标是针对常量池的回收和对类型的卸载。
运行常量池:方法区的一部分,Class文件中还有一项常量池,用户存放编译期生存的各种字符量和符号引用,
这部分内容在类加载后存放到方法区的运行时常量池(PS 运行期间将新的常量放入池中用 String.intern())直接内存:并不是虚拟机运行时数据区的一部分,但这部分内存被频繁的使用,也可能导致OOM。