JVM的基本結構圖:javascript
由圖可知,JVM的內存區域主要能夠劃分爲5塊:java
java.lang.StackOverFlowError
java.lang.OutOfMemoryError
和java棧的做用差很少,只不過是爲JVM使用到的native方法(使用非Java語言實現的方法)服務的數組
OutOfMemoryError
的運行時數據區下面經過AppMain.java和Sample.java兩塊代碼進一步說明多線程
//運行時, jvm把AppMain的信息都放入方法區
public class AppMain {
//main 方法自己放入方法區
public static void main(String[] args) {
//test1是引用,因此放到棧區裏,Sample是自定義對象應該放到堆裏面
Sample test1 = new Sample("測試1");
Sample test2 = new Sample("測試2");
test1.printName();
test2.printName();
}
}
複製代碼
//運行時, jvm把Sample的信息都放入方法區
public class Sample {
//new Sample實例後, name 引用放入棧區裏, name 對象放入堆裏
private String name;
/** 構造方法 */
public Sample(String name) {
this.name = name;
}
/** 輸出 */
//print方法自己放入方法區裏
public void printName() {
System.out.println(name);
}
}
複製代碼
啓動虛擬機進程,程序從AppMain的開始,先從classpath中找到並讀取AppMain.class二進制文件(編譯後),而後把AppMain類的類信息和方法信息放入方法區,這個過程叫AppMain類的加載過程;jvm
Java虛擬機定位到方法區AppMain類中的main()方法的字節碼,開始執行它的指令,第一條語句是:函數
Sample test1 = new Sample("測試1");
複製代碼
接着Java虛擬機到方法區中查找Sample類的信息,沒有找到,而後經過步驟1從新加載Sample類到方法區;測試
在堆中爲Sample對象實例分配內存,這個實例持有指向方法區的Sample類的信息的引用(引用是指Sample類的信息在方法區中的內存地址)this
每個線程都有一個棧,棧裏面的元素被稱爲棧幀,每當線程調用一個方法的時候就會往棧裏壓入一個新幀,這裏的幀是用來存儲方法的參數、局部變量和運算過程當中的臨時數據。位於**「=」前的test1是一個在main()
方法中定義的變量,它是一個局部變量,所以,它被會添加到了執行main()
方法的主線程的java方法調用棧中,而「=」**將把這個test1變量指向堆區中的Sample實例,也就是說,它持有指向Sample實例的引用spa
接下來,JAVA虛擬機將繼續執行後續指令,在堆區裏繼續建立另外一個Sample實例,而後依次執行它們的printName()
方法。當JAVA虛擬機執行test1.printName()
方法時,JAVA虛擬機根據局部變量test1持有的引用,定位到堆區中的Sample實例,再根據Sample實例持有的引用,定位到方法去中Sample類的類型信息,從而得到printName()
方法的字節碼,接着執行printName()
方法包含的指令.net
一、Q: Java中的參數傳遞(傳值呢?仍是傳引用?)
A:
程序運行永遠都是在棧中進行的,於是參數傳遞時,只存在傳遞基本類型和對象引用的問題,不會直接傳遞對象自己;
對象傳遞是引用值傳遞,原始類型數據傳遞是值傳遞; 實際上這個傳入函數的值是對象引用的拷貝,即傳遞的是引用的地址值,因此仍是按值傳遞。
二、Q: Java對象的大小如何計算?
A:
Object obj = new Object();
複製代碼
這樣在程序中完成了一個java對象的聲明,obj對象所佔的空間爲:
4byte(java棧中保存引用的所須要空間)+ 8byte(java堆中對象所需的空間) = 12byte
複製代碼
全部的java非基本類型的對象都須要默認繼承Object對象,所以不論什麼樣的java對象,其大小都必須是大於8byte
同時java對象大小是8的整數倍,所以obj對象的大小至少爲16byte
對象引用類型分爲強引用、軟引用、弱引用和虛引用
一、強引用:聲明對象時虛擬機生成的引用
Sample sample = new Sample();
複製代碼
sample
爲強引用,不會被垃圾回收
二、軟引用:根據系統剩餘內存來決定是否須要回收
換句話說,虛擬機在發生java.lang.OutOfMemoryError
時,確定是沒有軟引用存在的
三、弱引用:弱引用與軟引用相似,但在進行垃圾回收時,是必定會被回收掉的
所以其生命週期只存在於一個垃圾回收週期內
四、虛引用虛引用並不會決定對象的生命週期。
若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收器回收
虛引用主要用來跟蹤對象被垃圾回收器回收的活動
參考地址: