JVM运行时数据区域

时间:2022-01-01 09:56:58

基本概念:

每运行一个java程序,就会有一个对应的JVM实例和一个进程,一个进程可以包含多个线程。每个JVM实例(进程)都有自己的堆,每个线程都有自己私有的栈。进程所创建的所有类的实例(也就是对象)或数组(指的是数组的本身,不是引用)都放在堆中,并由该进程所有的线程共享。每一个对象的存储内存都是在堆中分配,而引用就是在栈中,栈里的引用生命周期结束后,马上出栈,而堆中的对象就会等待GC的回收。

JVM运行时数据区域

JVM运行时数据区图片

PC程序计数器(线程私有

学过汇编的都知道计算机本身也有个PC(program counter)或者叫做IP(Instruction Pointer),作用就是跟CS结合使用,执行代码指令,PC(IP)永远指向程序下一条将要执行的指令,它可以看作是当前线程所执行的指令指示器,为线程私有。


Java虚拟机栈线程私有

伴随着线程的生命周期创建与死亡,java虚拟机栈描述的是方法执行的内存模型:

每个方法的执行都会创建一个栈帧,每个方法的调用直到执行完成,代表着栈帧的进栈与出栈。栈帧存放着局部变量表,操作数栈,动态链接库,方法出入口等。

本地方法栈

本地方法栈与JVM栈非常相似,只不过它服务的方法是java程序中调用的本地方法,Sun HotSpot 合并了虚拟机栈和本地方法栈

堆(线程共享)

java虚拟机管理中内存最大的一块,被所有的线程所共享, The heap is the run-time data area from which memory for all class instances and arrays is allocated.规范中描述:所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器和逃逸分析技术的成熟,栈上分配、标量替换这些技术会导致一些微妙的变化,前面的“所有”会变得不那么绝对。GC管理着这块区域,采用分代收集算法,所以堆上可以继续划分为更细的区域:新生代,老年代;更细节就是Eden , From Survivor,To Survivor

JVM运行时数据区域

从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区。但是不管怎么划分,都与它存放的内容(对象实例)无关,都是为了更好地管理这块区域,进行内存回收、更快分配内存



方法区

这块区域在java8中已经被换成元空间,法区和Java堆一样,都是所有线程共享的一块内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。另外它有一个别名叫着“永久代”,这是因为HotSpot虚拟机将GC分代收集扩展到了方法区,这样HotSpot的垃圾回收器就可以一同样的方式来管理这块内存。--《深入理解java虚拟机第二版》周志明

运行时常量区

JVM运行时数据区域

属于方法区的一部分,Class文件中保存constant——pool,用于存放编译器生成的字面常量和符号引用,类加载的时候进入运行时常量区中存放。