java內存圖
- java文件運行流程
- 程序的內存空間
- 認識虛擬機棧
- 程序的執行流程
- 認識堆
- java的類與對象的關系
java文件運行流程
有這樣的一份 java 文件
在該目錄下的終端運行 javac Hello.java
命令,會生成 Hello.class 文件,內容如下:
Hello.java 打開是我們能夠看懂的代碼,也叫源代碼文件,源代碼文件是給咱們程序員去看的;而 Hello.class 文件這里邊是二進制的字節碼文件,二進制字節碼文件是給計算機看的
此時當前這兩份文件都在磁盤當中,都是在外部存儲設備當中
當終端運行 java Hello
這個命令,能將當前的二進制文件從磁盤放到內存中交給 CPU 運行,然后輸出 "hello world"
由于 java 這個命令可以將當前的二進制文件從磁盤放到內存中交給 CPU 運行,那么該程序在內存空間中是什么樣的呢?接下來我們來討論程序的內存空間部分。
程序的內存空間
數據類型決定數據在內存當中是如何存儲的,正在運行的程序在內存當中都必須要有自己的內存空間,因為任何一個變量任何一個指針都需要內存空間來進行表達
數據在內存當中的存儲位置是由操作系統所決定的,程序的運行需要操作系統給它開辟內存空間,當擁有這塊內存空間后就由 java 程序自己去操作這一塊內存空間,該內存空間會被切分為以下幾個區域:
其中最重要的三個是 虛擬機棧、堆 和 方法區
虛擬機棧
控制著程序的執行;
堆
是用來存儲對象的;
方法區
用于存儲虛擬機加載的存儲類信息、常量、靜態變量、臨時數據等;
方法區中存儲的也就是當前的 .class 文件
下面我們來具體講解虛擬機棧和堆
認識虛擬機棧
我們來看這樣一份代碼文件:
終端運行結果:
下面我們來看程序的執行流程
程序的執行流程
程序的內存空間如下:
其中虛擬機棧的執行流程如下:
首先第一步 main 方法入棧,入棧后表達程序,對 “hello world” 做了輸出,之后它會調用 run() 方法入棧。run() 方法進行表達,執行是從上到下執行,第一步先定義一個局部變量 num = 100,num 本身是一個 int 類型的指針, num 是指向100的地址,假設它的地址是 0x10 那么 num 就指向0x10,輸出完了之后,調用 jump() 方法。jump() 方法里面也有一個局部變量 num,num 是從上邊賦過來的值,相當于是做了一次值傳遞,相當于是把這個100傳了過去,繼續執行輸出,jump() 也就執行完畢后出棧。那么又回到咱們當前這個 run() 方法了,run 方法此時執行完這一行之后也就會出棧了,這樣就又回到 main() 方法了。main 方法中 run() 執行完畢 run() 出棧,main() 接著會去執行下一個方法 aaa(),aaa()入棧,有一個局部變量 byte a = 10,輸出后 aaa 執行完 main 方法出棧,整個程序就執行完畢了。
程序的執行過程就是 main 方法從入站到出棧,程序執行第一步是main方法入棧最后一步一定是main方法出棧。程序從開始執行到執行完畢是由 main 方法來對其進行控制的,從上到下依次進行執行,整個流程就是程序的執行過程,程序的執行過程又被叫做 線程。
引申:我們可以簡單去理解 java 當中的多線程,要想實現 java 當中的多線程就意味著我們需要多個程序的執行過程,而如何實現 java 當中的多線程,就需要多個虛擬機棧。
認識堆
在講述堆之前我們先看 java 的類與對象的關系
java的類與對象的關系
有這樣一份代碼文件:
我們發現打印結果里的 tom 和 jr 的名字不一樣
下面具體講解:
new
:關鍵字(java保留字,有實際含義)在堆內存中開辟內存空間
Cat()
:構造器,是在創建對象的時候給對象賦值
tom
:對象名或叫做變量名
Cat
:數據類型(引用數據類型中的類),數據類型決定數據在內存當中是如何存儲的
=
:賦值操作,將對象的地址值賦給變量
程序執行第一步main方法入棧,之后它就會調用 Cat tom = new Cat();
,首先 new 關鍵字會在堆里邊開辟一塊內存空間創建 tom 對象,由 Cat 數據類型決定數據在內存當中存儲形式,Cat 里邊有兩個方法和一個變量, eat(String food)、catchMouse() 和變量 name=‘aaa’,會將該對象的地址值 0x1 賦給 tom 變量。
每 new 一次都要開辟新的內存空間,Cat jr = new Cat();
會在堆中開辟一塊內存空間創建 jr 對象,同樣地在該對象中有 eat(String food)、catchMouse() 和變量 name=‘aaa’,該對象的地址值 0x2 賦給 jr 變量。為什么此時 tom 和 jr 的是相同的,因為他們具有相同的數據類型 Cat,相同的數據類型的內存形式是一樣的。但是在 main 函數中 jr.name = "jr";
對 jr 對象的 name 值進行了修改,這樣 jr 調用 name 輸出的就不再是 ‘aaa’ 了,而是 ‘jr’ 了。
一個類可以創建出多個對象,tom 和 jr 是兩個不同的對象,但是它們的存儲形式是相同的,相同的數據類型內存形式是一樣的。
類是創建對象的模板,那么模板里邊有什么那類里邊有什么,那對象當中就應該默認有什么
而 堆是用來存儲對象的
總結
:類是創建對象的模板,一個類可以創建多個對象
什么是 java 對象:堆內存當中的存儲結構