1. JVM中的 运行时内存区域 结构
方法区和堆是所有线程共享;PC寄存器,Java方法栈,本地方法栈是每个线程私有.
-
方法区
-
方法区Method Area是各个线程共享的内存区域,必须保证线程安全
如两个类要同时加载1个尚未被加载的类C,1个类会请求ClassLoader去加载类C,另1个类只能等待C加载完成而不会重复加载
-
方法区存储已被加载的类的信息,常量,静态变量,即时编译器编译后的代码等.
-
-
堆
- 堆是JVM管理的内存中最大的一块,被所有线程共享,在JVM启动时创建,非线程安全.
- 堆存在的目的就是为了存放对象实例.
- 堆是垃圾收集器管理的主要区域.从内存回收的角度看,现在的垃圾收集器都基于分代回收算法,Java堆可以进一步细分.
-
PC寄存器/程序计数器
- PC寄存器是一块较小的内存空间,用于记录当前线程正在执行的虚拟机字节码的地址;
- Java虚拟机的多线程是通过线程轮流切换分配处理器执行时间来实现,在任何1个确定时刻,一个CPU/多核CPU中的1个核只能执行1条线程的指令.
- 当有多个线程交叉执行时,被中断的线程当前执行到哪个字节码内存地址必然要保存下来,以便用于被中断的线程恢复执行时继续执行.每个线程都有一个独立的PC寄存器,多线程之间互不影响.
-
Java方法栈
-
Java方法栈是线程私有的,所以不需要关心数据一致性,也不存在同步锁问题.
-
每当创建1个线程,JVM就会为其创建对应的Java方法栈.
-
Java方法栈中包含多个栈帧.
- 每个栈帧关联了1个Java方法,每运行1个方法,就创建1个栈帧,栈帧包含了关联方法的信息.
- 每当1个方法执行完毕,该栈帧就会弹出栈帧的元素作为方法的返回值,并清理栈帧.Java方法栈的栈顶就是当前正在执行的方法,PC寄存器记录的也是这个地址.
- Java方法栈的栈顶的栈帧A调用新方法,会创建新的对应栈帧B压入栈顶,B执行完毕后,B被移除,B的返回值作为A的1个操作数,继续执行A
-
JVM规范规定了Java方法栈中的2中异常
- 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
- 如果虚拟机可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常
-
-
本地方法栈/Native Method Stack
- 本地方法栈Java方法栈所发挥的作用是非常相似的,其区别不过是Java方法栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务
- 本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常