1. 程式人生 > >《分散式java應用:基礎與實踐》筆記3

《分散式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 執行緒狀態與分析


(略)