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

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:java JVM

柚子快報(bào)邀請(qǐng)碼778899分享:java JVM

http://yzkb.51969.com/

JVM的組成

Java虛擬機(jī)(JVM)是執(zhí)行Java字節(jié)碼的運(yùn)行時(shí)環(huán)境。它由以下幾個(gè)主要部分組成:

1. **類加載器(ClassLoader)**: ? ?- 負(fù)責(zé)加載Java類的字節(jié)碼到JVM中,并進(jìn)行鏈接和初始化。

關(guān)于Java的類加載器,以下是一些關(guān)鍵點(diǎn),它們對(duì)于理解Java類如何被加載、鏈接和初始化非常重要:

1. **類加載過(guò)程**:

- Java的類加載過(guò)程包括三個(gè)主要步驟:加載(Loading)、鏈接(Linking)、初始化(Initialization)。

2. **加載**:

- 加載是類加載器讀取類文件的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)換為方法區(qū)中的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)的過(guò)程。

3. **鏈接**:

- 鏈接包括驗(yàn)證(Verification)、準(zhǔn)備(Preparation)和解析(Resolution)三個(gè)子階段。驗(yàn)證確保加載的類信息符合JVM規(guī)范;準(zhǔn)備負(fù)責(zé)為靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)初始值;解析將符號(hào)引用轉(zhuǎn)換為直接引用。

4. **初始化**:

- 初始化是為靜態(tài)變量賦予正確的初始值,并執(zhí)行靜態(tài)代碼塊的過(guò)程。

5. **類加載器類型**:

- Java提供了多種類型的類加載器:

- **啟動(dòng)類加載器(Bootstrap ClassLoader)**:負(fù)責(zé)加載Java核心庫(kù),如`rt.jar`。

加載lib目錄下的類庫(kù)

- **擴(kuò)展類加載器(Extension ClassLoader)**:負(fù)責(zé)加載擴(kuò)展目錄中的類庫(kù)。

加載ext目錄下的類庫(kù)

- **系統(tǒng)類加載器(System ClassLoader)**:負(fù)責(zé)加載應(yīng)用程序類路徑(`-classpath`參數(shù))上的類。

也稱為應(yīng)用類加載器,負(fù)責(zé)加載用戶類路徑(-classpath參數(shù)或系統(tǒng)屬性java.class.path)上指定的類庫(kù)。

- **自定義類加載器(User-Defined ClassLoader)**:應(yīng)用程序可以自定義類加載器來(lái)控制類的加載過(guò)程。

6. **雙親委派模型(Parent Delegation Model)**:

- 類加載器使用雙親委派模型來(lái)查找類。當(dāng)一個(gè)類請(qǐng)求被加載時(shí),它會(huì)首先委托給它的父類加載器去嘗試加載這個(gè)類,只有當(dāng)父類加載器無(wú)法完成這個(gè)請(qǐng)求時(shí),子類加載器才會(huì)嘗試自己去加載。

7. **類的唯一性**:

- 在同一個(gè)Java虛擬機(jī)中,任何一個(gè)類只有一個(gè)實(shí)例,即使由不同的類加載器加載也是如此。

8. **類加載器的層次結(jié)構(gòu)**:

- 類加載器形成了一個(gè)層次結(jié)構(gòu),通常從啟動(dòng)類加載器到系統(tǒng)類加載器,再到自定義類加載器。

9. **安全性**:

- 類加載器確保來(lái)自不同源的類是隔離的,例如,從網(wǎng)絡(luò)上加載的類不會(huì)影響系統(tǒng)類加載器加載的類。

10. **資源優(yōu)化**:

- 類加載器允許應(yīng)用程序在運(yùn)行時(shí)動(dòng)態(tài)地加載和卸載類,這有助于資源管理和優(yōu)化。

11. **類卸載**:

- 在某些情況下,如類不再被使用,JVM可以卸載這些類以釋放內(nèi)存。

12. **類加載器的實(shí)現(xiàn)**:

- Java允許開(kāi)發(fā)者通過(guò)繼承`java.lang.ClassLoader`類來(lái)實(shí)現(xiàn)自定義的類加載器。

了解類加載器的工作原理對(duì)于Java開(kāi)發(fā)者來(lái)說(shuō)非常重要,特別是在需要?jiǎng)討B(tài)加載類、隔離類版本、擴(kuò)展應(yīng)用程序功能或處理不同類路徑場(chǎng)景時(shí)。

2. **運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Areas)**: ? ?- 包括以下幾個(gè)部分: ? ? ?- **堆(Heap)**:存儲(chǔ)所有Java對(duì)象實(shí)例和數(shù)組。 ? ? ?- **方法區(qū)(Method Area)**:存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量等。在Java 8之前,這部分被稱為永久代(Permanent Generation,PermGen)。 ? ? ?- **棧(Stack)**:每個(gè)線程都有自己的棧,用于存儲(chǔ)局部變量和方法調(diào)用信息。 ? ? ?- **程序計(jì)數(shù)器(Program Counter)**:每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,用于跟蹤當(dāng)前執(zhí)行的字節(jié)碼指令。 ? ? ?- **本地方法棧(Native Method Stack)**:用于存儲(chǔ)本地方法(如JNI調(diào)用)的調(diào)用信息。

3. **執(zhí)行引擎(Execution Engine)**: ? ?- 負(fù)責(zé)解釋執(zhí)行字節(jié)碼或通過(guò)即時(shí)編譯器(JIT)將字節(jié)碼編譯為本地機(jī)器代碼后執(zhí)行。

4. **垃圾回收器(Garbage Collector, GC)**: ? ?- 負(fù)責(zé)自動(dòng)回收不再使用的對(duì)象,以管理堆內(nèi)存。

