虚拟机栈 JVM stack
- 线程私有
- Java方法执行的内存模型,每个方法对应栈帧stack frame,方法调用过程,对应着入栈与出栈;
- 栈帧存储,局部变量表,操作数栈,动态链接,方法出口等。
-
局部变量表: Java 8种基本类型,reference类型,returnAddress类型。
- 局部变量表所需内存空间在编译期确定,方法运行期间,不改变局部变量表大小。
- 64位 long和double 占用两个 局部变量空间slot,其余类型占用一个空间。
-
错误:
- stackoverflow error, 线程请求栈超过VM允许范围。
- OutOfMemoryError, 栈动态扩展失败,无法申请到足够内存。
本地方法栈 NativeMethodStack
- 为Native方法服务
- 可以多种语言实现
- StackOverflowError 和 OutOfMemoryError
堆 Heap
- JVM 规范规定,Heap处于不连续的内存空间中,只要逻辑上连续即可。
- 线程共享,JVM启动时创建,对象实例和数组都在堆上分配。
- 多个线程私有的Heap区域, Thread Local Allocation Buffer (TLAB)
- TLAB在Eden区,目的,减少线程共享。
- 分为年轻代 Young Generation 和 老年代 Old Generation,比例 1:2;
- 年轻代分为 :Eden区 和 两个Survivor区, 比例: 8:1:1;
- 年轻代GC采用复制算法
- 老年代GC采用 mark sweep 和 mark compact
- 控制参数: -Xms -Xmx
- 抛出 OutOfMemory Error
方法区 Method Area
- Java 7 永久代 Permanent Generation;
- JVM规范描述的Heap的一个逻辑部分;
- 线程共享;
- 存储VM 加载的类信息,常量,静态变量。 即时编译器编译后的代码等。
- 方法区主要回收 常量和无用的类。
- Java 8 元空间 Metaspace 。
运行时常量池
- Java8 移到Heap中,
- class 文件中 constant pool table;
- 存放 各种字面量和符号引用,具备动态性,申请不到空间会抛出 OutOfMemoryError,
- 参数: -XX:MaxPermSize
- String.intern() 可以将新的String常量放入池中。
直接内存 Direct Memory
- 不是虚拟机运行时数据区的逻辑组成部分,
- NIO中 DirectByteBuffer对象, 作为直接内存的引用进行操作,减少Heap和Native堆上来回复制数据。
程序计数器 Program Counter Register
- 线程私有,
- 当前线程执行的字节码的行号指示器,
- 无OutOfMemoryError的区域。
参考资料:
- 《深入理解Java虚拟机》
- 《Java性能权威指南》