【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器
文章目錄
- 一、線程棧
- 二、棧幀
- 三、棧幀 - 局部變量表
- 四、反匯編字節碼文件
- 五、Java 虛擬機指令手冊
- 六、程序計數器
一、線程棧
裝載 HelloWorld.class 字節碼文件到 Java 虛擬機內存中 , 會將該字節碼文件中的數據進行分解 , 放到不同的內存區域中 ;
public class HelloWorld {public int add() {int a = 1;int b = 1;int c = a + b;return c;}public static void main(String[] args) {HelloWorld helloWorld = new HelloWorld();helloWorld.add();} }運行該 HelloWorld.class 字節碼文件 , 會創建一個進程 ;
java HelloWorld.classmain 方法是程序入口 , 運行后會創建一個線程 , 就是程序的主線程 ;
public static void main(String[] args) {此時會針對 main 主線程 , 創建主線程的線程棧 ;
每個 線程 , 都要創建一個 線程棧 ;
二、棧幀
創建 main 主線程獨有的 線程棧 , 主要存放 " 棧幀 " , 每個方法都對應一個 棧幀 , 這里存放的是 main 方法對應的棧幀 , 棧幀中存放 臨時變量 , 操作數 ;
" 棧幀 " 同數據結構中的 棧 性質相同 , 先進后出 , 后入先出 ;
主線程 線程棧 中 , 執行 main 函數 , 放入了 main 方法的 棧幀 , 然后創建了 HelloWorld 對象 , 又執行該對象的 add 方法 , 又放入了 add 方法的 棧幀 ;
線程棧 中以 棧 的方式 管理 " 棧幀 " , 后進入的 棧幀 先執行 , 執行完畢后 , 從 線程棧 中 移出 ;
" 棧幀 " 中存儲的是 局部變量表 , 操作數棧 , 動態鏈接 , 方法出口 ;
三、棧幀 - 局部變量表
局部變量表 :
以如下方法為例 :
public int add() {int a = 1;int b = 1;int c = a + b;return a + b;}局部變量表 , 存儲局部變量 , 就是上述方法中的 a , b, c , 333 個局部變量 ;
在 main 方法的 棧幀 的局部變量表中 , 存儲局部變量 helloWorld ; 但是注意 HelloWorld 對象的數據存儲位置是 堆 ;
public static void main(String[] args) {HelloWorld helloWorld = new HelloWorld();helloWorld.add();}四、反匯編字節碼文件
使用
javac HelloWorld.java命令 , 將 HelloWorld.java 編譯為 HelloWorld.class 字節碼文件
使用
javap -c HelloWorld.class命令 , 對 HelloWorld.class 字節碼文件進行反匯編 ;
D:\java>javap -c HelloWorld.class Compiled from "HelloWorld.java" public class HelloWorld {public HelloWorld();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnpublic int add();Code:0: iconst_11: istore_12: iconst_13: istore_24: iload_15: iload_26: iadd7: istore_38: iload_39: ireturnpublic static void main(java.lang.String[]);Code:0: new #2 // class HelloWorld3: dup4: invokespecial #3 // Method "<init>":()V7: astore_18: aload_19: invokevirtual #4 // Method add:()I12: pop13: return }五、Java 虛擬機指令手冊
反匯編的結果都是 Java 虛擬機指令 ; 這些指令都是交給 Java 虛擬機 執行的 ;
根據 Java 虛擬機 指令手冊 , 分析上面的 Java 虛擬機指令 ;
附件中有一份 Java 虛擬機指令手冊 , 可以在博客資源中下載 ;
六、程序計數器
CPU 時間片輪轉 : 假設有一個單核 CPU , 給每個線程都會劃分一個運行時間 ;
將 1 秒鐘拆分成 1000 份 , 每份 1ms ; 很多線程在爭取 CPU 資源 , 操作系統需要給每個線程進行 CPU 時間分配 , 如給線程 1 分配 3ms , 線程 2 分配 5ms , 線程 1 執行完畢后 , 馬上切換到線程 2 執行 , 線程 2 執行完畢后 , 馬上其它線程繼續搶占 ;
線程 1 執行了 3ms , 然后 CPU 運行線程 2 , 假如 x ms 之后 , 再次回到線程 1 運行 , 需要靠程序計數器記錄應該執行哪條 JVM 指令 ;
多個線程并發運行時 , 相互交叉搶占 CPU 資源 , 線程執行完分配的 CPU 時間后 , 需要記錄下當前運行到哪 , 下一次分配到 CPU 資源后 , 繼續執行哪條 JVM 指令 , 這里就需要 程序計數器 來實現該功能 ;
程序計數器就是記錄下面的 JVM 指令前的數字 ;
public int add();Code:0: iconst_11: istore_12: iconst_13: istore_24: iload_15: iload_26: iadd7: istore_38: iload_39: ireturn總結
以上是生活随笔為你收集整理的【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java 虚拟机原理】JDK 体系结构
- 下一篇: 【Java 虚拟机原理】栈帧 | 局部变