当JVM加载class文件的字节码时,会为class分配一个JVM运行时数据区。
数据区包含方法区(类的方法),堆内存(类的对象),虚拟机栈,本地方法栈,程序计数器。
其中方法区、堆内存是线程共享的,虚拟机栈、本地方法栈、程序计数器是线程独占的。
线程共享:所有线程都能访问,随虚拟机或GC而创建和销毁。
线程独享:线程独立拥有的空间,随线程的生命周期创建和销毁。
方法区
JVM用来存储加载的类信息,常量,静态变量,编译后的代码等数据。
虚拟机规范中,这是个逻辑区划,不同的虚拟机有不同的具体实现。
比如:oracle的HotSpot在java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理。
堆内存
堆内存还可细分为:老年代,新生代(Eden、From Survivor、To Survivor),在JVM启动时创建,存放对象的实例。
GC主要就是管理堆内存。如果满了会出现OutOfMemoryError。
虚拟机栈
每个线程都在虚拟机栈有个私有的空间。
线程栈由多个栈帧(Stack Frame)组成。
一个线程会执行一个或多个方法,一个方法对应一个栈帧
栈帧内容包含:局部变量表,操作数栈,动态链接,方法返回地址,附加信息等
栈内存默认最大1M,超出则抛出*Error
本地方法栈
虚拟机栈是为虚拟机执行Java方法准备的,本地方法栈则是虚拟机执行Native方法准备的
虚拟机规范没有规定具体的实现,由不同虚拟机厂商实现。HotSpot中,本地方法栈和虚拟机栈的实现是一样的,栈内存默认最大1M,超出则抛出*Error
程序计数器
记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空
每个线程都在这个空间有个私有的空间,占用内存很少
CPU同一时间只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行,线程切换后,需要通过程序计数器,恢复正确的执行位置。