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