5. **本地接口(Native Interface)**: ? ?- 允許Java代碼調(diào)用和使用本地應(yīng)用程序編程接口(API),例如JNI(Java Native Interface)。

6. **即時(shí)編譯器(Just-In-Time Compiler, JIT)**: ? ?- 將熱點(diǎn)代碼(經(jīng)常執(zhí)行的代碼)編譯為機(jī)器代碼,以提高執(zhí)行效率。

7. **內(nèi)存管理器(Memory Manager)**: ? ?- 負(fù)責(zé)管理JVM的內(nèi)存分配和回收。

8. **安全管理系統(tǒng)(Security Manager)**: ? ?- 控制對(duì)系統(tǒng)資源的訪問(wèn),確保代碼的安全性。

9. **線程調(diào)度器(Thread Scheduler)**: ? ?- 管理線程的創(chuàng)建、調(diào)度和執(zhí)行。

10. **編譯系統(tǒng)和解釋器(Compiler and Interpreter)**: ? ? - 解釋器負(fù)責(zé)直接執(zhí)行字節(jié)碼,而編譯系統(tǒng)負(fù)責(zé)將字節(jié)碼編譯為本地代碼。

11. **性能分析器(Profiler)**: ? ? - 用于監(jiān)控和分析JVM的性能。

這些組件共同工作,為Java應(yīng)用程序提供了一個(gè)穩(wěn)定、安全且高效的運(yùn)行環(huán)境。JVM的架構(gòu)設(shè)計(jì)允許它在不同的操作系統(tǒng)和硬件平臺(tái)上運(yùn)行,確保了Java語(yǔ)言的跨平臺(tái)特性。

JDK8 JVM內(nèi)存結(jié)構(gòu)

在 JDK 8 中,JVM 的內(nèi)存結(jié)構(gòu)主要包括以下幾個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)域:

1. **堆(Heap)**: ? ?- 堆是JVM中最大的一塊內(nèi)存區(qū)域,主要用于存儲(chǔ)對(duì)象實(shí)例和數(shù)組。 ? ?- 堆是垃圾回收器管理的主要區(qū)域,經(jīng)常發(fā)生垃圾回收操作。

JVM堆是Java虛擬機(jī)中用于存儲(chǔ)對(duì)象實(shí)例和數(shù)組的主要內(nèi)存區(qū)域。以下是JVM堆中存儲(chǔ)的一些主要內(nèi)容:

1. **對(duì)象實(shí)例**:

- 所有通過(guò)Java關(guān)鍵字`new`創(chuàng)建的對(duì)象實(shí)例都存儲(chǔ)在堆中。

2. **數(shù)組**:

- 所有的數(shù)組,無(wú)論其元素類型如何(原始類型或引用類型),都存儲(chǔ)在堆中。

3. **實(shí)例變量**:

- 對(duì)象的非靜態(tài)成員變量也存儲(chǔ)在堆中,與對(duì)象實(shí)例一起。

4. **匿名內(nèi)部類**:

- 匿名內(nèi)部類(即使沒(méi)有具體名稱的內(nèi)部類)的實(shí)例同樣存儲(chǔ)在堆中。

5. **反射對(duì)象**:

- 通過(guò)Java反射API創(chuàng)建的類對(duì)象也存儲(chǔ)在堆中。

6. **字符串常量**:

- 盡管字符串常量可能會(huì)存儲(chǔ)在字符串常量池中,但通過(guò)`new`操作符創(chuàng)建的字符串對(duì)象實(shí)例仍然存儲(chǔ)在堆中。

7. **封裝類對(duì)象**:

- 封裝類(如`Integer`、`Double`等)的實(shí)例存儲(chǔ)在堆中。

8. **枚舉實(shí)例**:

- 枚舉類型(`enum`)的實(shí)例也存儲(chǔ)在堆中。

9. **異常對(duì)象**:

- 當(dāng)拋出異常時(shí),異常對(duì)象的實(shí)例會(huì)存儲(chǔ)在堆中,直到異常被處理。

10. **軟引用、弱引用、虛引用**:

- 這些引用類型指向的對(duì)象也存儲(chǔ)在堆中,盡管它們可能在垃圾回收時(shí)被回收。

11. **動(dòng)態(tài)代理對(duì)象**:

- 使用Java動(dòng)態(tài)代理API創(chuàng)建的代理對(duì)象實(shí)例存儲(chǔ)在堆中。

12. **Java本地方法接口(JNI)對(duì)象**:

- 通過(guò)JNI創(chuàng)建的對(duì)象實(shí)例同樣存儲(chǔ)在堆中。

JVM堆是垃圾回收器管理的主要區(qū)域,因?yàn)榇蠖鄶?shù)對(duì)象都是短暫的,并在此處進(jìn)行分配和回收。堆內(nèi)存的大小可以通過(guò)JVM啟動(dòng)參數(shù)(如`-Xms`和`-Xmx`)進(jìn)行配置。了解堆中存儲(chǔ)的內(nèi)容有助于開(kāi)發(fā)者進(jìn)行內(nèi)存管理和性能優(yōu)化。

JVM堆中的內(nèi)存被劃分為不同的代,主要是為了更有效地進(jìn)行垃圾回收。主要分為以下兩個(gè)部分:

1. **新生代(Young Generation)**:

- 新生代是新創(chuàng)建的對(duì)象存儲(chǔ)的地方。

- 它通常占據(jù)堆內(nèi)存的較小部分,并且被進(jìn)一步劃分為三個(gè)區(qū)域:

- **Eden區(qū)**:大多數(shù)新對(duì)象首先被分配到Eden區(qū)。

