JVM按照运行时数据的存储结构来划分内存结构,JVM在运行Java程序时,将它们划分为几种不同格式的数据,分别存储在不同的区域,这些数据统一称为运行时数据(Runtime Data)。
1.PC寄存器
PC寄存器严格来说是一个数据结构,它用于保存当前正常执行的程序的内部地址。
同时Java程序是多线程执行的,所以不可能一直按照线性执行下去,当有多个线程交叉执行时,被中断线程的程序当前执行到哪条语句对应的内存地址必然要保存下来,以便于它被恢复执行时再按照被中断时的指令地址继续执行下去。
2.Java栈
Java栈总是和线程关联在一起的,每当创建一个线程时,JVM就会为线程创建一个对应的Java栈,在这个Java栈中又会含有多个栈帧(Frames),这些栈帧是与线程中每个方法关联的,每运行一个方法就会创建一个栈帧,每个栈帧会含有一些内部变量(方法内定义的局部基本类型变量)、操作栈和方法返回值等信息。
非基本类型的变量在JVM栈上仅存在一个执行堆上的指针(引用)。所以,Java中基本类型变量是值传递,引用类型变量是引用传递。
每当一个方法执行完成时,这个栈帧就会弹出栈帧就会弹出栈帧的元素作为这个方法的返回值,并清除这个栈帧,Java栈的栈顶的栈帧就是当前正在执行的活动栈,也就是当前正在执行的方法,PC寄存器也会执行这个地址。只有这个活动栈中的本地变量可以被操作栈使用。
由于Java栈是与Java线程对应起来的,这个数据不是线程共享的,所以我们不用关心它的数据一致性问题,也不存在同步锁的问题。
运行Java程序时可以用-Xss 来指定栈的大小。
3.Java堆
用来存储Java对象实例和数组值的地方,它是JVM管理Java对象的核心存储区域。它是我们的应用程序与内存关系最密切的存储区域。
堆是被所有Java线程所共享的,所以对它的访问要注意同步问题,方法和对应的属性都需要保持一致性。
运行Java程序时可以用-Xmx -Xms 来指定堆的大小。
4.方法区
JVM方法区是用来存储类的结构信息的地方,包括了类的信息(类名、修饰符)、类中的静态变量、常量池(包括了用final定义的常量等)、构造函数等。
方法区这个存储区域其实也是Java堆中的一部分,也就是常说的Java堆中的永久区(持久代)。
5.运行时常量池
它也就是前面方法区中提到的常量池,它是方法区的一部分。
6.本地方法栈
为JVM运行Native方法准备的空间,它和前面介绍的Java栈的作用类似。