Java通过多线程机制实现多任务并行处理。
所有线程共享JVM内存(main memory),同时线程又有自己的工作内存。
当线程与主存进行交互时,数据从主存复制到工作内存中,由线程进行处理。
JVM的逻辑内存模型中,包含如下几个部分:
1)程序计数器
2)虚拟机栈
3)本地方法栈
4)Java堆
5)方法区
一、程序计数器
程序计数器是一块较小的内存空间。它可以被理解为是当前正在执行的字节码指令的指示器。字节码解释器就是通过程序计数器来选取下一条要执行的字节码指令。程序的分支、跳转、循环、线程切换都依赖程序计数器。
Java是多线程的,但是在任一时刻,一个处理器内核只能执行一个线程中的指令。因此,为了线程切换后能够恢复到正常的位置继续执行,需要为每一个线程配备一个独立的程序计数器。
注意,程序计数器是JVM中唯一不会抛出OutOfMemoryError的内存区域。
二、虚拟机栈
与程序计数器一样,虚拟机栈也是线程私有的。虚拟机栈体现了Java方法执行的内存模型。每个方法执行前都会创建一个栈帧,用于存放局部变量表等信息。方法的调用到执行完毕的过程,就对应了一个栈帧从入栈到出栈的过程。
局部变量表所需的内存大小在编译期确定,在方法运行期间不会改变局部变量表的大小。
注意,当线程请求的栈深度超过虚拟机允许的最大栈深度时,会抛出StackOverflowError。如果栈深度可以动态扩展,当无法申请到足够的内存空间时,会抛出OutOfMemoryError。
三、本地方法栈
本地方法栈和虚拟机栈的功能是非常相似的,不同的是,本地方法栈是为native方法调用服务的。同时,本地方法栈也会抛出StackOverflowError和OutOfMemoryError。
四、Java堆
Java堆在虚拟机启动时创建,是被所有线程共享的一块内存。它的作用是存放对象实例。Java堆也是垃圾回收器管理的主要区域。注意,当没有内存可以创建对象实例,并且堆也无法再扩展时,会抛出OutOfMemoryError。
五、方法区
方法区用于存放类信息、静态变量、常量等数据。当方法区无法满足内存需求时,也会抛出OutOfMemoryError。