欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)激活碼778899分享:JVM雨小結(jié)

柚子快報(bào)激活碼778899分享:JVM雨小結(jié)

http://yzkb.51969.com/

JVM

@Author yu

@Date 2024.5.14

文章目錄

JVM一、概述1. 如何理解java語言的跨平臺(tái)性?2. 如何理解JVM是跨語言的平臺(tái)?3.java歷史大事件:4. HotSpot虛擬機(jī)5. JVM組成

字節(jié)碼文件概述1. AOP(Ahead Of Time Compiler提前編譯器):2. 從字節(jié)碼角度看程序運(yùn)行過程(虛擬機(jī)棧)3.Class文件結(jié)構(gòu)4. 常量池(最重要部分?。。。?. java虛擬機(jī)的數(shù)據(jù)類型6.棧和堆的區(qū)別:

二、類的加載1. 類的加載過程(裝、鏈、初)2.類的加載器3. 類加載器的分類4. 雙親委派機(jī)制

三、運(yùn)行時(shí)內(nèi)存篇1. 程序計(jì)數(shù)器(pc)2. 虛擬機(jī)棧3.本地方法接口、棧4.*堆*① 概述:② 堆的內(nèi)部結(jié)構(gòu)四、堆空間對(duì)象分配① 總結(jié):② 分配原則③ Minor GC、Major GC、 Full GC④ OOM如何解決

5. 方法區(qū)① HotSpot中方法區(qū)的演進(jìn)

四、對(duì)象的內(nèi)存布局1. 創(chuàng)建對(duì)象的方式:2.創(chuàng)建對(duì)象的步驟:3.new對(duì)象的流程① 判斷對(duì)象是否加載、鏈接、初始化②為對(duì)象分配空間③ 處理并發(fā)安全問題④ 初始化分配到的空間⑤ 設(shè)置對(duì)象頭⑥ 顯示初始化

3. 對(duì)象包含的內(nèi)容

五、執(zhí)行引擎六、垃圾回收篇1. 垃圾回收算法① 垃圾判別階段算法② 垃圾清除階段的算法

2. 垃圾回收器① . 內(nèi)存泄漏和內(nèi)存溢出② . 五種引用③ . 垃圾回收器

3. 問題③ . 垃圾回收器

3. 問題

一、概述

1. 如何理解java語言的跨平臺(tái)性?

2. 如何理解JVM是跨語言的平臺(tái)?

3.java歷史大事件:

2000,jdk1.3 HotSpot虛擬機(jī)正式發(fā)布,成為java默認(rèn)虛擬機(jī) 2003,java平臺(tái)的Scala正式發(fā)布, 2008,Oracle收購了BEA,得到了,JRockit虛擬機(jī) 目前版本Oracle將HotSpot和JRockit虛擬機(jī)進(jìn)行了整合 2011,JDK7發(fā)布,正式啟用新的垃圾回收器,G1 JDK7,JDK8默認(rèn)的垃圾回收器:并行的(Parallel)垃圾回收器 2017,JDK9將G1定為默認(rèn)的GC,替代CMS(被標(biāo)記為Deprecated,JDK10徹底拿掉了) 同年IBM J9開源 2018,JDK11發(fā)布,LTS版本的JDK,發(fā)布革命性的ZGC

4. HotSpot虛擬機(jī)

2000,jdk1.3 HotSpot虛擬機(jī)正式發(fā)布,成為java默認(rèn)虛擬機(jī),主要使用C++實(shí)現(xiàn),JNI接口部分使用C實(shí)現(xiàn)

HotSpot是較新的java虛擬機(jī),使用JIT(Just in Time)編譯器,可以大大提高java運(yùn)行性能。

java原先是把源代碼編譯為字節(jié)碼在虛擬機(jī)運(yùn)行,這樣執(zhí)行速度較慢,而HotSpot將常用的部分代碼編譯為本地(原生,native)代碼,這樣顯著提高了性能。

5. JVM組成

以下是HotSpot虛擬機(jī)的組成:

線程私有:程序計(jì)數(shù)器、本地方法棧、虛擬機(jī)棧線程共享:方法區(qū)、堆

詳細(xì)架構(gòu)圖:

字節(jié)碼文件概述

java語言是半編譯,半解釋型語言

運(yùn)行java程序時(shí),需要兩個(gè)命令:javac ---->源代碼---->.class字節(jié)碼文件 javac 前端編譯器(不涉及優(yōu)化)

? java xxx.class

JDK1.3后引入了HotSpot虛擬機(jī),加入了JIT及時(shí)編譯器。執(zhí)行.class文件文件時(shí),有兩種方式:

? ① 解釋器逐行解釋字節(jié)碼,使之變?yōu)楸镜貦C(jī)器指令

