中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

《深入理解 Java 虛擬機 》學(xué)習(xí)筆記

2018-12-08    來源:importnew

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

第二章 Java 內(nèi)存區(qū)域與內(nèi)存溢出異常

內(nèi)存區(qū)域

– from 姜志明

對象創(chuàng)建

  1. 加載類
    • 若已經(jīng)在內(nèi)存中則跳過。
    • 類加載完以后就可以確定對象所需的空間大小?// TODO why?
  2. 分配內(nèi)存
    • 根據(jù) GC 回收算法的不同,分配方式略有區(qū)別。
      • 標(biāo)記整理算法,使用空閑列表
      • 帶壓縮的算法,使用指針碰撞(已分配和未分配內(nèi)存間由指針分隔)
  3. 內(nèi)存清零
  4. 對象初始化

對象的內(nèi)存布局

對象內(nèi)存布局

  • MarkWord 占用一個?字?的大小,其中分為兩部分:
    1. 對象自身運行時元數(shù)據(jù)。例如,哈希碼、GC 分代年齡、鎖狀態(tài)標(biāo)志等等
    2. 類型指針。指向其類的元數(shù)據(jù)。
    3. 若對象是數(shù)組則還需要保存數(shù)組的長度。
  • 域的存儲順序:
    1. 基本類型優(yōu)先,長度長的優(yōu)先。
    2. 父類域優(yōu)先。子類較短域可插入父類域空隙。
    3. 受虛擬機分配策略參數(shù)和域定義順序的影響。

對象訪問

兩種方式:

  1. 直接引用
  2. 引用句柄(句柄池)

內(nèi)存溢出異常

常用 JVM 參數(shù) (Java HotSpot VM)

常見異常及可能原因

  • 堆區(qū)
    • OutOfMemoryException。使用工具對快照進行分析,看是否發(fā)生了內(nèi)存泄露(內(nèi)存中有不再使用的但無法回收的對象或資源)。若是,則通過分析引用鏈找到根源,解決問題;若不是檢查虛擬機堆參數(shù),看是否能夠調(diào)大。再檢查代碼中是否有生命周期很長的大對象。
  • 虛擬機棧和本地方法棧
    • OutOfMemoryException。棧容量 * 線程數(shù)量 = 固定值。當(dāng)線程數(shù)量過多時會引發(fā),可以適當(dāng)減小棧容量。
    • StackOverflowException。按異常查根源。
  • 方法區(qū)和運行時常量池
  • 直接內(nèi)存溢出
    • 不正確的使用 NIO。

String 與字符串常量

