運行時棧幀結構

什麼是棧幀

棧幀(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虛擬機》

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