棧和棧幀
棧(JVM虛擬機棧)
棧的數據結構是先進后出、后進先出.JVM虛擬機棧是隨着線程的創建而創建、隨着線程的銷毀而終止。每個線程在啟動的時間都會分配一個JVM棧。那么JVM里存儲的是什么呢?就是棧幀
幀(棧幀)
JVM在執行每一個Java方法的時候都會創建一個棧幀,壓入棧底!隨着這個方法的結束,那么對應的棧幀也會彈出銷毀,被CPU調度的線程叫做當前線程、JVM當前執行的方法叫做當前方法,創建的棧幀叫做當前棧幀。
棧幀存儲的內容
既然一個棧幀對應的一個方法調用過程,那么方法里有什么呢?本地變量、 其他方法調用、數據運算、返回內容.. 那么由這些方法內容大致的可以確定棧幀的結構內容!
- 局部變量表(Local Variable Table)
- 操作數棧(Operand Stack)
- 動態鏈接 (Dynamic Linking)
- 方法的返回地址 (Return Address)
局部變量表
- 大小在編譯期間就可以決定,最少單位為變量槽(Var Sort))
- 一個Sort最少要能夠放的下 boolean(1位)、byte(8位)、char、short、int、float、reference(一個引用、對象的引用、數組等)、returnAddress(指向字節碼指令地址)類型的數據,64位的Long、double是占用兩個sort。
- 當一個方法被調用時、第0個sort位存儲是
this
引用、從1開始依次存放參數、和局部變量。 - 在一個方法體內sort可以重復利用、比如在一個if或者for語句內,內部定義的變量是不可以拿出再用的。
操作數棧
代碼做每次運算時,都會把相應的操作數壓到操作數棧里,然后彈出,運算,把結果再壓入操作數棧中以便下次使用。這里就不做演示,待下次深入再探!先知道個原理。
動態鏈接
在方法體,有一些其他函數的引用,比如調用外部函數、Java的多態,父類的引用指向子類的實例。那么動態鏈接就是找到運行時真正的指令地址,先知道個原理,下次再探。
方法返回地址
方法的結束分為兩種
- 正常的return調用、
- 出現了異常未處理、程序退出。
方法正常的完成即是正常的退出當前棧幀的過程,它負責還原調用者的上下文環境(局部變量表、操作數棧、配置pc計數器等、),並把當前的返回的值壓入調用者的操作數棧。異常結束是不會返回信息給調用者,信息在異常表里棧幀不負責保存這部分數據。