? ② JIT及時(shí)編譯器,尋找熱點(diǎn)代碼,緩存第一次編譯好的內(nèi)容,直接執(zhí)行。 后端編譯器

1. AOP(Ahead Of Time Compiler提前編譯器):

① 與JIT及時(shí)編譯器(后端編譯器)的區(qū)別: AOP在程序運(yùn)行前將.class文件轉(zhuǎn)為機(jī)器碼,而JIT即時(shí)編譯器在程序運(yùn)行過程中將熱點(diǎn)代碼直接編譯為機(jī)器碼,少了解釋執(zhí)行的步驟 (源代碼---->.class文件----->.so文件)

② 缺點(diǎn):1> 破壞了一次編譯到處運(yùn)行。需要爭對(duì)不同操作系統(tǒng)編譯不同的發(fā)行包

? 2> 破壞了java鏈接過程中的動(dòng)態(tài)型性

2. 從字節(jié)碼角度看程序運(yùn)行過程(虛擬機(jī)棧)

問題一:++i與i++問題

int i = 10;

i = i++;

print(i);// 10

問題二:包裝類緩存問題

Integer i1 = 10;//IntegerCache

Integer i2 = 10;

print(i1==i2)//true

Integer i3 = 128;

Integer i4 = 128;

print(i3==i4)//false

Boolean b1 = true;

Boolean b2 = true;

print(b1==b2)//true

問題三:Sting類型變量通過new 聲明和 通過字面量聲明

String str = new String("hello")+new String("world");

String str1 = "helloworld";

print(str==str1);//false

外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳

分析:底層先new了一個(gè)StringBuilder,壓入操作數(shù)棧,然后進(jìn)行dup操作,相當(dāng)于拷貝,最后將拷貝的StringBuilder彈出,實(shí)現(xiàn)StringBuildre的初始化。然后new了一個(gè)String,然后進(jìn)行dup操作,相當(dāng)于拷貝,最后將拷貝的String彈出,實(shí)現(xiàn)String的初始化。最后將調(diào)用StringBuilder的append方法,將String追加到StringBuilder中,最后調(diào)用StringBulider的toString方法,new了一個(gè)String對(duì)象。

StringBuilder 是JDK5.0新增的非線程安全的類。

JDK8:

String str = new String("hello")+new String("world");

str.intern();//

String str1 = "helloworld";

print(str==str1);//false--->true(加上inten()后變?yōu)閠rue) JDK6變?yōu)閒alse

String str = new String("hello")+new String("world");

String str1 = "helloworld";

str.intern();//

print(str==str1);//false--->(基于上面,交換intern位置,變?yōu)閒alse)

原因:String字面量存儲(chǔ)在常量池中

jdk6 常量池位于方法區(qū)(GC不頻繁),即永久代中 jdk7及之后 常量池位于堆空間,即元空間

對(duì)于jdk6,執(zhí)行intern()方法后,由于常量池沒有字符串內(nèi)容,所以會(huì)在方法區(qū)新創(chuàng)建一個(gè)字符串,和堆空間的字符串地址不同,故返回false

對(duì)于jdk8,執(zhí)行intern()方法后,由于常量池沒有字符串內(nèi)容,但堆空間有,而常量池就在堆空間,所以會(huì)返回堆空間中已經(jīng)存在的字符串地址,故會(huì)返回true。交換位置后,由于常量池中已經(jīng)有相關(guān)字符串內(nèi)容,不在公用對(duì)堆空間執(zhí)行toString方法new出來的字符串對(duì)象,所以會(huì)返回false

問題四:繼承問題

init方法:java中類的每個(gè)構(gòu)造器中都對(duì)應(yīng)一個(gè)init方法:init方法用于對(duì)成員變量進(jìn)行初始化:內(nèi)容及順序:① 顯示初始化 ②/③ 構(gòu)造器中初始化/代碼塊中初始化 | ④ 通過.引用/.方法初始化

運(yùn)行結(jié)果:

外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳

3.Class文件結(jié)構(gòu)