- **Survivor區(qū)**:為了能夠回收內(nèi)存,經(jīng)過(guò)一次垃圾回收后仍然存活的對(duì)象會(huì)被復(fù)制到Survivor區(qū)。Survivor區(qū)有兩個(gè),通常被稱為S0和S1,它們交替使用。

- 新生代使用復(fù)制算法進(jìn)行垃圾回收,稱為Minor GC。這個(gè)過(guò)程涉及將存活的對(duì)象從Eden區(qū)和Survivor區(qū)復(fù)制到另一個(gè)Survivor區(qū),然后清理Eden區(qū)和當(dāng)前使用的Survivor區(qū)。

Eden區(qū)和S0和S1內(nèi)存劃分比例值是8:1:1

Eden區(qū)內(nèi)存滿了就會(huì)觸發(fā)Minor GC

2. **老年代(Old Generation或Tenured Generation)**:

- 老年代用于存儲(chǔ)在新生代中經(jīng)過(guò)多次垃圾回收后仍然存活的對(duì)象。

- 這些對(duì)象通常已經(jīng)存在較長(zhǎng)時(shí)間,并且被認(rèn)為不太可能在近期內(nèi)變得垃圾。

- 老年代占據(jù)堆內(nèi)存的較大部分,并使用不同的垃圾回收算法,如標(biāo)記-清除或標(biāo)記-清除-整理算法。

- 老年代的垃圾回收,稱為Major GC或Full GC(如果涉及到整個(gè)堆的回收),通常比新生代的回收要慢,并且可能造成應(yīng)用程序的停頓。

線上項(xiàng)目中一定要盡量避免老年代內(nèi)存占滿,老年代內(nèi)存滿了后就會(huì)觸發(fā)Full GC 會(huì)產(chǎn)生Stop the world,這個(gè)時(shí)候除了Full GC線程會(huì)繼續(xù)執(zhí)行,其他線程用戶線程都會(huì)暫停,等待Full GC線程執(zhí)行完,其他用戶線程才會(huì)繼續(xù)執(zhí)行。

**晉升(Promotion)**:

GC掃一次沒(méi)有清理,那么年齡就會(huì)+1,達(dá)到一定年齡(默認(rèn)是15【CMS GC 默認(rèn)是6歲】)了就會(huì)晉升到老年代。

對(duì)象在新生代中經(jīng)過(guò)多次垃圾回收后,會(huì)根據(jù)其年齡(由垃圾回收次數(shù)決定)被晉升到老年代。這個(gè)過(guò)程有助于減少老年代中的對(duì)象數(shù)量,因?yàn)橹挥心切╅L(zhǎng)期存活的對(duì)象才會(huì)被移動(dòng)到那里。

**分代收集策略**:

JVM的分代垃圾回收策略基于這樣一個(gè)觀察:大多數(shù)對(duì)象都是短暫存在的,而只有少數(shù)對(duì)象會(huì)長(zhǎng)期存活。通過(guò)在新生代和老年代使用不同的垃圾回收算法,JVM可以優(yōu)化內(nèi)存回收的效率和速度。

了解新生代和老年代的概念對(duì)于分析和優(yōu)化Java應(yīng)用程序的內(nèi)存使用和垃圾回收性能至關(guān)重要。

2. **方法區(qū)(Method Area)**: ? ?- 也稱為永久代(PermGen),但在JDK 8中已經(jīng)被元空間(Metaspace)所取代。 ? ?- 方法區(qū)用于存儲(chǔ)類信息、常量、靜態(tài)變量、方法字節(jié)碼等數(shù)據(jù)。

3. **棧(Stack)**: ? ?- 每個(gè)線程都有自己的虛擬機(jī)棧,用于存儲(chǔ)局部變量、方法參數(shù)、方法調(diào)用和返回值。方法開(kāi)始的時(shí)候會(huì)進(jìn)棧,方法執(zhí)行完成會(huì)出棧,相當(dāng)于清空了數(shù)據(jù),所以不用進(jìn)行GC操作。 ? ?- 棧幀(Stack Frame)是棧的基本單位,每個(gè)方法調(diào)用都會(huì)創(chuàng)建一個(gè)新的棧幀。

4. **程序計(jì)數(shù)器(Program Counter)**: ? ?- 每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,用于記錄當(dāng)前線程執(zhí)行的字節(jié)碼指令地址。

5. **本地方法棧(Native Method Stack)**: ? ?- 用于存儲(chǔ)本地方法(如JNI調(diào)用)的調(diào)用信息。

6. **元空間(Metaspace)**: ? ?- JDK 8中引入,用于替代JDK 7及以前版本的永久代。 ? ?- 元空間不位于虛擬機(jī)內(nèi)存中,而是使用本地內(nèi)存,用于存儲(chǔ)類的元數(shù)據(jù)信息。

7. **代碼緩存(Code Cache)**: ? ?- 用于存儲(chǔ)JIT編譯器編譯后的本地機(jī)器代碼,以提高性能。

8. **運(yùn)行時(shí)常量池(Runtime Constant Pool)**: ? ?- 屬于方法區(qū)的一部分,用于存儲(chǔ)類中的常量,如字符串字面量、數(shù)字常量等。

9. **直接內(nèi)存(Direct Memory)**: ? ?- 不是JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,但Java程序可以通過(guò)NIO操作直接內(nèi)存。

在 JDK 8 中,除了上述內(nèi)存區(qū)域,還引入了一些新的垃圾回收特性,如G1垃圾回收器的進(jìn)一步優(yōu)化,以及用于提高性能的JVM參數(shù)調(diào)整等。了解這些內(nèi)存結(jié)構(gòu)對(duì)于進(jìn)行JVM調(diào)優(yōu)和性能分析非常重要。

JVM調(diào)優(yōu)參數(shù)

