1. 程式人生 > >靜態變數載入時間,靜態程式碼塊載入時間

靜態變數載入時間,靜態程式碼塊載入時間

當類載入器將類載入到JVM中的時候就會建立靜態變數,這跟物件是否建立無關靜態變數載入的時候就會分配記憶體空間靜態程式碼塊的程式碼只會在類第一次初始化的時候執行一次。一個類可以有多個靜態程式碼塊,它並不是類的成員,也沒有返回值,並且不能直接呼叫。靜態程式碼塊不能包含this或者super,它們通常被用初始化靜態變數。

通過一個小程式認識JVM

package com.spark.jvm;
/**
 * 從JVM呼叫的角度分析java程式堆記憶體空間的使用:
 * 當JVM程序啟動的時候,會從類載入路徑中找到包含main方法的入口類HelloJVM
 * 找到HelloJVM會直接讀取該檔案中的二進位制資料,並且把該類的資訊放到執行時的Method記憶體區域中。
 * 然後會定位到HelloJVM中的main方法的位元組碼中,並開始執行Main方法中的指令
 * 此時會建立Student例項物件,並且使用student來引用該物件(或者說給該物件命名),其內幕如下:
 * 第一步:JVM會直接到Method區域中去查詢Student類的資訊,此時發現沒有Student類,就通過類載入器載入該Student類檔案;
 * 第二步:在JVM的Method區域中載入並找到了Student類之後會在Heap區域中為Student例項物件分配記憶體,
 * 並且在Student的例項物件中持有指向方法區域中的Student類的引用(記憶體地址);
 * 第三步:JVM例項化完成後會在當前執行緒中為Stack中的reference建立實際的應用關係,此時會賦值給student
 * 接下來就是呼叫方法
 * 在JVM中方法的呼叫一定是屬於執行緒的行為,也就是說方法呼叫本身會發生線上程的方法呼叫棧:
 * 執行緒的方法呼叫棧(Method Stack Frames),每一個方法的呼叫就是方法呼叫棧中的一個Frame,
 * 該Frame包含了方法的引數,區域性變數,臨時資料等 student.sayHello();
 */
public class HelloJVM {
	//在JVM執行的時候會通過反射的方式到Method區域找到入口方法main
	public static void main(String[] args) {//main方法也是放在Method方法區域中的
		/**
		 * student(小寫的)是放在主執行緒中的Stack區域中的
		 * Student物件例項是放在所有執行緒共享的Heap區域中的
		 */
		Student student = new Student("spark");
		/**
		 * 首先會通過student指標(或控制代碼)(指標就直接指向堆中的物件,控制代碼表明有一箇中間的,student指向控制代碼,控制代碼指向物件)
		 * 找Student物件,當找到該物件後會通過物件內部指向方法區域中的指標來呼叫具體的方法去執行任務
		 */
		student.sayHello();
	}
}
 
class Student {
	// name本身作為成員是放在stack區域的但是name指向的String物件是放在Heap中
	private String name;
	public Student(String name) {
		this.name = name;
	}
	//sayHello這個方法是放在方法區中的
	public void sayHello() {
	System.out.println("Hello, this is " + this.name);
	}
}

具體JVM 架構圖參考下面內容