4. 常量池(最重要部分?。。。?/p>

常量池:用于存放編譯時(shí)期生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。

內(nèi)容:

常量具體的常量字面量文本字符串聲明為final的常量符號(hào)引用類和接口的全限定名字段的名稱和描述符方法的名稱和描述符

符號(hào)引用和直接引用

棧---->棧幀----->局部變量表 + 操作數(shù)棧

5. java虛擬機(jī)的數(shù)據(jù)類型

Java虛擬機(jī)中,數(shù)據(jù)類型可以分為哪幾類?

returnAddress:虛擬機(jī)棧中包含幾個(gè)結(jié)構(gòu):局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、返回地址。

6.棧和堆的區(qū)別:

空間上:堆的空間大

運(yùn)行速度上:棧的運(yùn)行速度快

8大基本數(shù)據(jù)類型在創(chuàng)建時(shí)就確定了

為什么不把基本數(shù)據(jù)類型放在堆中?

java是值傳遞還是引用傳遞?

二、類的加載

1. 類的加載過程(裝、鏈、初)

類的生命周期:加載 使用 卸載

一個(gè)類只能被同一個(gè)類加載器加載一次,但一個(gè)類能被不同的類加載多次(類和類的加載器是雙向綁定的關(guān)系)

加載(Loading):查找并加載二進(jìn)制數(shù)據(jù),生成Class實(shí)例 將磁盤中的Class.Files文件加載到內(nèi)存中,(存儲(chǔ)在方法區(qū)成為類模板), 會(huì)創(chuàng)建一個(gè)大的Class實(shí)例 類模板對(duì)象:所謂的類模板對(duì)象,其實(shí)就是java類在JVM內(nèi)存中的一個(gè)快照,JVM將從字節(jié)碼文件中解析出的常量池、類字段、類方法等信息存儲(chǔ)到類模板中,這樣JVM在運(yùn)行期便可以通過類模板獲得java類的任意信息,能夠?qū)ava類的成員變量進(jìn)行遍歷,也能進(jìn)行Java方法的調(diào)用。 反射的機(jī)制即基于這一基礎(chǔ),如果JVM沒有將Java類信息存儲(chǔ)起來,則JVM在運(yùn)行期無法反射。 類模板對(duì)象的位置:加載的類在JVM創(chuàng)建相應(yīng)的類結(jié)構(gòu),類結(jié)構(gòu)會(huì)存儲(chǔ)在方法去(jdk6及之前叫永久代,之后成為元空間) Class實(shí)例:是一個(gè)運(yùn)行時(shí)的類,存儲(chǔ)在堆空間。Class類的構(gòu)造器是私有的,只有JVM能夠創(chuàng)建。 java.lang.Class實(shí)例是訪問類型元數(shù)據(jù)的接口,也是反射的關(guān)鍵數(shù)據(jù)、入口。通過Class類提供的接口,可以獲得目標(biāo)類的數(shù)據(jù)結(jié)構(gòu)、方法、字段信息等。 數(shù)組類型的加載:數(shù)組類本身不是由類的加載器負(fù)責(zé)創(chuàng)建,而是由JVM在運(yùn)行時(shí)根據(jù)需要而創(chuàng)建的,但數(shù)組的元素類型仍需要靠類的加載器創(chuàng)建。由于基本數(shù)據(jù)類型已經(jīng)被JVM預(yù)先定義,所以僅需要加載引用數(shù)據(jù)類型。 鏈接(Linking)

驗(yàn)證(Verify):檢驗(yàn)字節(jié)碼正確性與合法性,通常與加載同時(shí)進(jìn)行。準(zhǔn)備(Prepare):為類的靜態(tài)變量分配內(nèi)存,并賦一個(gè)默認(rèn)值。特殊的對(duì)于static final修飾的變量,該階段會(huì)顯示賦值。通常在初始化完成之后執(zhí)行。解析(Resolve):將類、接口、字段、方法的符號(hào)引用轉(zhuǎn)為直接引用。 初始化(initialization):執(zhí)行方法,該方法不是自定義的,是自動(dòng)生成的。

:只有在給類中的static變量顯示賦值或在靜態(tài)代碼塊中賦值了,才會(huì)生成此方法。

:一定會(huì)出現(xiàn)在Class的method表中。

問題一:子類加載前一定會(huì)先加載父類嗎?

在加載一個(gè)類之前,虛擬機(jī)總是會(huì)試圖加載該類的父類,因此父類的總是在子類之前被掉用,也就是說,父類的static塊優(yōu)先級(jí)高于子類。

口訣:由父及子,靜態(tài)先行

總結(jié):

使用static + final修飾的成員變量,稱為:全局常量

什么時(shí)候在鏈接的準(zhǔn)備環(huán)節(jié):給此全局常量賦的值是字面量或常量,不涉及到方法的調(diào)用。

除此之外,都在初始化環(huán)節(jié)賦值

問題二 : Class的forName(“java.lang.String)和Class的getClassLoader().loadClass(“java.lang.String”)有什么區(qū)別?

Class的forName(“java.lang.String) 會(huì)完成裝載、鏈接、初始化全過程getClassLoader().loadClass(“java.lang.String”) 僅會(huì)完成裝載過程

問題三:哪些情況會(huì)觸發(fā)類的加載/類的加載時(shí)機(jī)

類的卸載:

2.類的加載器

類、類的加載器、類的實(shí)例之間的關(guān)系:

方法區(qū)的元空間使用本地內(nèi)存:很少卸載,防止方法區(qū)溢出。

3. 類加載器的分類

加載類的(鏈接中的Loading階段)。

問題一:何為類的唯一性?

問題二:類加載機(jī)制的三個(gè)基本特征

4. 雙親委派機(jī)制

類加載器分為兩類:啟動(dòng)類加載器(由C語言編寫)和自定義加載器(直接或間接繼承與ClassLoader)

啟動(dòng)類加載器:加載java核心api以及ClassLoader的加載擴(kuò)展類加載器:加載擴(kuò)展api系統(tǒng)類加載器(應(yīng)用程序類加載器):加載用戶自定義的類。用戶自定義加載類:

實(shí)現(xiàn)相關(guān)類庫的動(dòng)態(tài)加載實(shí)現(xiàn)應(yīng)用隔離打破雙親委派機(jī)制

問題一:什么是雙親委派機(jī)制?優(yōu)缺點(diǎn)?

應(yīng)用類加載器加載某些類時(shí),會(huì)把請(qǐng)求轉(zhuǎn)給父類加載器,委托幫忙加載,首先最頂層的類加載器加載,加載不到就轉(zhuǎn)交給子類加載器,如果最終到達(dá)加載器的底層還未找到,就拋出ClassNotFoundException。核心類庫(java包下的一定會(huì)被引導(dǎo)類加載器加載,preDefineClass()接口確保了)。

優(yōu)勢:安全,避免重復(fù)加載

弊端:下層訪問上層,上層加載器無法訪問下層

問題二: 破壞雙親委派

①:jdbc----->線程上下文

②:tomcat類加載機(jī)制

三、運(yùn)行時(shí)內(nèi)存篇

1. 程序計(jì)數(shù)器(pc)

? 記錄下一條指令的地址,也就是即將要執(zhí)行的指令代碼。

2. 虛擬機(jī)棧

問題一:棧和堆的區(qū)別?對(duì)象為什么不放在棧上?

空間小執(zhí)行效率(棧管運(yùn)行,堆管存儲(chǔ))存放的東西GC;OOM

問題二:棧存在GC(垃圾回收)嗎?

不存在GC,但存在OOM(StackOverFlowError)

問題三:如何指定棧大???

-Xss 1m.設(shè)置的??臻g值太大,導(dǎo)致系統(tǒng)可用于創(chuàng)建線程的數(shù)量減少。

問題四:虛擬機(jī)棧的組成(棧幀,一個(gè)棧幀對(duì)應(yīng)一個(gè)方法):

棧幀的組成:

局部變量表:決定局部變量多少。8 + 3 + 1(returnAddress)操作數(shù)棧:棧頂緩存技術(shù)

局部變量表的長度和操作數(shù)的深度在生成字節(jié)碼后就確定了。

動(dòng)態(tài)鏈接:每個(gè)棧幀內(nèi)部都包含一個(gè)指向運(yùn)行時(shí)常量池中該棧幀所屬方法的引用,包含這個(gè)引用的目的就是為了支持當(dāng)前方法的代碼能夠?qū)崿F(xiàn)動(dòng)態(tài)鏈接。返回地址:一個(gè)方法的結(jié)束有兩種方式:正常執(zhí)行完成,出現(xiàn)未處理異常,非正常退出,無論哪種方式退出,方法退出后,都返回該方法被調(diào)用的位置。

問題五:棧溢出的情況?調(diào)整棧大小就能保證內(nèi)存不溢出嗎?(no)

遞歸 StackOverflowError 局部變量表太大 OOM

問題六:分配的棧內(nèi)存越大越好嗎?

