Golang命令列引數
目錄
JVM
一、subSystrm(類載入子系統)
loding(載入)
類載入器
類載入器時我們java程式碼生成的.class檔案已二進位制流的方式載入到我們JVM當中的過程稱為類載入器。
通過以下程式碼可以清楚看到我們不同載入器可載入的目錄
URL[] urLs = Launcher.getBootstrapClassPath().getURLs(); for (URL urL : urLs) { System.out.println(urL.toExternalForm()); }
類載入防止重複載入是有鎖的
BootstrapLoader(引導類載入器)
引導類載入器是java專門用來載入jre環境的載入器,通常載入c/c++程式碼和rt.jar等包下的類。
我們無法使用引導類載入器去載入我們的java類。
ExtClassLoader(擴充套件類載入器)
擴充套件類用來載入ext.jar等包下的類,同樣我們也無法
AppClassLoader(應用類載入器)
又稱系統類載入器,可載入我們classpath使用者自定義的類載入到jvm當中
...ClassLoader(自定義類的載入器)
使用者也可以自定義記載器
-
隔離載入類
-
修改類載入方式
-
擴充套件載入源
在jdk1.2之前可以繼承ClassLoader類重寫loadCalss方法,而在1.2之後建議成功將邏輯解除安裝findClass方法中。如果沒有複雜的需求直接繼承URLClassLoader類避免重新findClass
雙親委派機制和沙箱安全
雙親委派機制
當我們建立一個java.lang.String類時,顯然他與我們java的String相沖突,我們的類載入器會首先委派給父類去載入String,當委派到BootstrapClassLoader時他會發現本身就又java.lang.String類最終載入,並且我們想在java.lang包下建立一個不存在與jdk裡的類也是不可以的,這就破壞了引導類載入器的安全性,因為使用者建立的類存在一定的安全問題。
沙箱安全
上訴描述的概念一樣,期思想就時不讓使用者汙染我們引導類載入器,保證我們jre本身不受外界影響。
linking(連結)
verify(檢測)
檔案格式驗證
- 是否以魔術OXCAFEBABE開通
- 主次版本號是否在接受範圍
- 常量也是否有不被支援的型別
- 檢測常量值的引是否執行不符合型別的常量
- 、、、
元資料驗證
- 這個類是否有父類
- 這個類是否繼承了不被允許的父類
- 是否實現類的抽象方法
- 是否方法的過載和重寫
- 、、、
位元組碼驗證
- 驗證區域性變量表會不會波運算元棧放入不同型別資料
- 保證任何跳轉不會跳到棧賴以為的位元組碼指令上
- 父類引用可以指向子類物件,而不是返回來或者不相干
- 、、、
符號引用驗證
- 符號引導描述字串是否能找到
- 符號引用描述名稱、欄位、方法是否存在
- 對於訪問修飾符是否有許可權
- 、、
prepare(準備)
在準備階段會對類變數也就是被static修飾的變數進行預設初始值的賦值,而例項變數和靜態的顯示變數需要等待物件初始化時在進行賦值並分配到堆空間中。final修飾static的常量在準備階段就會賦值,因為final在class編譯階段會生成與之相應ConstantValue值
這裡需要注意的點: 在jdk1.7及前中我們的類變數會分配到方法區中也叫永久代,而在jdk1.7後我們類變數會隨著Class物件儲存在堆空間中,而這時候“類變數在方法區”也成了邏輯上的概念
resolve(解析)
解析的過程就是我們符號引用轉為直接引用的過程,其中包括類,方法,欄位,介面,靜態常量等一系列的引用
initialization(初始化)
通過來對例項變數實現賦值。
通過來對類變數進行顯示賦值並按順序賦值。
二、RuntimeDateAreas(執行時資料區)
program count registers(程式計數暫存器)
是一塊較小的記憶體空間,可以看做位元組碼行號指示器。位元組碼指示器就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支迴圈跳轉異常處理,程式計數器是執行緒私有並且是唯——塊不會發生記憶體溢位的區域。
virtual machine Stack(虛擬機器棧)
java虛擬機器棧是執行緒私有的。它的生命週期與執行緒相同,每個方法在執行時都會建立一個棧幀。用於儲存區域性變量表,運算元棧、動態連結、方法出口。如果執行緒請求虛擬機器棧的深度大於虛擬機器所允許的深度。將丟擲StackOverflowError異常。如果擴充套件時無法申請到做夠的記憶體,則會丟擲O utofmemoryError異常
stack frame(棧幀)
LocalVariableTable(區域性變量表)
區域性變量表記錄著我們棧幀中的型別表,實在而且時在編譯期就確定下來了又幾個變數以及棧中變數槽的大小型別與作用域
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 args [Ljava/lang/String;
Slot(變數槽)
32位以內只棧1個操,所以在Double和Long型別在棧兩個槽。
這裡又一點當在一個棧幀中如果又變數生命週期提前結束的變數那麼之後的變數會重複利用他所佔的slot
operand stack(運算元棧)
我們java的操作指令是用的棧結構,特點是佔用空間小,執行效率慢,而與只對應的控制代碼結構佔用空間大,執行效率塊。
運算元棧類似陣列的棧,他的棧大小也是在編譯期就確定的,儲存在方法的Code屬性中,為max_stack的深度。
32bit佔用1個深度
64bit佔用2個深度
return adress(返回值地址)
存放呼叫該方法的pc暫存器的值:
列入:
在方法中呼叫其他方法,這時一個壓棧操作,當呼叫完成之後(出棧後)我們當前方法需要繼續執行這就需要用到返回值地址,我們返回值地址交給執行引擎繼續操作。
如果異常退出丟擲異常等,這放回置
dynamic linking(動態連結)
指向執行時常量池的符號引用,每一個棧幀都包含一個對常量池的一個引用。
其他
LineNumberTable(行號表)
位元組碼指令對應我們java程式碼的行號資訊
LineNumberTable:
line 12: 0
line 4: 4
line 13: 9
line 15: 15
line 18: 18
line 16: 21
line 17: 22
line 19: 26
Exception table
Exception table:
from to target type
15 18 21 Class java/lang/Exception
方法呼叫的過程
invokeddynamic(動態呼叫)
在jdk1.7後出現,1.8的時候被使用到,典型的例子lambad表示式以及一些函式介面就是使用此呼叫。通過實現反推出型別實現動態語言的一小步。
public static void main(String[] args) {
Function f = o -> "A";
}