public class StringTest {
	public static void main(String[] args) {
		String m = "hello";
		String n = "hello";
		String u = new String(m);
		String v = new String("hello");
		
		System.out.println("m == n: " + (m == n));
		System.out.println("m == u: " + (m == u));
		System.out.println("m == v: " + (m == v)

參考:?初探Java字符串

第三章 垃圾收集器與內(nèi)存分配策略

判斷對象是否存活

  1. 引用計數(shù)器算法。給對象添加一個引用計數(shù)器,增加/刪除引用時對計數(shù)器進行修訂。但是該方法因為無法解決循環(huán)引用(例如兩個對象互相引用)的問題,所以一般不使用該方法
  2. 可達性分析算法。從?GC root?開始遞歸查詢并標(biāo)記,結(jié)束后未被標(biāo)記的(不可達的)即為可回收的對象。GC root?共有四種:
    • 棧中引用的對象
    • 方法區(qū)常量引用的對象
    • 方法區(qū)靜態(tài)域引用的對象
    • 本地方法中 JNI 引用的對象(不太懂)
  3. 回收方法區(qū)
    • 新生代的回收效率可達到 70% – 95%,而永久代則低的多(性價比太低)
    • 在大量使用反射、動態(tài)代理、CGLib 等 ByteCode 框架、動態(tài)生成 JSP 以及 OSGi 這類頻繁自定義 ClassLoader 的場景都需要虛擬機有卸載類的能力。

垃圾收集算法

  1. 標(biāo)記-清除算法
    • 掃描一遍,標(biāo)記出需要回收的對象,再掃描將其清除
    • 標(biāo)記/清除兩階段時間效率都不高,且回收后空間較零碎。
  2. 復(fù)制算法
    • 將內(nèi)存分為兩塊,當(dāng)一塊中內(nèi)存不足時,將其中所有存活對象復(fù)制到另一塊中,回收當(dāng)前一整塊。
    • 目前商用虛擬機大都使用這一算法回收新生代。將內(nèi)存劃分為一個較大的 Eden 區(qū)和兩塊較小的 Survivor. Eden:Survivor = 8:1
  3. 標(biāo)記整理算法
    • 標(biāo)記出須清理的對象,然后其余對象移動到一端
  4. 分代收集算法
    • 新生代使用復(fù)制算法
    • 永久代使用其他兩種算法

HotSpot 算法實現(xiàn)

  1. 當(dāng)程序執(zhí)行到安全點(safepoint)時進行 GC,通過在安全點(safepoint)生成的 OopMaps 快速遍歷 GC root 進行回收。
    • 安全點(safepoint):指令序列復(fù)用的位置。例如方法調(diào)用、循環(huán)結(jié)構(gòu)、異常跳轉(zhuǎn)等位置。
    • OopMaps:一種特殊的數(shù)據(jù)結(jié)構(gòu),用于枚舉 GC root
  2. 但是如果線程處于不執(zhí)行的狀態(tài)時,如 sleep 或 blocked 無法執(zhí)行到安全點,即需要提前標(biāo)記為安全區(qū)域(safe region)。GC 時不考慮處于安全區(qū)域的線程,若安全區(qū)域代碼執(zhí)行結(jié)束但 GC 未結(jié)束時該線程等待 GC 結(jié)束信號。
    • 安全區(qū)域(safe region):引用不發(fā)生改變的代碼片段

垃圾收集器

  • 并發(fā)(concurrent) vs 并行(parallel)
    1. 并行是同時進行(多 CPU)
    2. 并發(fā)可交替
  • Minor GC vs Major GC vs Full GC
    • Minor GC:只回收新生代
    • Major GC:只回收永久代
    • Full GC: 回收整個堆。相當(dāng)于 Minor GC + Major GC
  1. serial。單線程,簡單高效。復(fù)制算法
  2. PerNew。serial 的多線程版本,并行。
  3. parallel Scavenge。 與 PerNew 類似,復(fù)制算法、多線程、并行。但側(cè)重吞吐量,擁有自適應(yīng)調(diào)節(jié)的能力。適合用在后臺不需要太多用戶交互的地方。
    • 吞吐量 = 用戶代碼執(zhí)行時間 / (用戶代碼執(zhí)行時間 + 垃圾回收時間)
    • 自適應(yīng)調(diào)節(jié):虛擬機根據(jù)但前系統(tǒng)的運行情況,自動調(diào)節(jié)虛擬機各參數(shù)以確保最大吞吐量。
  4. serial old。serial 的永久代版本。采用標(biāo)記整理算法。
  5. parallel old。parallel Scavenge 的老年代版本,采用標(biāo)記整理算法。與 parallel scavenge 搭配可以用在注重吞吐量及 CPU 資源敏感的地方。
  6. CMS(concurrent mark sweep)。并發(fā)低停頓,使用標(biāo)記清理算法。非常優(yōu)秀的一款收集器,但還是有幾個缺點:
    • 對 CPU 資源敏感,當(dāng)其小于數(shù)量小于 4 個是可能會對用戶程序有較大影響。默認(rèn)啟動回收線程數(shù) = (CPU 數(shù) + 3)/ 4
    • 無法處理浮動垃圾。浮動垃圾:在垃圾回收期間生成的垃圾
    • 回收后會留有大量的空間碎片。
  7. G1 //TODO

內(nèi)存分配與回收策略

TLAB(Thread local allocate buffer)線程私有分配緩沖區(qū),每個線程一個

  1. 對象優(yōu)先在 Eden 區(qū)分配。內(nèi)存不足時觸發(fā) Minor GC。
  2. 大對象直接進入老年代。例如數(shù)組或超過參數(shù)指定大小的對象。
  3. 長期存活的對象進入老年代。GC 超過一定次數(shù)仍存活的對象。默認(rèn)為 15 次,可通過虛擬機參數(shù)?-XX:MaxTenuringThreshold?來設(shè)置。
  4. 動態(tài)對象年齡判定。當(dāng)一個年齡的所有對象大小總和超過 Servivor 空間一半時,大于等于該年齡的所有對象都進入老年代
  5. 空間分配擔(dān)保。當(dāng)發(fā)生 Minor GC 時,若存活的對象過多,servivor 空間無法全部容納時,會將剩余的對象直接放入永久代;若永久代空間不足以容納時會引發(fā)一次 Full GC

第六章 類文件結(jié)構(gòu)

  1. 類文件的結(jié)構(gòu)擁有固定的格式,包含兩部分的數(shù)據(jù):
    • 類的元數(shù)據(jù)。
    • 方法代碼的字節(jié)流
  2. code?屬性表包含的屬性
    • max_stack?存儲操作數(shù)棧的最大深度值。運行時用來確定分配棧幀中所需的操作數(shù)棧深度。
    • max_locals?局部變量所需的最大空間大小
  3. 符號引用
    • 類與接口的全限定名
    • 域的名稱與描述符
    • 方法名與描述符
  4. 該部分內(nèi)容可以通過查表獲得,不再贅述。

第七章 虛擬機類加載機制

類加載的過程

1. 加載
通過全類名獲取該類的二進制字節(jié)流
解析字節(jié)流,將字節(jié)流所表達的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu) (這是什么東西?)
為該類創(chuàng)建一個 Class 對象,用來訪問該類的類數(shù)據(jù)

2. 連接

  • 驗證

為了確保加載的字節(jié)流時符合規(guī)范的,不會危害到虛擬機自身的安全。主要包括

  1. 文件格式驗證
  2. 元數(shù)據(jù)驗證
  3. 字節(jié)碼驗證
  4. 符號引用驗證
  • 準(zhǔn)備

為類變量分配內(nèi)存并進行初步初始化(0/null) // 不應(yīng)該是在類加載階段完成的么?

  • 解析

將符號引用替換為直接引用

3. 初始化

  • static fields and block init

4. 使用
5. 卸載

類加載器

一個加載器確定一個類的命名空間。同一個類由不同加載器加載后是不同的類。

雙親委派:當(dāng)需要加載一個類時先使用父類加載器(其實這個地方不是很準(zhǔn)確,父子關(guān)系是通過復(fù)合來實現(xiàn)的),若失敗了,再使用當(dāng)前的加載器。如果自己寫一個?Object?類,編譯可通過但是由于雙親委派,它永遠都不會被加載。

第十章 早期(編譯器)優(yōu)化

// TODO: 因本章含有相當(dāng)多的編譯原理相關(guān)概念,所以第十、十一章學(xué)習(xí)延后(預(yù)計第 8-9 周)

前端編譯過程(*.java --> *.class

解析與填充符號表

詞法分析。將源代碼轉(zhuǎn)換為標(biāo)記(Token) 的集合

  • Token: 是編譯過程中的最小元素。例如關(guān)鍵字、變量名、運算符等等

語法分析。通過 Token 序列將構(gòu)造抽象語法樹(Abstract syntax tree)

參考

  1. 鄭州大學(xué)姜志明老師課件
  2. 初探Java字符串?(非常好的一篇文章)
  3. Java HotSpot VM 參數(shù)
  4. Java HotSpot Virtual Machine Garbage Collection Tuning Guide
  5. JVM 垃圾回收器工作原理及使用實例介紹 — IBM
  6. Minor GC vs Major GC vs Full GC
  7. Abstract syntax tree
  8. 4.4 Symbol Tables

標(biāo)簽: ssl 安全 代碼

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:用信鴿來解釋 HTTPS

下一篇:如何高效的使用 Git