1. JVM组成

1.1 程序计数器(Program Counter Register)
(1) 一小块内存空间
(2) 线程私有:由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,在任何一个确定的时刻,一个处理器都只会执行一条指令,因此每条线程都需要一个独立的程序计数器,各个线程互不影响,独立存储
(3) 此区域是唯一一个不会出现OutOfMemoryError的区域
1.2 虚拟机栈(Virtual Machine Stacks)
(1) 线程私有,生命周期与线程相同
(2) 是java方法执行的内存模型:每个方法在执行的同事都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
(3) 局部变量表:存放编译期的基本类型、对象引用,其中long和double占用2个局部变量空间(Slot),其余只占用1个。
(4) 在方法运行期间,局部变量空间是完全确定的,不会改变。
(5) 这个区域出现两种异常:StackOverflowError(线程请求的栈深度大于虚拟机所允许的深度) 和 OutOfMemoryError(扩展时无法申请到足够内存)
1.3 本地方法栈(Native Method Stack)
(1) 与虚拟机栈相同,区别是为使用到的native方法服务
(2) HotSpot虚拟机把本地方法栈和虚拟机栈合二为一
(3) 同样会出现两种异常:StackOverflowError 和 OutOfMemoryError
1.4 方法区(Method Area)
(1) 与堆一样,各个线程共享区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
(2) 别名Non-Heap
(3) 抛出异常:OutOfMemoryError
1.5 运行时常量池(Runtime Constant Pool)
(1) 方法区的一部分
(2) 存储常量的地方
(3) 抛出异常:OutOfMemoryError
1.6 堆(Heap)
(1) 虚拟机管理的内存中最大一块内存
(2) 所有线程共享的一块区域
(3) 是垃圾回收的主要区域(Garbage Collected Heap)
(4) 细分为:新生代和老年代;再细分:Eden空间、From Survivor空间、To Survivor空间等
(5) 从内存分配角度看:线程共享的堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)
(6) 通过-Xmx 和 -Xms控制
(7) 抛出异常:OutOfMemoryError
1.7 直接内存(Direct Memory)
(1) 不是虚拟机运行时的一部分,也不是java虚拟机规范中定义的内存区域。但是会频繁使用
(2) NIO中DirectByteBuffer对象作为这块内存的引用进行操作。避免了在java堆和Native堆中来回复制数据
(3) 抛出异常:OutOfMemoryError