运行时栈帧结构

什么是栈帧

栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈(Virtual Machine Stack) [1]的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。

结构图

在这里插入图片描述

  • 局部变量表
    局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量,存在方法的Code属性的Max_locals数据项中。
  • 操作数栈
    操作数栈(Operand Stack)也常称为操作栈,它是一个后入先出(Last In First Out,LIFO)栈。同局部变量表一样,操作数栈的最大深度也在编译的时候写入到Code属性的max_stacks数据项中。操作数栈的每一个元素可以是任意的Java数据类型,包括long和double。32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2。在方法执行的任何时候,操作数栈的深度都不会超过在max_stacks数据项中设定的最大值。
  • 动态连接
    每个栈帧都包含一个指向运行时常量池 [1]中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。
  • 方法返回地址

小总结

总结一下上面JVM里面运行时栈帧的情况,下面我开下脑洞,我想看一下c语言在编译的时候是怎么创建栈帧的。

类比C语言的编译过程中的一些情况

编译过程

gcc这个是驱动程序,用来安排编译的文件情况。
编译的过程大概如下图:预编译(文件包含,宏定义、条件编译)-编译-汇编-连接
在这里插入图片描述

编译一个简单的文件xun.c

root@miv:~/learn# cat xun.c 
#include <stdio.h>
 
int main()
{
   /* 我的第一个 C 程序 */
   printf("Hello, World! \n");
   
   return 0;
}
root@miv:~/learn# gcc -v xun.c 
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
...

预编译、编译的阶段出现.cfi指令

使用命令:gcc -S my_c_file
发现有一些.cfi指令

root@miv:~/learn# gcc -S xun.c 
root@miv:~/learn# ls
a.out  xun.c  xun.i  xun.s
root@miv:~/learn# cat xun.s 
	.file	"xun.c"
	.text
	.section	.rodata
.LC0:
	.string	"Hello, World! "
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	leaq	.LC0(%rip), %rdi
	call	puts@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
	.section	.note.GNU-stack,"",@progbits

".cfi"开头的伪指令是辅助汇编器创建栈帧(stack frame)信息的。还有一部分是伪指令,
伪指令是不参与CPU运行的,只指导编译链接过程。
栈帧结构图大概如下
在这里插入图片描述

gcc命令

  • 编译、汇编、连接
    gcc -v my_c_file
  • 预编译
    gcc -E my_c_file -o my_c_file.i
  • 预编译、编译
    gcc -S my_c_file

总结

其实上面第一个角度是从Java的JVM角度看栈帧,第二个角度是分析c语言编译过程中的一个情况,这里涉及到方法调用,那么会有一些辅助的代码创建栈帧。
还没去看虚拟机源码,暂时就这可以通过这个角度看下,扩展一些知识面。

参考

《深度探索Linux操作系统》
《深入理解Java虚拟机》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章