JVM 提供了一系列參數(shù),可以通過(guò)命令行啟動(dòng)Java應(yīng)用程序時(shí)進(jìn)行調(diào)整。這些參數(shù)分為不同的類別,包括內(nèi)存設(shè)置、垃圾收集器配置、性能監(jiān)控和日志記錄等。以下是一些常見(jiàn)的JVM參數(shù):

### 1. 內(nèi)存管理參數(shù): - `-Xms`:設(shè)置JVM啟動(dòng)時(shí)的初始堆內(nèi)存大小。 - `-Xmx`:設(shè)置JVM可以使用的最大堆內(nèi)存大小。 - `-Xss`:設(shè)置每個(gè)線程的棧大小。 - `-XX:NewSize=`:設(shè)置新生代的初始大小。設(shè)置新生代(Young Generation)的初始大小,但請(qǐng)注意,設(shè)置新生代大小可能會(huì)間接影響到老年代的大小,因?yàn)檎麄€(gè)堆的大?。ㄓ?-Xmx 參數(shù)設(shè)置)是固定的。 - `-XX:MaxNewSize=`:設(shè)置新生代的最大大小。同樣,這會(huì)影響老年代可用的內(nèi)存。

-XX:OldSize=:直接設(shè)置老年代的初始內(nèi)存大小。

java -XX:MaxOldSize=4g -jar YourApplication.jar

-XX:MaxOldSize=:設(shè)置老年代的最大內(nèi)存大小。

-XX:NewRatio=:設(shè)置新生代與老年代的比率。例如,如果設(shè)置為3,意味著新生代占總堆大小的1/4,老年代占3/4。

-XX:SurvivorRatio=:設(shè)置新生代中Eden區(qū)與Survivor區(qū)的比例。這個(gè)比例會(huì)影響到每次Minor GC后存活對(duì)象晉升到老年代的速率。

-XX:InitiatingHeapOccupancyPercent=:設(shè)置觸發(fā)老年代垃圾回收的堆占用閾值。當(dāng)老年代的內(nèi)存占用達(dá)到這個(gè)百分比時(shí),會(huì)觸發(fā)Full GC。

- `-XX:PermSize=`(Java 8之前):設(shè)置永久代的初始大小。 - `-XX:MaxPermSize=`(Java 8之前):設(shè)置永久代的最大大小。 - `-XX:MetaspaceSize=`(Java 8及之后):設(shè)置元空間的初始大小。 - `-XX:MaxMetaspaceSize=`(Java 8及之后):設(shè)置元空間的最大大小。

### 2. 垃圾收集器參數(shù): - `-XX:+UseSerialGC`:使用串行垃圾收集器。 - `-XX:+UseParallelGC`:使用并行垃圾收集器。 - `-XX:+UseConcMarkSweepGC`:使用CMS垃圾收集器。 - `-XX:+UseG1GC`:使用G1垃圾收集器。 - `-XX:+UseZGC`(Java 11及之后):使用ZGC垃圾收集器(實(shí)驗(yàn)性)。 - `-XX:+UseShenandoahGC`:使用Shenandoah垃圾收集器(實(shí)驗(yàn)性)。

### 3. 性能監(jiān)控參數(shù): - `-XX:+PrintGC`:打印GC發(fā)生的情況。 - `-XX:+PrintGCDetails`:打印GC的詳細(xì)日志。 - `-XX:+PrintGCDateStamps`:在GC日志中添加時(shí)間戳。 - `-Xloggc:`:將GC日志輸出到指定文件。 - `-XX:+UseGCLogFileRotation`:?jiǎn)⒂肎C日志文件輪替。 - `-XX:NumberOfGCLogFiles=`:指定GC日志文件的數(shù)量。 - `-XX:GCLogFileSize=`:指定GC日志文件的大小。

### 4. JIT編譯器參數(shù): - `-XX:+PrintCompilation`:打印JIT編譯方法的信息。 - `-XX:+PrintInlining`:打印JIT編譯過(guò)程中的內(nèi)聯(lián)信息。

### 5. 線程參數(shù): - `-XX:ThreadStackSize=`:設(shè)置線程棧的大小。 - `-XX:+UseLargePages`(某些系統(tǒng)):使用大頁(yè)內(nèi)存,可以減少內(nèi)存占用和提升性能。

### 6. 其他參數(shù): - `-Djava.security.egd=file:/dev/./urandom`:設(shè)置隨機(jī)數(shù)生成器的熵源。 - `-XX:+HeapDumpOnOutOfMemoryError`:在發(fā)生OOM時(shí)生成堆轉(zhuǎn)儲(chǔ)。 - `-XX:HeapDumpPath=`:指定堆轉(zhuǎn)儲(chǔ)文件的路徑。

### 7. 實(shí)驗(yàn)性參數(shù)(可能在不同版本中有所不同): - `-XX:+UnlockExperimentalVMOptions`:解鎖實(shí)驗(yàn)性參數(shù)。 - `-XX:+UseContainerSupport`(Java 19及之后):?jiǎn)⒂脤?duì)容器化環(huán)境的支持。

這些參數(shù)可以根據(jù)應(yīng)用程序的具體需求和運(yùn)行環(huán)境進(jìn)行調(diào)整。建議在進(jìn)行調(diào)優(yōu)時(shí),結(jié)合實(shí)際的性能測(cè)試結(jié)果和監(jiān)控?cái)?shù)據(jù)來(lái)決定最合適的參數(shù)配置。

垃圾回收機(jī)制

判斷什么是垃圾

在Java中,判斷一個(gè)對(duì)象是否成為垃圾,即是否可被垃圾回收器(Garbage Collector,GC)回收,主要基于以下條件:

1. **無(wú)法到達(dá)性(Unreachability)**: ? ?對(duì)象沒(méi)有任何引用與之相連,即從GC Roots開(kāi)始無(wú)法到達(dá)該對(duì)象。