不是,因?yàn)檎{(diào)整棧大小,只會(huì)減少出現(xiàn)溢出的可能,棧大小不是可以無線擴(kuò)大的,所以不能保證不出現(xiàn)溢出。

問題七:垃圾回收是否會(huì)涉及到虛擬機(jī)棧?(棧只有溢出而沒有回收)

不會(huì);垃圾回收只會(huì)涉及到方法區(qū)和堆,方法區(qū)和堆也會(huì)存在溢出的可能;

程序計(jì)數(shù)器,只記錄運(yùn)行下一行的地址,不存在溢出和垃圾回收;

虛擬機(jī)棧和本地方法棧,都是只涉及壓棧和出棧,可能存在棧溢出,不存在垃圾回收。

問題五:方法中定義的局部變量是否是線程安全?

對(duì)于引用數(shù)據(jù)類型,對(duì)象存儲(chǔ)在堆中,不會(huì)隨著棧幀的出棧而銷毀,可能會(huì)被其他方法引用,所以可能導(dǎo)致不安全。

3.本地方法接口、棧

本地方法:java調(diào)用c代碼的接口。

4.堆

① 概述:

一個(gè)JVM實(shí)例只存在一個(gè)堆內(nèi)存,堆也是java內(nèi)存管理的核心區(qū)域 JAVA堆區(qū)在JVM啟動(dòng)時(shí)被創(chuàng)建,其空間大小也就確定了,時(shí)JVM管理的最大的一塊內(nèi)存空間 堆內(nèi)存的大小是可以調(diào)節(jié)的 《Java虛擬機(jī)規(guī)范》規(guī)定,堆可以處于物理上不連續(xù)的內(nèi)存空間中,但邏輯上被視為連續(xù)的。 堆是GC的重點(diǎn)區(qū)域 在方法結(jié)束后,堆中的對(duì)象不會(huì)馬上被溢出,僅僅在垃圾回收的時(shí)候才被移除。 對(duì)象都分配在堆上(存在某些優(yōu)化行為 棧上分配 不需要判斷GC 標(biāo)量替換)

問題一:對(duì)象都分配在堆上嗎?

對(duì)象都分配在堆上,但存在某些優(yōu)化行為 -->棧上分配 不需要判斷是否需要GC (并不是把整個(gè)對(duì)象放到棧上,而是標(biāo)量替換)

問題二:所有的線程都共享堆嗎?

所有線程都共享Java堆,但堆的伊甸園區(qū)為每個(gè)線程提供了一個(gè)隔離的空間,TLAB,確保不同線程之間不沖突。

② 堆的內(nèi)部結(jié)構(gòu)

? 堆空間分為新生代和老年代,新生代分為伊甸園區(qū)、from區(qū)、to區(qū)

JDK7 JDK8

問題一:什么是新生代、老年代,為什么要分?

存儲(chǔ)在JVM中的Java對(duì)象可以被分為兩類:

一類是是生命周期短的(朝生夕死),這類對(duì)象的創(chuàng)建和消亡都非常迅速一類生命周期非常長,甚至于JVM生命周期保持一致(Runtime) Java堆區(qū)可以分為新生代(80%的對(duì)象都是朝生夕死)和老年代 其中新生代又可以分為伊甸園區(qū)、from區(qū)、to區(qū)。 幾乎所有的Java對(duì)象都是在伊甸園區(qū)被創(chuàng)建出來的----> 特例 : 大對(duì)象直接進(jìn)入老年代

問題二:如何調(diào)整堆的大?。?/p>

-Xms 堆空間初始化大小

-Xmx 堆空間最大大?。撼^最大報(bào)OOM(OutOfMemoryError:heap)

問題三:為什么通常需要初始堆空間和最大最空間設(shè)置成一樣大???

通常會(huì)將-Xms 和 -Xmx配置相同的值,其目的是為了能夠在java垃圾回收機(jī)制清理完堆區(qū)后不需要重新分割計(jì)算堆區(qū)大小,從而提高性能。不會(huì)忽大忽小。

堆空間默認(rèn)大?。鹤畲笪锢韮?nèi)存1/4 初始大小 物理內(nèi)存1/64

問題四:如何設(shè)置新生代和老年代的大?。?/p>

新生代和老年代默認(rèn)比例為1:2

默認(rèn)-XX:NewRatio=2 表示新生代占1,老年代占2

-XX:NewRation=4 表示新生代占1,老年代占4

伊甸園區(qū)、s0、s1默認(rèn)比例為 8:1:1

四、堆空間對(duì)象分配

① 總結(jié):

from和to區(qū):復(fù)制之后有交換,誰空誰是to 關(guān)于垃圾回收:

頻繁在新生代收集很少在老年代收集幾乎不在方法區(qū)、元空間收集

問題五:描述一下對(duì)象創(chuàng)建的堆空間不同區(qū)域的過程。

new的對(duì)象首先放在堆空間的新生代的伊甸園區(qū),伊甸園區(qū)滿時(shí),會(huì)觸發(fā)Y GC/Minor GC,Minor GC包含兩個(gè)內(nèi)容,一方面會(huì)將伊甸園區(qū)的非垃圾對(duì)象放到s0區(qū),另一方面會(huì)將from區(qū)的非垃圾對(duì)象移至to區(qū)(誰空誰是to),從from移至to區(qū)后對(duì)象的年齡加1,加到15后(采用四個(gè)比特位記錄年齡,默認(rèn)就是15,可以手動(dòng)設(shè)置對(duì)象的年齡閾值),會(huì)將s0/1區(qū)的內(nèi)容移至老年代。在老年代,相對(duì)悠閑,當(dāng)老年代內(nèi)存不足時(shí),會(huì)觸發(fā)Major GC,進(jìn)行老年代的內(nèi)存清理。若老年代進(jìn)行了Major GC后仍發(fā)現(xiàn)內(nèi)存不足,就會(huì)OOM。

