面試中的相關問題主要是三塊
1.JVM 內存區域劃分
2.JVM 的類加載機制
3.JVM 的垃圾回收機制
JVM? Java虛擬機
VM Virtual Machine 虛擬機,用 軟件 來 模擬 硬件
傳統意義上的"虛擬機" 更多指的是 VMWare, Virtual Box, Hyper-V, KVM(構造出虛擬的電腦,甚至可以在虛擬機的電腦上安裝獨立的操作系統)
一臺計算機:
*CPU
*儲存器
*輸入設備
*輸出設備
通過硬件來模擬軟件
Java 的虛擬機,并不是虛擬電腦的所有核心硬件(一部分),也不能運行獨立的操作系統,只是可以運行Java代碼
JVM 更準確額說是 Java語言的"運行時環境",核心功能就是把 Java 代碼,翻譯成計算機可以識別的機器指令(低效的,更高效的,像C/C++/Go,編譯出來的程序就是標準的 CPU 構成的指令程序)
帶來的好處是,可更好的做到"跨平臺"和硬件無關
Java 程序是怎么運行的?
1.編寫代碼,是編寫了.Java文本文件
2.通過 Javac 這樣的 命令行工具,把.java 編譯成.class文件(字節碼文件)二進制的,.java 中的每個 class 都會對應一個.class 文件,一個.java文件中可以出現多個 class(只能有一個 public)
3.通過 java 這樣的命令行工具,運行對應的.class文件 java 命令行工具,對應到一個 java 進程,這個 java 進程就可以理解成一個 Java 虛擬機了(也可以叫 JVM 的進程),JVM 的進程,就會對,class 文件中的內容解釋執行了
Java 代碼中的"拋出異常"實在 3 這個階段產生的
1.JVM 內存區域劃分
java 程序跑起來,得到 java 進程,需要從操作系統申請一大塊空間
java 進程就需要把這一大塊空間,分成多個區域,分別賦予不同的功能
簡化的模型
1)程序計數器
非常小的空間,只需要保存一個"地址",描述當前 java 程序需要運行的下一個字節碼指令的位置
一個 java 進程中應該有幾個程序計數器呢?
應該是存在多個的
線程是 cpu 調度執行的基本單位.
每個線程都得有一個程序計數器來記錄
操作系統中也是有類似的設定的,會在 CPU 上專門準備一個寄存器,就會用這個寄存器,表示"下一條指令執行的地址",這個寄存器稱為 EIP(計組里就會把這個概念稱為"程序計數器"簡稱為 PC(Program Counter))
CPU 執行指令,只是"默認是循序執行的",比如遇到 if, while, for,方法調用,拋出異常....都會使指令不在按照循序執行,跳轉到某個位置
線程是"并發執行",產生一個調度,一個線程,執行一段時間之后,需要調度走,后續在調度回來
保存上下文,這個線程執行過程的所有相關寄存器的值(包括了 PC)
程序計數器的值,java代碼干預不了,程序計數器值,代表的要執行的指令的地址,也是在元數據區
2)元數據區(在 Java 8 之前 稱為 方法區,放的是 類 對應 的指令)
元數據區的內容,Java 代碼也干預不了,你的代碼中寫了多少類,元數據區的內容也就確定了
Java 代碼中,會創建類,基于 類 創建對象,對象當然是要有內存空間來保存的,類同樣也需要再內存空間中保存
java 中提出了"類對象"概念
JVM 中,通過特殊的對象,表示一個類的基本信息
*類的名字是啥
*類繼承的父類是啥
*實現的接口是啥
*有啥屬性(屬性的名字,類型,public/private)
*有啥方法(方法的名字,參數列表,返回值,public/private)
*類靜態成員
*常量
3)棧(這里的棧和數據結構中的棧是不同的概念)
數據結構的棧 -> 錢
JVM 的棧 -> 人民幣
這個區域保存了方法調用關系
java 的方法保證了,當前方法執行完畢返回上一層,調用位置繼續執行
這個棧也是后進先出的特點,這里的元素,有固定的說法,把 JVM 的棧中的每一個元素,稱為"棧幀(frame)"
棧幀表示一次"方法調用"
1)方法的產生是哪些
2)方法中的局部變量有哪些
3)方法執行結束之后,返回值的結果
4)方法執行結束之后,跳轉回的地址
4)堆
堆存放了 new 出來的對象,對象對應的內存空間在堆中,常量之前是放到元數據區的,后來放到了堆中
class Test {private int n;private static int m;public void test1() {//...}static public void test2() {//...}
}
main(){Test t = new Test();
常見誤區:
內置類型在棧上
引用類型在堆上
關鍵是變量的形態
局部變量 => 棧
成員變量 => 堆
靜態成員變量 => 元數據區