2. **GC Roots的起點(diǎn)**: ? ?GC Roots是垃圾收集器進(jìn)行可達(dá)性分析時(shí)的起始點(diǎn),包括: ? ?- 靜態(tài)字段(`static`字段)中的對(duì)象引用。 ? ?- 局部變量表(棧幀中的局部變量)中的對(duì)象引用。 ? ?- 活躍線程的引用,包括Java方法棧和本地方法棧。 ? ?- 同步鎖(`synchronized`關(guān)鍵字所創(chuàng)建的鎖)的對(duì)象。 ? ?- 被Java虛擬機(jī)引用的對(duì)象,如系統(tǒng)類加載器。

3. **可達(dá)性分析(Reachability Analysis)**: ? ?垃圾回收器會(huì)定期進(jìn)行可達(dá)性分析,從GC Roots開(kāi)始遍歷所有可達(dá)對(duì)象。所有不可達(dá)的對(duì)象被認(rèn)為是垃圾。

4. **finalize()方法**: ? ?如果對(duì)象沒(méi)有被引用,并且沒(méi)有被垃圾回收器回收,它可能會(huì)成為垃圾回收的候選對(duì)象。如果對(duì)象定義了`finalize()`方法,并且該方法還未被調(diào)用,垃圾回收器可能會(huì)調(diào)用這個(gè)方法。但自Java 9起,`finalize()`方法已被標(biāo)記為過(guò)時(shí),并推薦使用`Cleaner`類來(lái)實(shí)現(xiàn)類似功能。

5. **引用類型**: ? ?- **強(qiáng)引用(Strong References)**:普通的引用,如`Object obj = new Object();`。 ? ?- **軟引用(Soft References)**:`java.lang.ref.SoftReference`,當(dāng)內(nèi)存不足時(shí)會(huì)被回收。 ? ?- **弱引用(Weak References)**:`java.lang.ref.WeakReference`,一旦成為弱引用,就會(huì)被垃圾回收器回收。 ? ?- **虛引用(Phantom References)**:`java.lang.ref.PhantomReference`,無(wú)法通過(guò)虛引用訪問(wèn)對(duì)象,僅用于跟蹤對(duì)象被回收的狀態(tài)。

6. **回收時(shí)機(jī)**: ? ?即使對(duì)象已經(jīng)被視為垃圾,垃圾回收器也不一定會(huì)立即回收它們。回收時(shí)機(jī)取決于多種因素,如GC算法、堆內(nèi)存的使用情況等。

7. **回收過(guò)程**: ? ?對(duì)象被判定為垃圾后,GC會(huì)在合適的時(shí)機(jī)進(jìn)行回收。在回收過(guò)程中,對(duì)象占用的內(nèi)存會(huì)被釋放。

開(kāi)發(fā)者可以通過(guò)以下方式幫助JVM管理內(nèi)存: - 及時(shí)釋放不再使用的引用,如將對(duì)象設(shè)置為`null`。 - 使用適當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)和算法,減少內(nèi)存占用。 - 避免內(nèi)存泄漏,如避免循環(huán)引用或確保及時(shí)關(guān)閉資源。

記住,Java的垃圾回收是自動(dòng)的,但開(kāi)發(fā)者可以通過(guò)編寫良好的代碼來(lái)輔助JVM更高效地進(jìn)行內(nèi)存管理。 ?

垃圾回收算法

標(biāo)記-清除(Mark-Sweep):

首先標(biāo)記所有需要回收的對(duì)象。 清除所有被標(biāo)記的對(duì)象,釋放內(nèi)存。 缺點(diǎn)是會(huì)產(chǎn)生內(nèi)存碎片,并且標(biāo)記和清除過(guò)程可能較慢。

復(fù)制(Copying): 將內(nèi)存分為兩個(gè)相等的區(qū)域,每次只使用一個(gè)區(qū)域。 當(dāng)一個(gè)區(qū)域滿了,將存活的對(duì)象復(fù)制到另一個(gè)區(qū)域,并清空當(dāng)前區(qū)域。 優(yōu)點(diǎn)是解決了內(nèi)存碎片問(wèn)題,缺點(diǎn)是空間利用率降低。

標(biāo)記-整理(Mark-Compact): 先進(jìn)行標(biāo)記階段,找出存活對(duì)象。 然后將存活對(duì)象向內(nèi)存的一端移動(dòng),并清空剩余區(qū)域。 優(yōu)點(diǎn)是解決了內(nèi)存碎片問(wèn)題,缺點(diǎn)是移動(dòng)對(duì)象可能較耗時(shí)。

增量回收(Incremental or Generational GC): 將堆分為不同的代(通常是新生代和老年代),并假設(shè)大部分對(duì)象都是短暫存活的。 新生代使用復(fù)制算法,老年代使用標(biāo)記-清除或標(biāo)記-整理算法。 增量回收嘗試減少單次GC的停頓時(shí)間。

分代收集(Generational Collection): 基于增量回收的概念,進(jìn)一步優(yōu)化,將對(duì)象分配到不同代。 新生代對(duì)象存活率低,使用復(fù)制算法;老年代對(duì)象存活率高,使用標(biāo)記-清除或標(biāo)記-整理算法。

并發(fā)標(biāo)記-清除(Concurrent Mark-Sweep): 允許垃圾回收器的某些階段與應(yīng)用程序并發(fā)運(yùn)行,減少停頓時(shí)間。

G1(Garbage-First): 一種服務(wù)器端的垃圾回收算法,旨在提供可預(yù)測(cè)的停頓時(shí)間。 將堆分割成多個(gè)區(qū)域,并優(yōu)先回收那些包含大量垃圾的區(qū)域。

