JVM虚拟机主要分三部分:类加载子系统、运行时数据类型(内存模型)、字节码执行引擎。
今天我们主要学习内存模型,内存模型又分为堆、栈(线程栈)、本地方法栈、方法区(元空间)、程序计数器几部分,如下图:
首先了解一下栈内存区域,栈内存又称之为线程栈。
当我们运行一个main方法时,开启一个主线程,就会在栈内存中分配一小块内存给当前线程。
当前线程所运行的程序每调用一个方法就会在栈中分配一块空间给当前方法,此空间称之为栈帧。
如以下代码:
主程序运行了两个方法,一个main方法,一个compute方法。那么在当前栈空间中就会有两个栈帧,如下:
在栈帧中可以看到,栈帧里面有局部变量表、操作数栈、动态链接与方法出口。
局部变量表:用于存储当前方法中的局部变量或参数。如a=1。
操作数栈:当方法运行到a=1,时,首先在操作数栈中new一个1,然后再放入局部量表。个人理解为数据新建和运算时的临时存放空间。
动态链接:运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。
方法出口:记录上级栈帧的运行的JVM指令行数,本方法运行完成后,返回调用方法运行的所在位置。
从上图我们可以看到,在栈中有程序计数器,程序计数器的作用就是记录当前方法运行的jvm指令的行数,每运行一行就会更新一次做加一操作。
本地方法栈:存在本地运行方法的变量。
堆内存:所有new出来的变量都放在堆内存中。
堆栈的关系:如上面所举例的代码,new 出来math,引用放在栈帧的局部变量表中,引用所指向的实例是放在堆内存中。
方法区(云空间):存放静态变量、类元信息等。
堆与方法区的关系:堆中的对象头部信息中有一部分指针指向对象所属类的类元信息。