偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java程序員必備基礎(chǔ)結(jié)構(gòu)圖

開發(fā) 后端
最近看了深入理解Java虛擬機(jī)第三版,整理了一些基礎(chǔ)結(jié)構(gòu)圖,算是比較全的了,做一下筆記,大家一起學(xué)習(xí)。

前言

最近看了深入理解Java虛擬機(jī)第三版,整理了一些基礎(chǔ)結(jié)構(gòu)圖,算是比較全的了,做一下筆記,大家一起學(xué)習(xí)。

[[324862]]

1.Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)圖

JVM內(nèi)存結(jié)構(gòu)是Java程序員必須掌握的基礎(chǔ)。

程序計(jì)數(shù)器

  • 程序計(jì)數(shù)器,可以看作當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器
  • 它是線程私有的。

Java虛擬機(jī)棧

  • 線程私有的,生命周期與線程相同。
  • 每個(gè)方法被執(zhí)行的時(shí)候都會(huì)創(chuàng)建一個(gè)"棧幀",用于存儲(chǔ)局部變量表(包括參數(shù))、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。
  • 局部變量表存放各種基本數(shù)據(jù)類型boolean、byte、char、short等

本地方法棧

  • 與虛擬機(jī)?;绢愃?,區(qū)別在于虛擬機(jī)棧為虛擬機(jī)執(zhí)行的java方法服務(wù),而本地方法棧則是為Native方法服務(wù)。

Java堆

  • Java堆是java虛擬機(jī)所管理的內(nèi)存中最大的一塊內(nèi)存區(qū)域,也是被各個(gè)線程共享的內(nèi)存區(qū)域,在JVM啟動(dòng)時(shí)創(chuàng)建。
  • 其大小通過-Xms和-Xmx參數(shù)設(shè)置,-Xms為JVM啟動(dòng)時(shí)申請(qǐng)的最小內(nèi)存,-Xmx為JVM可申請(qǐng)的最大內(nèi)存。

方法區(qū)

  • 它用于存儲(chǔ)虛擬機(jī)加載的類信息、常量、靜態(tài)變量、是各個(gè)線程共享的內(nèi)存區(qū)域。-可以通過-XX:PermSize 和 -XX:MaxPermSize 參數(shù)限制方法區(qū)的大小。

2. 堆的默認(rèn)分配圖

  • Java堆 = 老年代 + 新生代
  • 新生代 = Eden + S0 + S1
  • 新生代與老年代默認(rèn)比例的值為 1:2 ,可以通過參數(shù) –XX:NewRatio 配置。
  • 默認(rèn)的,Eden : from : to = 8 : 1 : 1 ,可以通過參數(shù)–XX:SurvivorRatio 來設(shè)定

3.方法區(qū)結(jié)構(gòu)圖

方法區(qū)是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)已被虛擬機(jī)加載的類型信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼緩存等數(shù)據(jù)。

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

一個(gè)Java對(duì)象在堆內(nèi)存中包括對(duì)象頭、實(shí)例數(shù)據(jù)和補(bǔ)齊填充3個(gè)部分:

  • 對(duì)象頭包括Mark Word(存儲(chǔ)哈希碼,GC分代年齡等) 和 類型指針(對(duì)象指向它的類型元數(shù)據(jù)的指針),如果是數(shù)組對(duì)象,還有一個(gè)保存數(shù)組長(zhǎng)度的空間
  • 實(shí)例數(shù)據(jù)是對(duì)象真正存儲(chǔ)的有效信息,包括了對(duì)象的所有成員變量,其大小由各個(gè)成員變量的大小共同決定。
  • 對(duì)齊填充不是必然存在的,僅僅起占位符的作用。

5.對(duì)象頭的Mark Word圖

  • Mark Word 用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程 ID、偏向時(shí)間戳等。
  • 在32位的HotSpot虛擬機(jī)中,如果對(duì)象處于未被鎖定的狀態(tài)下,那么Mark Word的32bit空間里的25位用于存儲(chǔ)對(duì)象哈希碼,4bit用于存儲(chǔ)對(duì)象分代年齡,2bit用于存儲(chǔ)鎖標(biāo)志位,1bit固定為0,表示非偏向鎖。

6.對(duì)象與Monitor關(guān)聯(lián)結(jié)構(gòu)圖

對(duì)象是如何跟monitor有關(guān)聯(lián)的呢?

一個(gè)Java對(duì)象在堆內(nèi)存中包括對(duì)象頭,對(duì)象頭有Mark word,Mark word存儲(chǔ)著鎖狀態(tài),鎖指針指向monitor地址。Synchronized的底層跟這相關(guān)哦~