② 分配原則

針對(duì)不同年齡段的對(duì)象分配原則如下:

優(yōu)先分配到Eden大對(duì)象直接分配到老年代:

盡量避免在程序中出現(xiàn)大對(duì)象 長期存活的對(duì)象分配到老年代動(dòng)態(tài)對(duì)象年齡判斷:

如果Survivor區(qū)中相同年齡的對(duì)象大小總和大于Survivor空間的一半,年齡大于或等于該年齡的對(duì)象可以直接進(jìn)入老年代,無需等到年齡閾值 空間分配擔(dān)保:在發(fā)生Minor GC之前,虛擬機(jī)會(huì)檢查老年代最大可用的連續(xù)空間是否大于新生代所有對(duì)象的總空間

如果大于,則Minor GC安全如果小于,則虛擬機(jī)會(huì)查看空間分配擔(dān)保是否開啟,如果開啟,那么會(huì)檢查老年代最大可用連續(xù)空間是否大于歷次晉升到老年代的對(duì)象的平均大小,如果大于,則嘗試進(jìn)行一次Minor GC,但這次Minor GC依然是有風(fēng)險(xiǎn)的,如果小于或者空間擔(dān)保未開啟,則進(jìn)行一次full GC。

③ Minor GC、Major GC、 Full GC

新生代(Minor GC)觸發(fā)機(jī)制:

當(dāng)年輕代的伊甸園區(qū)空間不足時(shí),會(huì)觸發(fā)Minor GC。Survivor區(qū)滿不會(huì)觸發(fā)GC。(每次Minor GC會(huì)清理年輕代內(nèi)存)Java對(duì)象大多都是朝生熄死,所以Minor GC非常頻繁,一般回收速度也比較快,Minor GC會(huì)引發(fā)STW 暫停其他用戶線程,等垃圾回收結(jié)束,用戶線程才會(huì)恢復(fù)。

老年代GC (major GC/Full GC)觸發(fā)機(jī)制:

指發(fā)生在老年代的GC,對(duì)象從老年代消失時(shí),major GC/Full GC發(fā)生了。

出現(xiàn) Major GC,經(jīng)常會(huì)伴隨至少一次的Minor GC。即老年代空間不足時(shí),會(huì)先嘗試觸發(fā)Minor GC,如果空間還不足,則觸發(fā)Major GC Major GC的速度一般會(huì)比Minor GC慢 10倍以上,STW的時(shí)間更長。如果Major GC后,內(nèi)存還不足,就報(bào)OOM了。 Full GC觸發(fā)機(jī)制:

調(diào)用System.gc()、Runtime.getRuntime.gc()時(shí),系統(tǒng)建議執(zhí)行Full GC,但不必然執(zhí)行,有安全點(diǎn)的概念老年代空間不足方法區(qū)空間不足通過Minor GC后進(jìn)入老年代的平均大小大于老年代的可用內(nèi)存(空間分配擔(dān)保失?。?/p>

說明:full gc時(shí)開發(fā)調(diào)優(yōu)中盡量要避免的

④ OOM如何解決

分析dump文件內(nèi)存泄漏對(duì)象生命周期過長調(diào)節(jié)虛擬機(jī)參數(shù)

問題六:為什么要把Java堆分代?

優(yōu)化GC性能,范圍小,方便查找及清理

5. 方法區(qū)

幾乎不進(jìn)行GC。

方法區(qū)主要回收兩部分內(nèi)容:常來池中廢棄的常量和不在使用的類的類型。

① HotSpot中方法區(qū)的演進(jìn)

jdk7之前,習(xí)慣把方法區(qū)稱為永久代,jdk8開始,使用元空間(MateSpace)取代了永久代(PermGen) 元空間使用的是本地內(nèi)存,不是虛擬機(jī)層面的內(nèi)存了。

問題一:永久代中存在垃圾回收行為嗎?

存在,但永久代的垃圾回收效果并不好,一般都回收不掉類的加載器回收不掉。除非自定義類的加載器。

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

1. 創(chuàng)建對(duì)象的方式:

new、靜態(tài)方法、工廠方法、反射、clone(默認(rèn)淺拷貝,屬性不拷貝)、反序列化、第三方庫

2.創(chuàng)建對(duì)象的步驟:

從字節(jié)碼來看: 操作數(shù)棧:new 、dup 、 復(fù)制品出棧,觸發(fā)調(diào)用方法,將操作數(shù)棧內(nèi)容保存到局部變量表中。

3.new對(duì)象的流程

① 判斷對(duì)象是否加載、鏈接、初始化

②為對(duì)象分配空間

計(jì)算對(duì)象所需內(nèi)存大小

為對(duì)象分配空間(指針碰撞、空閑鏈表)

指針碰撞(不存在內(nèi)存碎片) ? 如果垃圾收集器選擇的是Serial、ParNew這種基于標(biāo)記壓縮算法的,虛擬機(jī)采用指針碰撞的分配方式。(老年代)

空閑鏈表(存在內(nèi)存碎片) CMS標(biāo)記清除算法。

③ 處理并發(fā)安全問題

CAS(Compare And Swap):加鎖TLAB: 每個(gè)線程在堆空間分配一塊獨(dú)立的線程,成為本地線程分配緩存區(qū)

④ 初始化分配到的空間

? 對(duì)象屬性賦默認(rèn)值

⑤ 設(shè)置對(duì)象頭

? 對(duì)象的HashCode和對(duì)象的GC信息,鎖信息等數(shù)據(jù)存儲(chǔ)在對(duì)象的對(duì)象頭中,這個(gè)過程的具體設(shè)置方式取決于JVM實(shí)現(xiàn)。

⑥ 顯示初始化

? 對(duì)象屬性顯示初始化

3. 對(duì)象包含的內(nèi)容

對(duì)象頭

運(yùn)行時(shí)元數(shù)據(jù):

哈希值GC分代的年齡鎖狀態(tài)標(biāo)識(shí)(數(shù)組長度)對(duì)于數(shù)據(jù)來說 類型指針:指向方法區(qū)類元數(shù)據(jù)(對(duì)象是哪個(gè)類的對(duì)象) 實(shí)例數(shù)據(jù)

父類數(shù)據(jù)本類數(shù)據(jù) 對(duì)齊填充

五、執(zhí)行引擎

問題一:HotSpot虛擬機(jī)為什么既選用JIT及時(shí)編譯器又選用解釋器?為什么說java是半編譯半解釋型語言。

jdk1.3引入了JIT,使得java的運(yùn)行速度不弱于C,原理是.class文件的運(yùn)行過程分為編譯運(yùn)行和解釋運(yùn)行兩種。其中解釋運(yùn)行是對(duì).class文件逐行解釋為機(jī)器碼運(yùn)行,對(duì)于一些熱點(diǎn)代碼,通過方法調(diào)用計(jì)數(shù)器,JIT及時(shí)編譯器會(huì)將熱點(diǎn)代碼編譯成機(jī)器碼進(jìn)行保存。想想油電混動(dòng)。

JIT編譯器有兩種C1編譯器和C2編譯器,其中C2編譯器還對(duì)代碼進(jìn)行動(dòng)態(tài)優(yōu)化,深度優(yōu)化。熱機(jī)時(shí)間較長,適合服務(wù)器:

標(biāo)量替換(先進(jìn)行逃逸分析)棧上分配同步消除:鎖清除

問題二:AOP和JIT的區(qū)別,AOP的不足。

相較于JIT,省去了“熱機(jī)”的過程。在程序運(yùn)行前就將代碼直接編譯為機(jī)器語言,但違背了java的跨平臺(tái)性,且沒有動(dòng)態(tài)優(yōu)化。

總結(jié):

一般來講,JIT編譯出來的機(jī)器碼性能比解釋器高C2編譯器啟動(dòng)時(shí)長比C1編譯器慢,系統(tǒng)穩(wěn)定執(zhí)行后,C2編譯器執(zhí)行比C1快。

六、垃圾回收篇

1. 垃圾回收算法

① 垃圾判別階段算法

? 當(dāng)一個(gè)對(duì)象已經(jīng)不被任何對(duì)象所繼續(xù)引用時(shí),就可以宣判對(duì)象死亡了。

? 引用計(jì)數(shù)算法:計(jì)數(shù)器,引用 + 1 不引用 -1 計(jì)數(shù)為0 清除

? 問題:無法解決循環(huán)引用問題

? *可達(dá)性分析算法(根搜索算法、追蹤性垃圾收集算法):java選擇這個(gè)

? 局部變量表(根GC Root)相連的就可達(dá)。沒有循環(huán)引用問題。但 仍存在OOM情況,取GCRoot需要STW

? GC ROOT :局部變量表、類靜態(tài)屬性、方法區(qū)常量、異常、鎖

② 垃圾清除階段的算法

標(biāo)記清除算法(Mark-Sweep):標(biāo)記不是垃圾的對(duì)象,清除其余 缺點(diǎn):內(nèi)存碎片化 CMS老年代采用標(biāo)記清除算法

![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/a9f9e3897ed0491989fdf3992fee11db.png)

復(fù)制算法:標(biāo)記不是垃圾的對(duì)象,將其按順序復(fù)制到另外一份空間中 優(yōu)點(diǎn):沒有內(nèi)存碎片 缺點(diǎn):耗費(fèi)內(nèi)存,適合于存活對(duì)象少的區(qū)域(新生代) 新生代使用的是復(fù)制算法,所以有s0區(qū)和s1區(qū)。 標(biāo)記壓縮算法(Mark and Compact):除CMS其他老年代用的是標(biāo)記壓縮 優(yōu)點(diǎn):消除了 標(biāo)記清除 和 復(fù)制 算法的弊端 空間開銷小, 缺點(diǎn):效率低于復(fù)制算法 ? 效率不高,不僅要標(biāo)記所有存活對(duì)象,還要整理所有存活對(duì)象的引用地址。 ? 對(duì)于老年代每次都有大量存活區(qū)域來說,極為負(fù)重。 ? 移動(dòng)對(duì)象的同時(shí),如果對(duì)象被其他對(duì)象引用,則還需要調(diào)整引用的地址。 ? 移動(dòng)過程中,需要暫停用戶應(yīng)用程序。STW

增量收集算法 為減少STW,垃圾收集線程和程序運(yùn)行線程交替進(jìn)行。第延遲,但吞吐量下降。

2. 垃圾回收器

① . 內(nèi)存泄漏和內(nèi)存溢出

② . 五種引用

強(qiáng)引用:90%對(duì)象是強(qiáng)引用,gc無法回收軟引用:內(nèi)存不足回收: SoftReference:用于實(shí)現(xiàn)內(nèi)存敏感的緩存高速緩存弱引用:發(fā)現(xiàn)即回收:WeakHashMap:可有可無的緩存數(shù)據(jù)虛引用:唯一目的跟蹤垃圾回收過程終結(jié)引用

③ . 垃圾回收器

串行(Serial) 并行(Parallel) ? Serial GC(串行回收):新生代 復(fù)制算法 STW 老年代使用 Serial Old GC 這種串行方法已過時(shí)

ParNew GC(并行回收):新生代 復(fù)制算法,多核場景運(yùn)行好 老年代使用 Serial Old GC

Parallel(并行):JDK8默認(rèn),新生代多線程 復(fù)制算法,老年代Parallel Old標(biāo)記壓縮,自適應(yīng)調(diào)節(jié)策略,目的是達(dá)到可控制的吞吐量伊甸園區(qū) servivor區(qū) 比例6:1:1

CMSGC:標(biāo)記清除算法!減少STW時(shí)間,有碎片,但低延遲

G1:兼具并行和并發(fā),具有分代收集的特點(diǎn)

3. 問題

問題一:什么是GC?

什么是G(垃圾)?

An object is considerd garbage when it can no longer be reached from any pointer in the running program.(沒有任何指針指向)

為什么需要GC?

沒有GC,內(nèi)存不夠用OOM,不能保證應(yīng)用程序正常運(yùn)行

full GC STW時(shí)間太長,影響用戶體驗(yàn)

問題二:垃圾回收的區(qū)域是什么?(堆和方法區(qū))

頻繁回收新生代較少回收老年代基本不動(dòng)原空間

可有可無的緩存數(shù)據(jù)

虛引用:唯一目的跟蹤垃圾回收過程終結(jié)引用

③ . 垃圾回收器

串行(Serial)

并行(Parallel)

Serial GC(串行回收):新生代 復(fù)制算法 STW 老年代使用 Serial Old GC 這種串行方法已過時(shí)

ParNew GC(并行回收):新生代 復(fù)制算法,多核場景運(yùn)行好 老年代使用 Serial Old GC

Parallel(并行):JDK8默認(rèn),新生代多線程 復(fù)制算法,老年代Parallel Old標(biāo)記壓縮,自適應(yīng)調(diào)節(jié)策略,目的是達(dá)到可控制的吞吐量伊甸園區(qū) servivor區(qū) 比例6:1:1

CMSGC:標(biāo)記清除算法!減少STW時(shí)間,有碎片,但低延遲

G1:兼具并行和并發(fā),具有分代收集的特點(diǎn)

3. 問題

問題一:什么是GC?

什么是G(垃圾)?

An object is considerd garbage when it can no longer be reached from any pointer in the running program.(沒有任何指針指向)

為什么需要GC?

沒有GC,內(nèi)存不夠用OOM,不能保證應(yīng)用程序正常運(yùn)行

full GC STW時(shí)間太長,影響用戶體驗(yàn)

問題二:垃圾回收的區(qū)域是什么?(堆和方法區(qū))

頻繁回收新生代較少回收老年代基本不動(dòng)原空間

柚子快報(bào)激活碼778899分享:JVM雨小結(jié)

http://yzkb.51969.com/

精彩內(nèi)容

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19040092.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