局部变量表存储每个变量值,也就是平时在方法内部定义的局部变量以及在调方法时传的参数,都是存储在局部变量表里。当虚拟机把java文件编译成字节码文件的时候,会对程序里的方法进行检查,然后确定每个方法需要分配的最大局部变量表的容量。
操作数栈,就是存储要进行操作的变量,是后入先出的结构栈,跟局部变量表一样也是在编译的时候就会确定好它的最大容量。当方法执行的时候,刚开始操作数栈是空的,然后随着执行的过程中会对操作数元素进行压栈和弹出。
返回地址,是确保方法在退出后返回到方法被调用的位置的地址信息。当一个方法在正常退出或异常退出完成后,虚拟机栈中的返回地址就会被拿来恢复它的上层方法执行状态。
可能说完这些概念之后还是有点抽象,以下举个例子你就明白了。这里写段代码:
以上这个方法在内存中执行的过程是这样的:
-
假设该方法是写在Sum.java文件里,虚拟机对它进行编译时会去确定好栈帧中局部变量表和操作数栈的容量,然后在创建局部变量表和操作数栈的时候根据这个容量来创建便可。
-
然后执行int x = 1的时候其实就是先将常量1压入操作数栈栈顶,然后再把它弹出栈并且放入到局部变量表索引为1的位置里,作为变量x的值。
-
接着int y = 2时也一样,将常量2压入操作数栈顶,然后再弹出来并且放入到局部变量表索引为2的位置里,作为y变量的值。
-
接着执行int z = x + y时,先将此时局部变量表里的值1和值2压入到操作数栈中,此时栈顶是2,底下是1,然后进行加法操作得到值3,然后此时栈顶就是该结果值3,将该值3出栈,存入到局部变量表索引为3的位置。
-
最后执行return z的时候,将局部变量表中的3压入回操作数栈栈顶,然后将操作数栈栈中的3返回给上层方法。到这里整个sum方法执行完毕,而布局变量表和操作数栈也会跟着销毁。
以上过程如果要画成图可以这样表示:
整个流程图虽然很长,但结构非常容易理解,要操作的元素都出入操作数栈,而变量值则存按索引位置存到局部变量表里,请结合上文五点步骤描述来理解此图。
最后也可以使用javap 命令来查看该类的字节码指令,验证是否像上图描述的流程一样执行该方法。这点读者可自行去确认,这里就不作讲解了。
堆内存这块区域则是存放对象实例的,大家应该不陌生了,当堆内存中的对象没有被引用指向时,就变成了可回收对象,被GC进行垃圾回收。
方法区,主要存储类信息(类模板),常量和静态变量等。
程序计数器,用来记录当前线程执行的位置,也就是平时我们在编辑器里不是会看到一段代码的左侧会有数字记录每一行吗,这些行数就是线程用来记录当前方法执行到哪个位置,这样CPU在切换回线程时仍然能继续上一次位置继续执行。