7.Java Monitor的工作機(jī)理圖:

Java 線程同步底層就是監(jiān)視鎖Monitor~,如下是Java Monitor的工作機(jī)理圖:

  • 想要獲取monitor的線程,首先會(huì)進(jìn)入_EntryList隊(duì)列。
  • 當(dāng)某個(gè)線程獲取到對(duì)象的monitor后,進(jìn)入Owner區(qū)域,設(shè)置為當(dāng)前線程,同時(shí)計(jì)數(shù)器count加1。
  • 如果線程調(diào)用了wait()方法,則會(huì)進(jìn)入WaitSet隊(duì)列。它會(huì)釋放monitor鎖,即將owner賦值為null,count自減1,進(jìn)入WaitSet隊(duì)列阻塞等待。
  • 如果其他線程調(diào)用 notify() / notifyAll() ,會(huì)喚醒WaitSet中的某個(gè)線程,該線程再次嘗試獲取monitor鎖,成功即進(jìn)入Owner區(qū)域。
  • 同步方法執(zhí)行完畢了,線程退出臨界區(qū),會(huì)將monitor的owner設(shè)為null,并釋放監(jiān)視鎖。。

8.創(chuàng)建一個(gè)對(duì)象內(nèi)存分配流程圖

  • 對(duì)象一般是在Eden區(qū)生成。
  • 如果Eden區(qū)填滿,就會(huì)觸發(fā)Young GC。
  • 觸發(fā)Young GC的時(shí)候,Eden區(qū)實(shí)現(xiàn)清除,沒有被引用的對(duì)象直接被清除。
  • 依然存活的對(duì)象,會(huì)被送到Survivor區(qū),Survivor =S0+S1.
  • 每次Young GC時(shí),存活的對(duì)象復(fù)制到未使用的那塊Survivor 區(qū),當(dāng)前正在使用的另外一塊Survivor 區(qū)完全清除,接著交換兩塊Survivor 區(qū)的使用狀態(tài)。
  • 如果Young GC要移送的對(duì)象大于Survivor區(qū)上限,對(duì)象直接進(jìn)入老年代。
  • 一個(gè)對(duì)象不可能一直呆在新生代,如果它經(jīng)過多次GC,依然活著,次數(shù)超過-XX:MaxTenuringThreshold的閥值,它直接進(jìn)入老年代。簡(jiǎn)言之就是,對(duì)象經(jīng)歷多次滾滾長(zhǎng)江,紅塵世事,終于成為長(zhǎng)者(進(jìn)入老年代)

9.可達(dá)性分析算法判定對(duì)象存活

可達(dá)性分析算法是用來判斷一個(gè)對(duì)象是否存活的~

算法的核心思想:

  • 通過一系列稱為“GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始根據(jù)引用關(guān)系向下搜索,搜索走過的路徑稱為“引用鏈”,當(dāng)一個(gè)對(duì)象到 GC Roots 沒有任何的引用鏈相連時(shí)(從 GC Roots 到這個(gè)對(duì)象不可達(dá))時(shí),證明此對(duì)象不可能再被使用。

10.標(biāo)記-清除算法示意圖

  • 標(biāo)記-清除算法是最基礎(chǔ)的垃圾收集算法。
  • 算法分為兩個(gè)階段,標(biāo)記和清除。
  • 首先標(biāo)記出需要回收的對(duì)象,標(biāo)記完成后,統(tǒng)一回收掉被標(biāo)記的對(duì)象。
  • 當(dāng)然可以反過來,先標(biāo)記存活的對(duì)象,統(tǒng)一回收未被標(biāo)記的對(duì)象。
  • 標(biāo)記-清除 兩個(gè)缺點(diǎn)是,執(zhí)行效率不穩(wěn)定和內(nèi)存空間的碎片化問題~

11.標(biāo)記-復(fù)制算法示意圖

  • 1969年 Fenichel提出“半?yún)^(qū)復(fù)制”,將內(nèi)存容量劃分對(duì)等兩塊,每次只使用一塊。當(dāng)這一塊內(nèi)存用完,將還存活的對(duì)象復(fù)制到另外一塊,然后把已使用過的內(nèi)存空間一次清理掉~
  • 1989年,Andrew Appel提出“Appel式回收”,把新生代劃分為較大的Eden和兩塊較小的Survivor空間。每次分配內(nèi)存只使用Eden和其中一塊Survivor空間。發(fā)生垃圾收集時(shí),將Eden和Survivor中仍然存活的對(duì)象一次性復(fù)制到另外一塊Survivor空間上。Eden和Survivor比例是8:1~
  • “半?yún)^(qū)復(fù)制”缺點(diǎn)是浪費(fèi)可用空間,并且,如果對(duì)象存活率高的話,復(fù)制次數(shù)就會(huì)變多,效率也會(huì)降低。

