JVM内存模型
Java运行时数据区
Java虚拟机在执行Java程序的时候,会把它管理的内存区域分为多个部分,主要分为线程私有区和共享数据区两个部分。
方法区和堆区属于共享数据区,虚拟机栈、本地方法栈和程序计数器属于线程私有区。
-
方法区
存放被虚拟机加载的类信息,常量,静态变量,以及编译器编译过的代码等数据。一般比较少发生GC. 可以跑出OOM错误。 -
运行时常量池
运行时常量池是方法区的一部分,存放字面量和符号引用。除了编译期生成的class文件的常量,运行时也可以加入新的常量。常量池不会抛出OOM错误。 -
Java堆
Java堆是Java虚拟机管理的最大的一块区域,存放着几乎所有对象的实例,还有数组数据,是GC的主要区域。该区域可以抛出OOM错误。 -
虚拟机栈
生命周期和线程一样,是Java方法执行的内存模型。每一个方法执行的时候,都会创建一个栈帧。会抛出OOM和StackOverflowError. -
本地方法栈
本地方法栈和虚拟机栈类似,只不过它是native方法执行的内存模型。 -
程序计数器
PC是内存中较小的一块,它指向代码执行的地址,如果正在执行的是Java方法,则它指向的是字节码的地址,执行的是native方法的时候,PC为空。
Java内存模型
需要注意的是,Java内存模型与JVM的数据区是两个不同的概念. 定义Java内存模型的目的是为了屏蔽掉硬件和操作系统访问内存的差异,使得Java程序能在不同的平台上都表现出相同的并发效果,避免像C/C++一样,直接操作内存区域. 所以Java内存模型定义了程序中变量的访问规则,即虚拟机是如何将变量存到内存中以及如何从内存中取出数据.
Java内存模型中规定, Java虚拟机中的所有变量都存储在主存中, 但是每个线程都有自己的工作内存, 存有这些变量的副本, 一个线程不能访问其他线程的工作内存, 当一个线程需要更新变量,先更新自己工作线程中的数据,然后刷新到到主存中.