ZGC(Z Garbage Collector): 一種低延遲垃圾回收器,使用彩色標(biāo)記和并發(fā)處理。 它允許應(yīng)用程序在非常大的堆上運(yùn)行,同時(shí)保持低延遲。

Shenandoah: 一種與應(yīng)用程序并發(fā)運(yùn)行的垃圾回收器,幾乎沒(méi)有停頓。 它使用全局并發(fā)標(biāo)記和編譯器支持的引用處理。

Epsilon: 一種無(wú)操作垃圾回收器,不執(zhí)行任何垃圾回收,用于性能基準(zhǔn)測(cè)試。

垃圾回收器

在JDK 8中,主要的垃圾回收器(Garbage Collectors,GC)有以下幾種:

1. **Serial GC**:這是單線程的垃圾回收器,使用一個(gè)線程進(jìn)行垃圾回收,適合內(nèi)存資源受限的環(huán)境和小數(shù)據(jù)量的應(yīng)用場(chǎng)景。它在新生代使用復(fù)制算法,在老年代使用標(biāo)記-整理算法。

2. **ParNew GC**:ParNew是Serial GC的多線程版本,同樣在新生代使用復(fù)制算法,適用于多CPU環(huán)境。它是許多運(yùn)行在server模式下的虛擬機(jī)中首選的新生代收集器。

3. **Parallel Scavenge GC**:這個(gè)收集器是一個(gè)關(guān)注吞吐量的新生代收集器,使用復(fù)制算法。它提供了一些參數(shù),如 `-XX:MaxGCPauseMillis` 用于控制最大垃圾收集停頓時(shí)間,以及 `-XX:GCTimeRatio` 用于設(shè)置吞吐量大小。

它的目標(biāo)是達(dá)到一個(gè)可控的吞吐量(吞吐量=運(yùn)行用戶代碼的時(shí)間 /(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間)),例子:虛擬機(jī)一共運(yùn)行了100分鐘,垃圾收集器用了1分鐘,用戶代碼運(yùn)行時(shí)間99分鐘,那么吞吐量就是99%。

4. **Parallel Old GC**:這是Parallel Scavenge收集器的老年代版本,使用多線程和標(biāo)記-整理算法。它適用于注重吞吐量和CPU資源的場(chǎng)合。

5. **CMS (Concurrent Mark Sweep) GC**:CMS是一種以最小化GC停頓時(shí)間為目標(biāo)的收集器,采用標(biāo)記-清除算法。它的垃圾收集過(guò)程分為四個(gè)步驟:初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記和并發(fā)清除。CMS在JDK 9中被標(biāo)記為過(guò)時(shí),并在JDK 14中被移除。

6. **G1 (Garbage-First) GC**:G1是一種服務(wù)器端的垃圾回收器,旨在提供可預(yù)測(cè)的停頓時(shí)間,同時(shí)保持高吞吐量。它將堆內(nèi)存分割成多個(gè)區(qū)域,并優(yōu)先回收那些包含大量垃圾的區(qū)域。G1在JDK 9之后成為默認(rèn)的垃圾回收器。

7. **ZGC (Z Garbage Collector)**:雖然ZGC是在JDK 11中引入的,但它是一種低延遲的垃圾回收器,能夠在保持高吞吐量的同時(shí),將停頓時(shí)間控制在毫秒級(jí)別。ZGC支持最大16TB的堆內(nèi)存,適合需要極低延遲和大堆內(nèi)存的應(yīng)用場(chǎng)景。

JDK 8的默認(rèn)垃圾回收器組合是Parallel Scavenge GC用于新生代,Parallel Old GC用于老年代。開(kāi)發(fā)者可以根據(jù)應(yīng)用的具體需求和JVM的性能特性來(lái)選擇合適的垃圾回收器。 ?

Java 垃圾收集器(Garbage Collector,GC)日志分析工具

Universal JVM GC analyzer - Java Garbage collection log analysis made easy

GC Easy 是一款在線的 Java 垃圾回收日志分析工具,它通過(guò)機(jī)器學(xué)習(xí)技術(shù)輔助用戶快速理解 GC 日志,定位內(nèi)存泄漏和優(yōu)化垃圾回收性能。使用 GC Easy 非常簡(jiǎn)單,用戶只需上傳 GC 日志文件,GC Easy 就會(huì)自動(dòng)解析日志并生成包含多種圖表和詳細(xì)指標(biāo)的分析報(bào)告,幫助用戶直觀地了解應(yīng)用程序的內(nèi)存使用情況和垃圾回收性能 。

打印GC日志

打印GC(Garbage Collection,垃圾回收)日志是監(jiān)控和調(diào)優(yōu)Java應(yīng)用程序性能的重要手段。以下是一些常用的JVM參數(shù),用于控制GC日志的打?。?/p>

1. **`-Xlog:gc*`**: ? ?這個(gè)參數(shù)會(huì)打印GC日志,`*`可以替換為更具體的日志選項(xiàng),例如`-Xlog:gc`只打印GC日志,而`-Xlog:gc+heap=info`會(huì)打印GC和堆信息。

2. **`-XX:+PrintGC`**: ? ?啟用這個(gè)參數(shù)會(huì)打印每次GC事件的簡(jiǎn)要信息。

3. **`-XX:+PrintGCDetails`**: ? ?如果需要更詳細(xì)的GC日志,可以使用此參數(shù),它會(huì)打印GC的詳細(xì)日志,包括GC的類型、花費(fèi)的時(shí)間、回收了多少內(nèi)存等。

4. **`-XX:+PrintGCTimeStamps`**: ? ?這個(gè)參數(shù)會(huì)讓GC日志包含時(shí)間戳,這對(duì)于分析GC事件的發(fā)生時(shí)間非常有用。

