《分散式java應用:基礎與實踐》筆記3
《分散式java應用:基礎與實踐》筆記3
3.1.1原始碼編譯機制
3.1.2 類載入機制
裝載:將位元組碼裝載至JVM。識別類:類的全限定名+ClassLoader例項ID(對於介面與非陣列型類;對於陣列類,陣列的元素型別由ClassLoader載入,陣列類由jvm建立)
連結:位元組碼格式(二進位制)校驗,(JVM規範)---->初始化類中靜態變數——>驗證方法權
限。
初始化:靜態初始化程式碼、構造器、靜態屬性等等
JVM的類載入通過ClassLoader及其子類完成
Bootscrap Class Loader : C++實現此類,所以程式碼無法拿到該物件。不屬於ClassLoader子類。
Extension Class Loader : 對應類名為ExtClassLoader。拓展功能jar包
System Class Loader :對應類名為AppClassLoader。Classpath目錄中的jar包。
JVM保證一個ClassLoader例項只加載一次同名的類,從而實現類的隔離。
3.1.3 類執行機制
位元組碼解釋執行。
Invokestatic、invockevirtual、invokeinterface、invokespecial四個指令執行不同方法呼叫。
執行緒在建立後,都會產生程式計數器PC,PC存放下一條要執行的指令在方法內的偏移量;棧中存放了棧幀,每個方法每次呼叫都會產生棧幀。棧幀主要分區域性變數區和運算元棧兩部分,前者存放區域性變數和引數,後者產生中間結果。棧幀中還會一些雜用空間。
1) 指令解釋執行
2) 編譯執行:為提高效率,將頻率高的程式碼編譯執行。
Client compiler優化方法:方法內聯(呼叫到的方法直接植入當前方法中)、去虛擬化(如果類的方法只有一個實現類,使用方法內聯)冗餘消除,根據執行狀況時行程式碼摺疊或削除。
Server compiler優化方法:標題替換(用標題替換聚合量,如X替換point.x);棧上分配(如果物件沒逃逸,C2選擇在棧上直接建立對像例項)同步削除(如果同步的物件未逃逸,則沒有同步的必要。)
3) Sun JDK未選擇在啟動時即編譯成機器碼的原因:
a) 靜態編譯不能根據程式執行狀況優化執行程式碼。
b) 解釋執行比編譯執行更節省記憶體。
c) 啟動時解釋執行的啟動速度比編譯再啟動更快。
但程式在未編譯期間解釋執行方式會比較慢,因此需要一個權衡值。
反射執行
可動態呼叫某物件例項中對應的方法、訪問檢視物件的屬性,無需在編寫程式碼時就確定要建立的物件。(getMethod比較耗效能,一要許可權校驗,二要所有方法掃描及Method物件複製)
3.2 JVM記憶體管理
3.2.1 記憶體空間
方法區:存放要載入的類的資訊、靜態變數、final型別常量、類Field資訊、類的方法資訊。通過-XX:PermSize及-XX:MaxPermSize來控制。
堆:儲存物件例項及陣列值.-Xms和-Xmx控制。為避免在執行時頻繁調整Heap大小值設一樣。
Jdk1.2開始分代管理記憶體。
新生代(New Gerneration):新建物件,-Xmn來指定
舊生代(Old Gerneratiion): 快取物件。-Xmx 減去- Xmn決定。
-XX:PretenureSizeThreshold=1024(位元組)表示當物件超過多大時就尖就不在新生代分配,直接在舊生代分配。
本地方法棧:用於支援native方法的執行。儲存每個native方法呼叫的狀態。在SunJDK實現中本地方法棧和JVM方法棧是同一個。
PC暫存器和JVM方法棧:每個執行緒均會建立PC暫存器和JVM方法棧。前者佔用可能為CPU暫存器或作業系統記憶體。JVM方法棧佔用的為作業系統記憶體。JVM方法棧為執行緒私有,分配記憶體上非常高效。當方法執行完畢對應棧幀所佔用記憶體也會自動釋放。JVM方法橈空間不足會丟擲StackOverflowError.。在JDK中可通過-Xss來指定其大小。
3.2.2 記憶體分配
Java物件在堆中分配,堆為執行緒共享,因此在堆中分配記憶體要加鎖。堆空間不足觸發GC。GC後不足,觸發OutofMemery。
TLAB(Thread localAllocation buffer):用於提升記憶體效率。在每個新建立執行緒的新生代的EdenSpace提供獨立區域。大小由JVM根據執行情況計算而得。可通過-XX:TLABWasteTargetPercent來設定TLAB可佔用Eden Space的百分比。預設1%。影響TLAB空間大小引數:-XX的配置、執行緒數量、執行緒是否頻繁分配物件。TLAB上分配記憶體不需要加鎖,因此JVM儘量在TLAB上分配物件記憶體。可通過在啟動引數上增加-XX:+PrintTLAB來檢視空間使用情況。
除了在堆上分配及TLAB上分配還有基於逃逸分析直接在棧上進行分配的方式。
3.2.3 記憶體回收
通常採用收集器的方式實現GC,有可引用計數收集器和跟蹤收集器。
可用計數收集器:在迴圈引用中無法GC
跟蹤收集器:採用集中管理,全域性跟蹤物件引用狀態。通過事件觸發從根集合掃描引用關係。
根據不同的區域採用不同的GC:
MinsorGC 、Full GC等略。
3.2.4 記憶體檢視方法與分析工具
1,輸出日誌:需要人為分析。
2,GC Portal:幫助分析GC日誌。需要老版本Tomcat
3,,Jconsole:JDK5以上自帶工具。
4,JvisulVM:JDK6 update7之後的工具。可安裝VisualGC外掛來分析GC趨勢。
5,JMAP:JDK 的bin目錄下。分析JVM記憶體狀況
6,JHAT:6以後自帶(bin下),分析JVM堆dump工具。
7,JSTAT:除以上,還可看編譯狀況。
8,EclipseMemory Analyzer:eclipse提供的工具。
3.3 記憶體執行緒資源同步與互動機制
3.3.1 資源同步機制
Lock/unlock。Sychronicze從略
3.3.2 互動機制
Wait/notify方法。從略
3.3.3 執行緒狀態與分析
(略)