12.標(biāo)記-整理算法示意圖

  • 1974年,Edward 提出“標(biāo)記-整理”算法,標(biāo)記過程跟“標(biāo)記-清除”算法一樣,接著讓所有存活的對(duì)象都向內(nèi)存空間一端移動(dòng),然后直接清理掉邊界以外的內(nèi)存~
  • 標(biāo)記-清除算法和標(biāo)記整理算法本質(zhì)差異是:前者是一種非移動(dòng)式的回收算法,后者是移動(dòng)式的回收算法。
  • 是否移動(dòng)存活對(duì)象都存在優(yōu)缺點(diǎn),移動(dòng)雖然內(nèi)存回收復(fù)雜,但是從程序吞吐量來看,更劃算;不移動(dòng)時(shí)內(nèi)存分配更復(fù)雜,但是垃圾收集的停頓時(shí)間會(huì)更短,所以看收集器取舍問題~
  • Parallel Scavenge收集器是基于標(biāo)記-整理算法的,因?yàn)殛P(guān)注吞吐。CMS收集器是基于標(biāo)記-清除算法的,因?yàn)樗P(guān)注的是延遲。

13.垃圾收集器組合圖

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:CMS、Serial Old、Parallel Old
  • 混合收集器:G1

14.類的生命周期圖

一個(gè)類從被加載到虛擬機(jī)內(nèi)存開始,到卸載出內(nèi)存為止,這個(gè)生命周期經(jīng)歷了七個(gè)階段:加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用、卸載。

加載階段:

  • 通過一個(gè)類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流。
  • 將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。
  • 在內(nèi)存中生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口

驗(yàn)證:

  • 驗(yàn)證的目的是確保Class文件的字節(jié)流中包含的信息滿足約束要求,保證這些代碼運(yùn)行時(shí)不會(huì)危害虛擬機(jī)自身安全
  • 驗(yàn)證階段有:文件格式校驗(yàn)、元數(shù)據(jù)校驗(yàn)、字節(jié)碼校驗(yàn)、符號(hào)引用校驗(yàn)。

準(zhǔn)備

  • 準(zhǔn)備階段是正式為類中定義的變量(靜態(tài)變量)分配內(nèi)存并設(shè)置類變量初始值的階段。

解析

  • 解析階段是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過程。

初始化

  • 到了初始化階段,才真正開始執(zhí)行類中定義的Java字節(jié)碼。

15.類加載器雙親委派模型圖

雙親委派模型構(gòu)成

啟動(dòng)類加載器,擴(kuò)展類加載器,應(yīng)用程序類加載器,自定義類加載器

雙親委派模型工作過程是

如果一個(gè)類加載器收到類加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器完成。每個(gè)類加載器都是如此,只有當(dāng)父加載器在自己的搜索范圍內(nèi)找不到指定的類時(shí)(即ClassNotFoundException),子加載器才會(huì)嘗試自己去加載。

為什么需要雙親委派模型?

如果沒有雙親委派,那么用戶是不是可以自己定義一個(gè)java.lang.Object的同名類,java.lang.String的同名類,并把它放到ClassPath中,那么類之間的比較結(jié)果及類的唯一性將無法保證,因此,雙親委派模型可以防止內(nèi)存中出現(xiàn)多份同樣的字節(jié)碼。

16.棧幀概念結(jié)構(gòu)圖

棧幀是用于支持虛擬機(jī)進(jìn)行方法調(diào)用和方法執(zhí)行背后的數(shù)據(jù)結(jié)構(gòu)。棧幀存儲(chǔ)了方法的局部變量表、操作數(shù)棧、動(dòng)態(tài)連接和方法返回地址信息。

局部變量表

  • 是一組變量值的存儲(chǔ)空間,用于存放方法參數(shù)和方法內(nèi)部定義的局部變量。
  • 局部變量表的容量以變量槽(Variable Slot)為最小單位。

操作數(shù)棧

  • 操作數(shù)棧,也稱操作棧,是一個(gè)后入先出棧。
  • 當(dāng)一個(gè)方法剛剛開始執(zhí)行的時(shí)候, 該方法的操作數(shù)棧也是空的, 在方法的執(zhí)行過程中, 會(huì)有各種字節(jié)碼指令往操作數(shù)棧中寫入和提取內(nèi)容, 也就是出棧與入棧操作。

