jvm的内存结构, 以及各部分的功能
1. 程序计数器
- 线程私有, 相当于一个指针, 指向class文件, 字节码就是靠记录程序计数器的值, 实现程序的 分支, 循环 以及 线程的切换后恢复;
- 占用很小的内存空间, 它是jvm中唯一不会出现内存溢出的地方(Out Of Memory, OOM).
2.虚拟机栈
- 线程私有, 生命周期与线程相同, 描述的是Java方法执行的内存模型.
- 每个方法对应着一个栈帧, 存放着对象的引用, 8种基本类型数据等;
- 每个方法从被调用到执行完毕的过程, 就对应着一个栈帧在jvm入栈到出栈的过程;
- 当请求的栈深度超过了虚拟机栈所允许的深度, 会触发 StackOutFlowError.
3. 本地方法栈
- 与虚拟机栈功能相同, 只不过虚拟机栈是为class文件服务, 对应着Java方法; 而 本地方法栈对应着本地方法的调用;
- 凡是方法中带有 "native"关键字的,表明该方法是本地方法, 它通过本地方法接口(JNI)去调用本地方法库中具体实现方法.
4. 堆
- 线程共享的区域, jvm启动时创建;
- 存放着对象实例以及数组;
- GC管理的重点区域.
5. 方法区
- java6之前的版本存在此概念, 包含Class对象, 静态变量, 常量, 运行时常量池等数据;
- Java7逐渐淡化此概念, 常量池放在了堆中;
- Java8之后, 用MetaSpace(元空间)取代了方法区, 元空间使用的是直接内存, 由于直接内存很大, OOM概率降低了.