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

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

2018-12-08    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線(xiàn)!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

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

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

– from 姜志明

對(duì)象創(chuàng)建

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

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

對(duì)象內(nèi)存布局

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

對(duì)象訪(fǎng)問(wèn)

兩種方式:

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

內(nèi)存溢出異常

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

常見(jiàn)異常及可能原因

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

判斷對(duì)象是否存活

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

垃圾收集算法

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

HotSpot 算法實(shí)現(xiàn)

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

垃圾收集器

  • 并發(fā)(concurrent) vs 并行(parallel)
    1. 并行是同時(shí)進(jìn)行(多 CPU)
    2. 并發(fā)可交替
  • Minor GC vs Major GC vs Full GC
    • Minor GC:只回收新生代
    • Major GC:只回收永久代
    • Full GC: 回收整個(gè)堆。相當(dāng)于 Minor GC + Major GC
  1. serial。單線(xiàn)程,簡(jiǎn)單高效。復(fù)制算法
  2. PerNew。serial 的多線(xiàn)程版本,并行。
  3. parallel Scavenge。 與 PerNew 類(lèi)似,復(fù)制算法、多線(xiàn)程、并行。但側(cè)重吞吐量,擁有自適應(yīng)調(diào)節(jié)的能力。適合用在后臺(tái)不需要太多用戶(hù)交互的地方。
    • 吞吐量 = 用戶(hù)代碼執(zhí)行時(shí)間 / (用戶(hù)代碼執(zhí)行時(shí)間 + 垃圾回收時(shí)間)
    • 自適應(yīng)調(diào)節(jié):虛擬機(jī)根據(jù)但前系統(tǒng)的運(yùn)行情況,自動(dòng)調(diào)節(jié)虛擬機(jī)各參數(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)秀的一款收集器,但還是有幾個(gè)缺點(diǎn):
    • 對(duì) CPU 資源敏感,當(dāng)其小于數(shù)量小于 4 個(gè)是可能會(huì)對(duì)用戶(hù)程序有較大影響。默認(rèn)啟動(dòng)回收線(xiàn)程數(shù) = (CPU 數(shù) + 3)/ 4
    • 無(wú)法處理浮動(dòng)垃圾。浮動(dòng)垃圾:在垃圾回收期間生成的垃圾
    • 回收后會(huì)留有大量的空間碎片。
  7. G1 //TODO

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

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

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

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

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

第七章 虛擬機(jī)類(lèi)加載機(jī)制

類(lèi)加載的過(guò)程

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

2. 連接

  • 驗(yàn)證

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

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

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

  • 解析

將符號(hào)引用替換為直接引用

3. 初始化

  • static fields and block init

4. 使用
5. 卸載

類(lèi)加載器

一個(gè)加載器確定一個(gè)類(lèi)的命名空間。同一個(gè)類(lèi)由不同加載器加載后是不同的類(lèi)。

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

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

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

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

解析與填充符號(hào)表

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

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

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

參考

  1. 鄭州大學(xué)姜志明老師課件
  2. 初探Java字符串?(非常好的一篇文章)
  3. Java HotSpot VM 參數(shù)
  4. Java HotSpot Virtual Machine Garbage Collection Tuning Guide
  5. JVM 垃圾回收器工作原理及使用實(shí)例介紹 — 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),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀(guān)點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:用信鴿來(lái)解釋 HTTPS

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