動(dòng)態(tài)連接

  • 每個(gè)棧幀都包含一個(gè)指向運(yùn)行時(shí)常量池中該棧幀所屬方法的引用, 持有引用是為了支持方法調(diào)用過程中的動(dòng)態(tài)連接(Dynamic Linking)。

方法返回地址

  • 當(dāng)一個(gè)方法開始執(zhí)行時(shí), 只有兩種方式退出這個(gè)方法 。一種是執(zhí)行引擎遇到任意一個(gè)方法返回的字節(jié)碼指令。另外一種退出方式是在方法執(zhí)行過程中遇到了異常。

17.Java內(nèi)存模型圖

  • Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中
  • 每條線程還有自己的工作內(nèi)存
  • 線程的工作內(nèi)存中保存了該線程中是用到的變量的主內(nèi)存副本拷貝
  • 線程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存。
  • 不同的線程之間也無法直接訪問對(duì)方工作內(nèi)存中的變量,線程間變量的傳遞均需要自己的工作內(nèi)存和主存之間進(jìn)行數(shù)據(jù)同步進(jìn)行。

18.線程狀態(tài)轉(zhuǎn)換關(guān)系圖

Java語言定義了6種線程池狀態(tài):

  • 新建(New):創(chuàng)建后尚未啟動(dòng)的線程處于這種狀態(tài)
  • 運(yùn)行(Running):線程開啟 start()方法,會(huì)進(jìn)入該狀態(tài)。
  • 無限等待(Waiting):處于這種狀態(tài)的線程不會(huì)被分配處理器執(zhí)行時(shí)間,一般 LockSupport::park(),沒有設(shè)置了Timeoout的 Object::wait()方法,會(huì)讓線程陷入無限等待狀態(tài)。
  • 限期等待(Timed Waiting):處于這種狀態(tài)的線程不會(huì)被分配處理器執(zhí)行時(shí)間,在一定時(shí)間之后他們會(huì)由系統(tǒng)自動(dòng)喚醒。 sleep()方法會(huì)進(jìn)入該狀態(tài)~
  • 阻塞(Blocked):在程序等待進(jìn)入同步區(qū)域的時(shí)候,線程將進(jìn)入這種狀態(tài)~
  • 結(jié)束(Terminated):已終止線程的線程狀態(tài),線程已經(jīng)結(jié)束執(zhí)行

19. Class文件格式圖

  • u1、u2、u4、u8 分別代表1個(gè)字節(jié)、2個(gè)字節(jié)、4個(gè)字節(jié)和8個(gè)字節(jié)的無符號(hào)數(shù)
  • 表是由多個(gè)無符號(hào)數(shù)或者其他表作為數(shù)據(jù)項(xiàng)構(gòu)成的復(fù)合數(shù)據(jù)類型
  • 每個(gè)Class文件的頭四個(gè)字節(jié)被稱為魔數(shù)(記得以前校招面試,面試官問過我什么叫魔數(shù)。。。)
  • minor和major version表示次版本號(hào),主版本號(hào)
  • 緊接著主次版本號(hào)之后,是常量池入口,常量池可以比喻為Class文件里的資源倉庫~

20.JVM參數(shù)思維導(dǎo)圖

JVM調(diào)優(yōu)是通往高級(jí)開發(fā)的必經(jīng)橋梁,所以好好積累JVM參數(shù)配置哈~

 

責(zé)任編輯:華軒 來源: 撿田螺的小男孩
相關(guān)推薦

2020-05-09 11:20:02

Java結(jié)構(gòu)圖虛擬機(jī)

2020-01-12 19:10:30

Java程序員數(shù)據(jù)

2009-06-25 09:33:43

Java API程序員

2020-03-16 08:22:11

Java程序員虛擬機(jī)

2020-07-20 07:46:01

程序員加簽驗(yàn)簽

2020-04-20 19:00:30

程序員分布式事務(wù)架構(gòu)

2019-09-25 11:39:07

程序員編程技術(shù)

2022-10-24 09:00:47

畫圖工具程序員XMind

2014-08-15 14:25:48

Android程序員資源

2014-08-20 10:28:29

Android

2011-06-11 20:59:12

程序員

2021-05-06 07:04:35

安全漏洞業(yè)務(wù)

2009-07-02 15:10:17

Java程序員面試

2015-08-20 14:34:25

程序員java基礎(chǔ)網(wǎng)絡(luò)編程

2022-03-17 10:24:28

JavaJVM

2019-07-05 10:45:27

Java程序員編程語言

2015-07-09 10:30:35

程序員必備經(jīng)驗(yàn)

2020-10-14 08:32:08

算法遞歸面試

2020-04-20 11:19:00

Java開發(fā)序列化

2019-07-19 10:04:05

Java程序員Tomcat
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)