5. **`-XX:+PrintGCDateStamps`**: ? ?與`-XX:+PrintGCTimeStamps`類似,但這個(gè)參數(shù)會(huì)打印日期和時(shí)間戳。

6. **`-Xloggc:`**: ? ?通過(guò)這個(gè)參數(shù)可以指定GC日志輸出到文件而不是控制臺(tái)。

7. **`-XX:+UseGCLogFileRotation`**: ? ?啟用日志文件輪轉(zhuǎn),防止日志文件無(wú)限增長(zhǎng)。

8. **`-XX:NumberOfGCLogFiles=`**: ? ?設(shè)置輪轉(zhuǎn)的日志文件數(shù)量。

9. **`-XX:GCLogFileSize=`**: ? ?設(shè)置每個(gè)GC日志文件的最大大小。

10. **`-XX:HeapDumpPath=`**: ? ? 設(shè)置在發(fā)生OOM(Out of Memory)時(shí)Heap Dump文件的路徑。

11. **`-XX:+HeapDumpOnOutOfMemoryError`**: ? ? 在發(fā)生OOM時(shí)自動(dòng)生成Heap Dump。

以下是一個(gè)示例,展示如何使用這些參數(shù)啟動(dòng)Java應(yīng)用程序:

```sh java -Xmx1024m -Xms512m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/path/to/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/heapdump.hprof YourApplication.jar ```

在這個(gè)示例中,我們?cè)O(shè)置了堆的最大和初始大小,啟用了詳細(xì)GC日志和時(shí)間戳,并將GC日志輸出到指定的文件。同時(shí),如果發(fā)生OOM錯(cuò)誤,會(huì)自動(dòng)在指定路徑生成Heap Dump文件。

請(qǐng)注意,這些參數(shù)可能會(huì)根據(jù)JDK的版本和實(shí)現(xiàn)有所不同,建議查閱具體版本的官方文檔以獲取最準(zhǔn)確的信息。 ?

演示案例

代碼

public class TestGC {

public static void main(String[] args) throws InterruptedException {

final int STRING_COUNT = 100000; // 要生成的字符串?dāng)?shù)量

List arr = new ArrayList<>();

for (int i = 0; i < STRING_COUNT; i++) {

String replace = UUID.randomUUID().toString().replace("-", "");

System.out.println(replace);

arr.add(replace);

replace = null;

}

arr.clear();

System.gc();

Thread.sleep(5000);

}

}

設(shè)置jvm參數(shù)

-Xmx128m -Xms128m -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

在Universal JVM GC analyzer - Java Garbage collection log analysis made easy?上傳你的gc日志

然后分析

你會(huì)發(fā)現(xiàn)新生代內(nèi)存空間占分配的128m棧內(nèi)存的三分之一左右,老年代占三分之2左右。

通過(guò)下面這張圖:

新生代內(nèi)存滿了之后,JVM會(huì)觸發(fā)Minor GC(也稱為Young GC),在這次垃圾回收過(guò)程中,不再有存活價(jià)值的對(duì)象會(huì)被回收,而仍然存活的對(duì)象會(huì)根據(jù)其年齡(age)進(jìn)行處理。在HotSpot JVM中,對(duì)象在新生代中有一個(gè)年齡計(jì)數(shù)器,每次經(jīng)歷一次Minor GC后,如果對(duì)象仍然存活,其年齡計(jì)數(shù)器會(huì)增加。當(dāng)對(duì)象的年齡達(dá)到一定的閾值(可以通過(guò)-XX:MaxTenuringThreshold參數(shù)設(shè)置,默認(rèn)值通常是15),對(duì)象就會(huì)被晉升到老年代(Old Generation或Tenured Generation)。

晉升到老年代的對(duì)象會(huì)有更多的生存時(shí)間,JVM會(huì)認(rèn)為這些對(duì)象的生命周期較長(zhǎng),因此不需要在每次Minor GC時(shí)都進(jìn)行回收。老年代的垃圾回收(Major GC或Full GC)發(fā)生的頻率遠(yuǎn)低于新生代,這樣可以減少垃圾回收的開(kāi)銷。

總結(jié)來(lái)說(shuō),新生代內(nèi)存滿了會(huì)觸發(fā)Minor GC,在此過(guò)程中,滿足年齡條件的對(duì)象會(huì)被晉升到老年代,而未滿足條件的存活對(duì)象則仍然留在新生代中。這個(gè)過(guò)程有助于JVM更有效地管理內(nèi)存,減少垃圾回收的頻率和成本。

?下圖,平均GC執(zhí)行時(shí)間,和最大GC執(zhí)行時(shí)間

下圖,發(fā)現(xiàn)Full GC 觸發(fā)了一次,我們調(diào)優(yōu)就是為了盡量避免Full GC的觸發(fā),System.gc()很大可能會(huì)觸發(fā),我們上面代碼寫了System.gc(),所以Full GC了一次,如果你去掉System.gc()代碼,然后再分析日志,你會(huì)發(fā)現(xiàn)觸發(fā)次數(shù)是0了。下面是FullGC觸發(fā)了條件

Full GC(Full Garbage Collection)是JVM中的老年代垃圾回收,它是一種成本較高的垃圾回收操作,因?yàn)樗鼤?huì)回收整個(gè)堆內(nèi)存(包括新生代和老年代)。Full GC的觸發(fā)條件通常包括以下幾種情況:

1. **老年代空間不足**:當(dāng)老年代中沒(méi)有足夠的內(nèi)存空間去容納新生代晉升的對(duì)象時(shí),會(huì)觸發(fā)Full GC 。 2. **Metaspace區(qū)內(nèi)存達(dá)到閾值**:從JDK8開(kāi)始,永久代(PermGen)被廢棄,取而代之的是Metaspace。當(dāng)Metaspace區(qū)域的內(nèi)存使用達(dá)到一定閾值時(shí),會(huì)觸發(fā)Full GC 。 3. **統(tǒng)計(jì)得到的Minor GC晉升到老年代的平均大小大于老年代的剩余空間**:Hotspot為了避免新生代對(duì)象晉升到老年代導(dǎo)致空間不足,在進(jìn)行Minor GC時(shí)會(huì)做一個(gè)判斷,如果統(tǒng)計(jì)得到的晉升平均大小大于老年代剩余空間,則直接觸發(fā)Full GC 。 4. **堆中分配很大的對(duì)象**:當(dāng)創(chuàng)建一個(gè)很大的對(duì)象,且該對(duì)象需要的內(nèi)存空間大于老年代的剩余空間時(shí),會(huì)觸發(fā)Full GC 。 5. **CMS GC時(shí)出現(xiàn)promotion failed和concurrent mode failure**:在使用CMS垃圾收集器時(shí),如果出現(xiàn)晉升失敗或并發(fā)模式失敗,也會(huì)觸發(fā)Full GC 。 6. **顯式調(diào)用System.gc()**:雖然只是建議JVM進(jìn)行Full GC,但在大多數(shù)情況下會(huì)增加Full GC的次數(shù),導(dǎo)致系統(tǒng)性能下降 。

在進(jìn)行Full GC時(shí),JVM會(huì)嘗試清理整個(gè)堆內(nèi)存中的垃圾對(duì)象,這可能會(huì)導(dǎo)致應(yīng)用程序的線程暫停,從而影響性能。因此,理解并監(jiān)控Full GC的觸發(fā)條件和頻率對(duì)于優(yōu)化Java應(yīng)用程序的性能至關(guān)重要。開(kāi)發(fā)者可以通過(guò)監(jiān)控工具和調(diào)整JVM參數(shù)來(lái)優(yōu)化垃圾回收過(guò)程,例如設(shè)置堆的最大大小、新生代與老年代的比例、使用合適的垃圾回收器等 。 ?

JVM調(diào)優(yōu)總結(jié)

?

JVM調(diào)優(yōu)是一個(gè)綜合性的過(guò)程,涉及到多個(gè)方面的參數(shù)調(diào)整,主要包括內(nèi)存設(shè)置、垃圾收集器選擇、性能監(jiān)控等。以下是一些常見(jiàn)的JVM調(diào)優(yōu)參數(shù)和策略:

1. **堆內(nèi)存設(shè)置**:使用 `-Xms` 和 `-Xmx` 參數(shù)來(lái)設(shè)置JVM堆的初始大小和最大大小,這有助于優(yōu)化內(nèi)存使用并減少動(dòng)態(tài)調(diào)整的開(kāi)銷。

2. **垃圾收集器選擇**:根據(jù)應(yīng)用的特點(diǎn)和需求,選擇合適的垃圾收集器。例如,`-XX:+UseG1GC` 用于選擇G1垃圾收集器,它適合于大堆內(nèi)存和多核處理器的場(chǎng)景,可以提供平衡的吞吐量和較低的延遲。

3. **性能監(jiān)控**:?jiǎn)⒂?`-XX:+PrintGCDetails` 參數(shù)打印詳細(xì)的GC日志,這有助于監(jiān)控垃圾收集的性能和優(yōu)化垃圾收集策略。

4. **元空間(Metaspace)**:設(shè)置 `-XX:MetaspaceSize` 和 `-XX:MaxMetaspaceSize` 參數(shù)來(lái)控制元空間的大小,避免因元空間無(wú)限增長(zhǎng)導(dǎo)致的問(wèn)題。

5. **日志和監(jiān)控**:使用 `-Xloggc` 將GC日志寫入指定文件,并使用 `-XX:+UseGCLogFileRotation` 開(kāi)啟GC日志文件的輪替,以便于監(jiān)控和分析。

6. **JVM性能調(diào)優(yōu)**:使用 `-XX:+UseStringDeduplication` 開(kāi)啟字符串去重功能,減少堆內(nèi)存的占用;使用 `-XX:+DisableExplicitGC` 禁用System.gc()的顯式調(diào)用,避免可能的性能問(wèn)題。

7. **同步優(yōu)化**:在多線程應(yīng)用中,合理使用同步機(jī)制,避免因過(guò)度同步導(dǎo)致的性能損耗。

8. **JIT編譯器優(yōu)化**:JIT編譯器是JVM性能優(yōu)化的重要手段,通過(guò)調(diào)整JIT編譯器的參數(shù)和關(guān)閉不必要的優(yōu)化,提高程序的執(zhí)行效率。

9. **內(nèi)存分析工具**:使用內(nèi)存分析工具,如VisualVM和MAT,幫助定位內(nèi)存泄漏問(wèn)題并解決。

10. **監(jiān)控工具**:使用jstat、jvisualvm、jconsole等JVM監(jiān)控工具,監(jiān)控和分析Java應(yīng)用的性能。

需要注意的是,JVM調(diào)優(yōu)應(yīng)根據(jù)應(yīng)用程序的具體需求和運(yùn)行情況進(jìn)行,逐步調(diào)整并觀察每次調(diào)整的效果。此外,JVM調(diào)優(yōu)是一個(gè)持續(xù)的過(guò)程,需要根據(jù)應(yīng)用的運(yùn)行情況不斷進(jìn)行優(yōu)化和調(diào)整。 ?

柚子快報(bào)邀請(qǐng)碼778899分享:java JVM

http://yzkb.51969.com/

相關(guān)閱讀

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

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

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

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

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

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

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

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

文章目錄