97色伦色在线综合视频,无玛专区,18videosex性欧美黑色,日韩黄色电影免费在线观看,国产精品伦理一区二区三区,在线视频欧美日韩,亚洲欧美在线中文字幕不卡

商城網站建設效果臨淄網站制作價格低

鶴壁市浩天電氣有限公司 2026/01/22 06:46:06
商城網站建設效果,臨淄網站制作價格低,豫建設標文件在哪個網站公布,建網站要大約多少錢內存分代回收的‘晉升’細節(jié)#xff1a;對象在 Scavenger 空間存活多久才會進入老年代 各位技術同仁#xff0c;大家好。今天我們將深入探討Java虛擬機#xff08;JVM#xff09;中一個至關重要的內存管理機制——分代垃圾回收#xff08;Generational Garbage Collectio…內存分代回收的‘晉升’細節(jié)對象在 Scavenger 空間存活多久才會進入老年代各位技術同仁大家好。今天我們將深入探討Java虛擬機JVM中一個至關重要的內存管理機制——分代垃圾回收Generational Garbage Collection尤其是其中“對象晉升”Promotion到老年代的細節(jié)。理解這一機制對于我們進行JVM性能調優(yōu)、排查內存問題具有不可替代的價值。引言內存管理的挑戰(zhàn)與分代回收的誕生在軟件開發(fā)中內存管理一直是核心且復雜的任務。早期的程序需要開發(fā)者手動分配和釋放內存這不僅效率低下而且極易引入內存泄漏、野指針等問題導致程序崩潰或行為異常。自動垃圾回收Garbage Collection, GC機制的出現(xiàn)極大地解放了程序員使得他們能更專注于業(yè)務邏輯的實現(xiàn)。然而簡單的“標記-清除”或“標記-整理”算法在面對大型、高并發(fā)應用時會帶來明顯的性能瓶頸尤其是“Stop-The-World”STW的暫停時間可能導致用戶體驗下降。為了解決這一問題研究者們提出了“分代回收”的概念。分代回收基于一個重要的經驗性假說——“弱代假說”Weak Generational Hypothesis。它包含兩個子假說大部分對象朝生夕滅Most Objects Die Young絕大多數(shù)對象在被創(chuàng)建后很快就會變得不可達。熬過越多次垃圾回收過程的對象就越可能存活The Longer an Object Lives, The More Likely it is to Live Longer少數(shù)能夠熬過多次GC過程的對象往往生命周期較長?;谶@兩個假說分代回收將堆內存劃分為不同的區(qū)域通常是“年輕代”Young Generation和“老年代”O(jiān)ld Generation并對不同區(qū)域采用最適合其對象生命周期的GC算法從而提高垃圾回收的效率減少STW時間。JVM堆內存結構年輕代、老年代與GC基礎在HotSpot JVM中Java堆Heap是管理Java對象的主要內存區(qū)域也是垃圾回收器主要工作的地方。堆通常被邏輯劃分為以下幾個主要部分年輕代Young Generation / Eden Space用于存放新創(chuàng)建的對象。根據(jù)“朝生夕滅”的假說年輕代中的對象生命周期短因此這里會頻繁地進行垃圾回收稱為“Minor GC”或“Young GC”或“Scavenge GC”。年輕代又進一步細分為一個Eden空間和兩個Survivor空間S0和S1也常稱作From和To。Eden空間絕大多數(shù)新對象首先在這里分配內存。Survivor空間用于存放那些在Minor GC中幸存下來的對象。兩個Survivor空間在任意時刻只有一個是空的用作Minor GC的“To”空間另一個則用作“From”空間。老年代Old Generation / Tenured Generation用于存放那些在年輕代中多次垃圾回收后依然存活的對象或者一些本身就很大的對象。老年代中的對象生命周期較長因此這里的GC頻率較低但回收的范圍更大通常會包含年輕代這種GC被稱為“Full GC”或“Major GC”。Full GC的STW時間通常比Minor GC長得多。元空間MetaspaceJDK 8/ 方法區(qū)Method AreaJDK 7及以前用于存儲類的元數(shù)據(jù)信息如類結構、運行時常量池、字段和方法數(shù)據(jù)等。它不屬于Java堆而是直接使用本地內存。垃圾回收主要針對常量池的回收和對類的卸載。其他內存區(qū)域如棧Stack、本地方法棧Native Method Stack、程序計數(shù)器Program Counter Register等這些區(qū)域的生命周期與線程或方法調用相關通常不涉及垃圾回收。GC Roots垃圾回收器判斷對象是否存活依賴于“可達性分析算法”。這個算法從一系列被稱為“GC Roots”的根對象開始遍歷所有可達的對象。如果一個對象無法從任何GC Roots到達那么它就是不可達的可以被回收。GC Roots通常包括虛擬機棧棧幀中的本地變量表中引用的對象、本地方法棧中引用的對象、方法區(qū)中靜態(tài)屬性引用的對象、方法區(qū)中常量引用的對象等。年輕代垃圾回收Minor GC的運行機制理解年輕代的回收過程是理解對象晉升的基礎。當新對象在Eden區(qū)分配內存如果Eden區(qū)空間不足就會觸發(fā)一次Minor GC。Minor GC的詳細步驟如下暫停應用線程STW為了確保對象圖的穩(wěn)定性JVM會暫停所有應用線程。標記存活對象從GC Roots開始遍歷年輕代中的所有對象標記出所有可達即存活的對象。復制存活對象將Eden區(qū)和當前“From”Survivor空間假設是S0中所有存活的對象復制到另一個空的“To”Survivor空間假設是S1。在復制過程中如果對象已經經歷過一次Minor GC其年齡tenuring age會增加1。如果對象的年齡達到了晉升閾值或者S1空間不足這些對象就會被直接復制到老年代。如果S1空間也無法容納所有存活對象那么一部分對象會直接晉升到老年代。清空Eden和From空間復制完成后Eden區(qū)和S0空間中的所有對象包括已死亡和已復制走的都被視為垃圾直接清空。交換Survivor空間角色S0和S1的角色互換。原S1現(xiàn)在成為“From”空間原S0成為“To”空間。恢復應用線程GC完成后恢復所有應用線程的執(zhí)行。這個過程被稱為“復制算法”其優(yōu)點是效率高且不會產生內存碎片。但缺點是需要一塊額外的空間作為“To”空間。為了更好地理解這個過程我們來看一個簡化的偽代碼流程// 假設這是JVM內部的Minor GC邏輯 public void performMinorGC() { // 1. 暫停應用線程 stopTheWorld(); // 2. 標記階段簡化表示 SetObject liveObjects markLiveObjects(GC_ROOTS, YoungGeneration); // 3. 復制階段 for (Object obj : liveObjects) { if (obj.isInEden() || obj.isInSurvivorFrom()) { // 檢查對象年齡和Survivor空間容量 if (obj.getAge() MaxTenuringThreshold || SurvivorToSpace.isAlmostFull() || obj.isLargeObject()) { // 大對象可能直接晉升 // 晉升到老年代 OldGeneration.allocate(obj); obj.moveToOldGeneration(); } else { // 復制到Survivor To空間并增加年齡 SurvivorToSpace.allocate(obj); obj.moveToSurvivorToSpace(); obj.incrementAge(); } } } // 4. 清空Eden和From空間 EdenSpace.clear(); SurvivorFromSpace.clear(); // 5. 交換Survivor空間角色 swapSurvivorSpaces(); // 6. 恢復應用線程 resumeApplicationThreads(); }對象晉升Promotion的核心策略年齡閾值對象晉升是指對象從年輕代通常是Survivor空間移動到老年代的過程。這是分代回收中的一個關鍵環(huán)節(jié)。對象晉升的決定因素主要有兩個對象的年齡Age和Survivor空間的使用情況以及對象的大小。硬性年齡閾值MaxTenuringThreshold每個對象在JVM內部都有一個年齡計數(shù)器。這個計數(shù)器存儲在對象頭Object Header的Mark Word中。HotSpot JVM的Mark Word是一個多用途的字用于存儲對象的哈希碼、GC信息如分代年齡、鎖信息等。在32位JVM上Mark Word通常占用4字節(jié)在64位JVM上通常占用8字節(jié)。其中對象的年齡通常用4位二進制數(shù)表示因此最大年齡為150-15。當一個對象在Eden區(qū)被創(chuàng)建時其年齡為0。每當它在Minor GC中幸存下來并被復制到Survivor空間時其年齡就會加1。當對象的年齡達到一個預設的閾值時它就會被晉升到老年代。這個閾值由JVM參數(shù)MaxTenuringThreshold控制。MaxTenuringThreshold的默認值不同GC算法和JVM版本MaxTenuringThreshold的默認值可能有所不同。JVM參數(shù)默認值描述MaxTenuringThreshold15Serial / Parallel / CMS GC的默認值MaxTenuringThreshold6G1 GC的默認值 (JDK 8 HotSpot)這個差異反映了不同GC算法對內存分配和回收策略的不同側重。例如G1收集器更加注重低延遲其Region劃分和回收機制使得它可能更傾向于讓對象更早地晉升到老年代避免在年輕代Region之間頻繁復制。示例如果MaxTenuringThreshold設置為15一個對象在Minor GC中幸存了15次那么在第15次Minor GC后它就會被晉升到老年代。動態(tài)年齡判斷HotSpot JVM的智能抉擇僅僅依靠一個固定的MaxTenuringThreshold可能無法完美適應所有應用場景。例如如果Survivor空間很大但大部分對象在幾次GC后就死亡了那么將MaxTenuringThreshold設置為15會導致Survivor空間長時間被少量存活對象占據(jù)造成空間浪費。反之如果Survivor空間很小但對象生命周期較長固定的高閾值可能導致Survivor空間頻繁溢出進而提前晉升增加老年代壓力。為了解決這個問題HotSpot JVM引入了“動態(tài)年齡判斷”機制。JVM并不是簡單地等到對象的年齡達到MaxTenuringThreshold才將其晉升。它會根據(jù)Minor GC后Survivor空間的使用情況動態(tài)地調整晉升閾值。動態(tài)年齡判斷的原理JVM會統(tǒng)計當前Minor GC后Survivor To空間中所有年齡段1到MaxTenuringThreshold對象的總大小。它會找到一個最小的年齡k使得從年齡1到年齡k的所有對象大小之和超過了Survivor To空間容量的TargetSurvivorRatio默認是50%。那么所有年齡大于等于k的對象就會被晉升到老年代而年齡小于k的對象則繼續(xù)留在Survivor空間。這個機制旨在充分利用Survivor空間當Survivor空間有足夠容量時可以容納更多存活時間稍長的對象避免它們過早進入老年代。避免Survivor空間溢出當Survivor空間面臨壓力時可以適當降低晉升閾值將部分對象提前送入老年代以騰出Survivor空間避免因Survivor空間不足導致更多的對象直接晉升到老年代這通常伴隨更長的STW時間。動態(tài)計算過程詳解假設Survivor To空間的總容量為S_capacityTargetSurvivorRatio為R例如0.5。在Minor GC結束后JVM會遍歷Survivor To空間中所有存活對象的年齡分布。它會從年齡age1開始累加對象大小sum_size。當累加到某個年齡k時如果sum_size首次超過S_capacity * R那么所有年齡大于或等于k的對象以及年齡大于等于MaxTenuringThreshold的對象都會被晉升到老年代。新的實際晉升閾值就是k。如果遍歷完所有年齡sum_size都沒有超過S_capacity * R則實際晉升閾值仍為MaxTenuringThreshold。示例表格動態(tài)年齡判斷假設Survivor To空間容量為 100MBTargetSurvivorRatio為 50% (0.5)即目標使用量為 50MB。MaxTenuringThreshold為 15。對象年齡該年齡段對象大小 (MB)累積大小 (MB)是否超過50MB動態(tài)晉升閾值實際晉升行為11010否–留在Survivor21525否–留在Survivor32045否–留在Survivor41055是4晉升到老年代5560是4晉升到老年代………是4晉升到老年代15161是4晉升到老年代在這個例子中當累加到年齡為4的對象時總大小達到了55MB首次超過了50MB的目標。因此動態(tài)晉升閾值被設置為4。這意味著在這次Minor GC后所有年齡小于4的對象將繼續(xù)留在Survivor空間而年齡為4及以上的對象都將被晉升到老年代。這種動態(tài)調整的機制使得JVM能夠根據(jù)實際運行情況靈活地進行內存管理優(yōu)化GC性能。代碼演示與GC日志分析為了更直觀地理解對象晉升和動態(tài)年齡判斷我們通過一個Java程序來觀察GC日志。import java.util.ArrayList; import java.util.List; public class TenuringThresholdDemo { private static final int _1MB 1024 * 1024; // 1MB public static void main(String[] args) throws InterruptedException { // -Xmx20m: 最大堆內存20MB // -Xmn10m: 年輕代10MB (Eden S0 S1) // -XX:SurvivorRatio8: Eden:S0:S1 8:1:1, 所以Eden約8MB, S0/S1約1MB // -XX:MaxTenuringThreshold3: 設置最大年齡閾值為3 // -XX:PrintGCDetails: 打印詳細GC信息 // -XX:PrintGCTimestamps: 打印GC時間戳 // -XX:PrintTenuringDistribution: 打印對象年齡分布 // -XX:UseSerialGC: 使用Serial GC便于觀察 // -XX:TargetSurvivorRatio90: 目標Survivor空間使用率90% System.out.println(Starting TenuringThresholdDemo...); System.out.println(JVM Args: -Xmx20m -Xmn10m -XX:SurvivorRatio8 -XX:MaxTenuringThreshold3 -XX:PrintGCDetails -XX:PrintGCTimestamps -XX:PrintTenuringDistribution -XX:UseSerialGC -XX:TargetSurvivorRatio90); Listbyte[] list new ArrayList(); // 1. 第一次分配觸發(fā)Minor GC // 目標讓一部分對象存活1次GC年齡變?yōu)? System.out.println(n--- First Allocation (Eden full, Minor GC 1) ---); list.add(new byte[2 * _1MB]); // obj1: 2MB list.add(new byte[2 * _1MB]); // obj2: 2MB list.add(new byte[2 * _1MB]); // obj3: 2MB // Eden約8MB此時已經分配了6MB。 // 再分配一個Eden會滿觸發(fā)第一次Minor GC。 // 此時list中的三個對象年齡為1。 byte[] allocation1 new byte[3 * _1MB]; // obj4: 3MB觸發(fā)GCobj1,2,3年齡變?yōu)?進入S1 System.out.println(After first allocation block, list size: list.size()); Thread.sleep(100); // 稍作等待讓GC日志打印完整 // 2. 第二次分配觸發(fā)Minor GC // 目標讓obj1,2,3存活2次GC年齡變?yōu)? System.out.println(n--- Second Allocation (Eden full, Minor GC 2) ---); byte[] allocation2 new byte[7 * _1MB]; // obj5: 7MB觸發(fā)GCobj1,2,3年齡變?yōu)?進入S0 // 同時obj4被回收。 System.out.println(After second allocation block, list size: list.size()); Thread.sleep(100); // 3. 第三次分配觸發(fā)Minor GC // 目標讓obj1,2,3存活3次GC年齡變?yōu)?觀察是否晉升 System.out.println(n--- Third Allocation (Eden full, Minor GC 3) ---); byte[] allocation3 new byte[7 * _1MB]; // obj6: 7MB觸發(fā)GCobj1,2,3年齡變?yōu)?進入S1或老年代 // 同時obj5被回收。 System.out.println(After third allocation block, list size: list.size()); Thread.sleep(100); // 4. 第四次分配觸發(fā)Minor GC // 目標讓obj1,2,3存活4次GC年齡變?yōu)?觀察是否晉升 System.out.println(n--- Fourth Allocation (Eden full, Minor GC 4) ---); byte[] allocation4 new byte[7 * _1MB]; // obj7: 7MB觸發(fā)GCobj1,2,3年齡變?yōu)?進入S0或老年代 // 同時obj6被回收。 System.out.println(After fourth allocation block, list size: list.size()); Thread.sleep(100); // 確保list中的對象不會被回收 System.gc(); // 觸發(fā)一次Full GC以觀察最終堆狀態(tài)雖然不是本次重點 System.out.println(Done.); } }運行命令示例java -Xmx20m -Xmn10m -XX:SurvivorRatio8 -XX:MaxTenuringThreshold3 -XX:PrintGCDetails -XX:PrintGCTimestamps -XX:PrintTenuringDistribution -XX:UseSerialGC -XX:TargetSurvivorRatio90 TenuringThresholdDemoGC日志分析精簡示例由于完整的GC日志會非常龐大我們截取關鍵部分進行分析。第一次Minor GC (age1)[0.123s][info][gc,heap,exit] Heap [0.123s][info][gc,heap,exit] PSYoungGen total 9216K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) [0.123s][info][gc,heap,exit] eden space 8192K, 75% used [0x00000000ff600000,0x00000000ffc00000,0x00000000ffe00000) [0.123s][info][gc,heap,exit] from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000) [0.123s][info][gc,heap,exit] to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000) [0.123s][info][gc,heap,exit] ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) [0.123s][info][gc,heap,exit] space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000) [0.123s][info][gc,heap,exit] Metaspace used 3871K, capacity 4402K, committed 4480K, reserved 1056768K [0.123s][info][gc,heap,exit] class space used 416K, capacity 427K, committed 512K, reserved 1048576K [0.128s][info][gc,start ] GC(0) Pause Young (Allocation Failure) [0.130s][info][gc,task ] GC(0) Using 1 workers of 4 for evacuation [0.130s][info][gc,age ] GC(0) Desired survivor size 921600 bytes, TargetSurvivorRatio 90% [0.130s][info][gc,age ] GC(0) Age 1: 614400 bytes, 60.00 % of survivor space (921600 bytes) [0.130s][info][gc,age ] GC(0) Age 2: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.130s][info][gc,age ] GC(0) Age 3: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.130s][info][gc,age ] GC(0) Tenuring threshold 3 (MaxTenuringThreshold 3) [0.130s][info][gc ] GC(0) Pause Young (Allocation Failure) 9M-6M(19M) 2.067ms [0.130s][info][gc,heap ] PSYoungGen total 9216K, used 6002K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) [0.130s][info][gc,heap ] eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000) [0.130s][info][gc,heap ] from space 1024K, 58.78% used [0x00000000fff00000,0x00000000fff8fe00,0x0000000100000000) [0.130s][info][gc,heap ] to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000) [0.130s][info][gc,heap ] ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) [0.130s][info][gc,heap ] space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000) [0.130s][info][gc,heap ] Metaspace used 3871K, capacity 4402K, committed 4480K, reserved 1056768K [0.130s][info][gc,heap ] class space used 416K, capacity 427K, committed 512K, reserved 1048576KDesired survivor size 921600 bytes, TargetSurvivorRatio 90%: Survivor空間目標使用量是921600字節(jié)約0.9MB它是S0/S1空間1MB的90%。Age 1: 614400 bytes, 60.00 % of survivor space: 年齡為1的對象占用614400字節(jié)6MB占Survivor空間容量的60%。這個6MB就是我們代碼中l(wèi)ist里的3個2MB對象。Tenuring threshold 3 (MaxTenuringThreshold 3): 此時動態(tài)計算出的晉升閾值仍然是MaxTenuringThreshold設置的3。因為60% (0.6MB) 并沒有超過90% (0.9MB)所以沒有提前晉升。from space 1024K, 58.78% used: 晉升后from space(即S1) 被使用了約58.78%里面存的是年齡為1的對象。第二次Minor GC (age2)[0.231s][info][gc,start ] GC(1) Pause Young (Allocation Failure) [0.233s][info][gc,age ] GC(1) Desired survivor size 921600 bytes, TargetSurvivorRatio 90% [0.233s][info][gc,age ] GC(1) Age 1: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.233s][info][gc,age ] GC(1) Age 2: 614400 bytes, 60.00 % of survivor space (921600 bytes) [0.233s][info][gc,age ] GC(1) Age 3: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.233s][info][gc,age ] GC(1) Tenuring threshold 3 (MaxTenuringThreshold 3) [0.233s][info][gc ] GC(1) Pause Young (Allocation Failure) 9M-6M(19M) 2.100ms [0.233s][info][gc,heap ] PSYoungGen total 9216K, used 6002K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) [0.233s][info][gc,heap ] eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000) [0.233s][info][gc,heap ] from space 1024K, 58.78% used [0x00000000ffe00000,0x00000000ffe8fe00,0x00000000fff00000) [0.233s][info][gc,heap ] to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)Age 2: 614400 bytes, 60.00 % of survivor space: 此時上次Minor GC幸存的對象年齡變成了2依然占用6MB。Tenuring threshold 3: 動態(tài)晉升閾值依然是3。第三次Minor GC (age3)[0.334s][info][gc,start ] GC(2) Pause Young (Allocation Failure) [0.336s][info][gc,age ] GC(2) Desired survivor size 921600 bytes, TargetSurvivorRatio 90% [0.336s][info][gc,age ] GC(2) Age 1: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.336s][info][gc,age ] GC(2) Age 2: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.336s][info][gc,age ] GC(2) Age 3: 614400 bytes, 60.00 % of survivor space (921600 bytes) [0.336s][info][gc,age ] GC(2) Tenuring threshold 3 (MaxTenuringThreshold 3) [0.336s][info][gc ] GC(2) Pause Young (Allocation Failure) 9M-6M(19M) 2.100ms [0.336s][info][gc,heap ] PSYoungGen total 9216K, used 6002K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) [0.336s][info][gc,heap ] eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000) [0.336s][info][gc,heap ] from space 1024K, 58.78% used [0x00000000fff00000,0x00000000fff8fe00,0x0000000100000000) [0.336s][info][gc,heap ] to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)Age 3: 614400 bytes, 60.00 % of survivor space: 對象的年齡達到3。Tenuring threshold 3: 動態(tài)晉升閾值仍然是3。關鍵點由于我們設置MaxTenuringThreshold3并且在這次GC中對象的年齡達到了3理論上它們應該晉升了。然而日志中from space仍然顯示58.78%使用說明它們還在Survivor空間。這是因為年齡計數(shù)器是在對象被復制到“To”Survivor空間時才更新的。當對象年齡達到MaxTenuringThreshold時在下一次Minor GC中它們才會被直接復制到老年代。也就是說當age達到MaxTenuringThreshold時它是在這次GC中被標記為“可以晉升”然后被直接復制到老年代而不是復制到Survivor空間。所以在第三次GC結束后list中的對象年齡從2變?yōu)?它們被復制到了from space(新的S1)。第四次Minor GC (age4)[0.437s][info][gc,start ] GC(3) Pause Young (Allocation Failure) [0.439s][info][gc,age ] GC(3) Desired survivor size 921600 bytes, TargetSurvivorRatio 90% [0.439s][info][gc,age ] GC(3) Age 1: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.439s][info][gc,age ] GC(3) Age 2: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.439s][info][gc,age ] GC(3) Age 3: 0 bytes, 0.00 % of survivor space (921600 bytes) [0.439s][info][gc,age ] GC(3) Tenuring threshold 3 (MaxTenuringThreshold 3) [0.439s][info][gc ] GC(3) Pause Young (Allocation Failure) 9M-0M(19M) 2.050ms [0.439s][info][gc,heap ] PSYoungGen total 9216K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) [0.439s][info][gc,heap ] eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000) [0.439s][info][gc,heap ] from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000) [0.439s][info][gc,heap ] to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000) [0.439s][info][gc,heap ] ParOldGen total 10240K, used 6144K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) [0.439s][info][gc,heap ] space 10240K, 60.00% used [0x00000000fec00000,0x00000000ff1ff000,0x00000000ff600000)關鍵觀察點在這次GC之前l(fā)ist中的對象年齡是3。當再次觸發(fā)Minor GC時這些年齡為3的對象由于MaxTenuringThreshold3它們達到了晉升條件被直接復制到了老年代。PSYoungGen total 9216K, used 0K: 年輕代被清空包括Survivor空間。ParOldGen total 10240K, used 6144K: 老年代被使用了6144K6MB這正是我們list中3個2MB對象的大小。這證實了對象在年齡達到MaxTenuringThreshold時被晉升到了老年代。通過這個實驗我們可以清晰地看到MaxTenuringThreshold和對象年齡如何在Minor GC中協(xié)同工作最終決定對象的去留。其他晉升條件大對象與空間擔保除了年齡閾值還有其他情況會導致對象晉升到老年代大對象直接晉升老年代PretenureSizeThreshold有些對象即使是新創(chuàng)建的也可能因為其體積過大無法在年輕代的Eden區(qū)或Survivor空間中找到足夠的連續(xù)內存進行分配或者頻繁在Survivor空間復制的成本過高。JVM允許通過設置PretenureSizeThreshold參數(shù)讓大小超過這個閾值的對象直接在老年代中分配。參數(shù)-XX:PretenureSizeThresholdN單位為字節(jié)0表示禁用。目的避免大對象在年輕代觸發(fā)過多的Minor GC減少復制開銷。注意這個參數(shù)只對Serial和ParNewParallel Scavenge收集器有效對Parallel Old和CMS收集器無效。G1收集器有自己的 Region 分配策略不需要這個參數(shù)。// 示例設置大對象直接晉升 // java -Xmx20m -Xmn10m -XX:PretenureSizeThreshold4194304 -XX:PrintGCDetails ... public class LargeObjectPromotion { private static final int _1MB 1024 * 1024; public static void main(String[] args) throws InterruptedException { System.out.println(Starting LargeObjectPromotion demo...); // 設置PretenureSizeThreshold4MB byte[] largeObj1 new byte[5 * _1MB]; // 5MB 4MB, 直接進入老年代 System.out.println(Allocated 5MB object.); Thread.sleep(1000); byte[] largeObj2 new byte[2 * _1MB]; // 2MB 4MB, 正常在年輕代分配 System.out.println(Allocated 2MB object.); Thread.sleep(1000); // 觸發(fā)GC觀察 System.gc(); } }運行帶有-XX:PretenureSizeThreshold4194304的參數(shù)可以看到第一個5MB的對象直接分配在老年代而第二個2MB對象則在年輕代。Survivor空間不足空間擔保Handle Promotion Failure當進行Minor GC時如果Survivor To空間不足以容納所有存活的對象包括從Eden和From空間復制過來的以及從Old Gen擔保過來的那么這些無法放入Survivor To空間的對象就會被直接晉升到老年代。這種情況通常發(fā)生在年輕代存活對象過多或者Survivor空間設置過小的時候。為了應對這種情況JVM會進行“空間擔保”在Minor GC之前JVM會檢查老年代是否有足夠的連續(xù)空間來容納年輕代所有對象以防Survivor空間不足。如果老年代空間也不足則會觸發(fā)一次Full GC。這種機制是為了確保Minor GC能夠順利完成避免因內存不足而崩潰。GC參數(shù)調優(yōu)與性能影響理解對象晉升機制后我們可以更有效地進行JVM參數(shù)調優(yōu)以優(yōu)化應用程序的性能。年輕代大小配置-Xmn,-XX:NewRatio-Xmn直接設置年輕代大小。-XX:NewRatioN設置年輕代與老年代的比例。例如NewRatio2表示年輕代占1/3堆內存老年代占2/3。影響年輕代過小Minor GC會更頻繁STW時間可能縮短因為回收范圍小但對象可能更早晉升到老年代導致老年代更快被填滿增加Full GC的頻率和STW時間。年輕代過大Minor GC頻率降低但單次Minor GC的STW時間可能增長因為回收范圍大并且如果大量短生命周期對象在年輕代中存活時間過長會增加Minor GC的壓力。MaxTenuringThreshold的調整調高MaxTenuringThreshold效果對象在年輕代存活時間更長減少晉升到老年代的頻率。優(yōu)點如果應用中存在大量“中等生命周期”對象即在幾次GC后死亡的對象它們可以被在年輕代回收減少老年代的負擔和Full GC的次數(shù)。缺點Survivor空間需要更大的容量來容納這些存活對象否則可能導致Survivor空間溢出反而觸發(fā)提前晉升。如果這些對象最終仍會進入老年代那么在年輕代頻繁復制會增加Minor GC的開銷。調低MaxTenuringThreshold效果對象更快晉升到老年代。優(yōu)點可以減少Survivor空間的壓力避免因Survivor空間不足導致的問題。缺點可能導致老年代過早充滿增加Full GC的頻率和STW時間。如果這些對象本可以在年輕代被回收那么提前晉升到老年代會增加老年代的回收難度。調優(yōu)策略通常通過GC日志分析PrintTenuringDistribution輸出觀察對象的生命周期分布。如果發(fā)現(xiàn)大量對象在年齡很小例如3-5時就晉升到老年代但老年代很快又被回收可能意味著MaxTenuringThreshold過低。如果Survivor空間總是很滿且很多對象在達到MaxTenuringThreshold之前就因空間不足而晉升可能需要增大Survivor空間或者調整TargetSurvivorRatio。TargetSurvivorRatio的考量默認值通常是50%。調高JVM會更積極地保留對象在Survivor空間減少晉升。但可能導致Survivor空間利用率不足浪費內存。調低JVM會更早地將對象晉升到老年代以保持Survivor空間有更多空閑。這有助于避免Survivor空間溢出但可能增加老年代的壓力。調優(yōu)策略需要與MaxTenuringThreshold配合使用。如果希望更多對象在年輕代被回收可以適當調高MaxTenuringThreshold和TargetSurvivorRatio但要確保Survivor空間足夠大。PretenureSizeThreshold的合理設置目的避免大對象在年輕代來回復制的開銷。調優(yōu)策略通過分析應用日志或內存dump識別出哪些對象是“大對象”且生命周期較長。如果這些大對象在年輕代頻繁引發(fā)Minor GC可以考慮設置PretenureSizeThreshold讓它們直接進入老年代。但要注意這可能會增加老年代的GC壓力。GC日志解讀的關鍵指標Minor GC暫停時間、頻率反映年輕代回收效率。Full GC暫停時間、頻率反映老年代回收效率和整個堆的健康狀況。年輕代、老年代使用率趨勢分析有助于判斷內存分配和回收是否合理。PrintTenuringDistribution輸出直接顯示對象在年輕代的年齡分布是調整MaxTenuringThreshold和TargetSurvivorRatio的主要依據(jù)。不同GC算法中的晉升機制簡述雖然我們主要討論了HotSpot JVM中經典的年輕代晉升機制但不同的垃圾回收器在具體實現(xiàn)上會有所差異Serial / Parallel / CMS 收集器這些收集器都遵循前面描述的“Eden S0 S1”年輕代結構并使用復制算法進行Minor GC。MaxTenuringThreshold和動態(tài)年齡判斷機制對它們都是通用的且PretenureSizeThreshold對Serial和Parallel收集器有效。G1 (Garbage-First) 收集器G1是面向大內存、低延遲設計的收集器。它的堆被劃分為大小相等的多個“Region”。年輕代和老年代不再是連續(xù)的物理空間而是由多個Region邏輯組成。有Eden Region、Survivor Region和Old Region。G1仍然有類似“Survivor空間”的概念即Survivor Region也采用復制算法進行年輕代GC。晉升機制對象在Survivor Region中經歷多次GC后其年齡達到MaxTenuringThreshold(G1默認6)會被復制到Old Region。G1的獨特之處在于其“Remembered Set”RSet機制用于記錄從老年代到年輕代的引用從而在進行年輕代GC時無需掃描整個老年代提高效率。G1不再使用PretenureSizeThreshold而是根據(jù)對象大小如果對象過大會直接在老年代的Humongous Region中分配。盡管G1在內部實現(xiàn)上有所不同但其核心的“分代”思想和“年齡晉升”機制依然存在只是具體實現(xiàn)細節(jié)更加精細和復雜以適應其并發(fā)和低延遲目標。內存分代策略的精髓與調優(yōu)考量分代垃圾回收策略是JVM在“大部分對象朝生夕滅”和“少量對象長久存活”這一經驗假說指導下的精妙設計。它通過將堆內存劃分為年輕代和老年代并采用不同的回收策略極大地優(yōu)化了垃圾回收的性能降低了應用程序的停頓時間。理解對象從年輕代“晉升”到老年代的各種細節(jié)包括硬性年齡閾值MaxTenuringThreshold、HotSpot JVM的動態(tài)年齡判斷機制、大對象直接晉升以及Survivor空間擔保是進行JVM性能調優(yōu)的關鍵一環(huán)。通過合理配置這些參數(shù)結合GC日志的深入分析我們可以幫助應用程序在有限的內存資源下以最優(yōu)的性能運行減少不必要的GC開銷和停頓。調優(yōu)是一個持續(xù)的過程需要結合應用程序的實際運行情況、負載模式和性能目標進行迭代和驗證。掌握這些底層機制我們就能更有信心地駕馭JVM構建出高性能、高可用的Java應用。
版權聲明: 本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若內容造成侵權/違法違規(guī)/事實不符,請聯(lián)系我們進行投訴反饋,一經查實,立即刪除!

誰專門做網站安全維護網站搭建免費域名

誰專門做網站安全維護,網站搭建免費域名,建個人網站,番禺網站建設怎么樣文章目錄 前言1. 安裝Docker2. 使用Docker拉取鏡像3. 創(chuàng)建并啟動Cloudreve容器4. 本地訪問測試5. 公

2026/01/21 18:17:01

邵陽網站制作建設如何攻擊Wordpress站點

邵陽網站制作建設,如何攻擊Wordpress站點,網頁版淘寶網登錄入口,wordpress寫博客流行嗎分享3個國內最大的黑客學習網站#xff0c;從新手到黑客高手#xff0c;手把手帶你進階#xff0

2026/01/21 16:43:01

便民工具 網站開發(fā)wordpress做cms

便民工具 網站開發(fā),wordpress做cms,該工具支持 preview 功能,石家莊網站系統(tǒng)建設量子物理中的哈代空間與位置相關質量問題的奇妙影響 1. 哈代空間公理與量子物理中的時間不對稱性

2026/01/21 18:55:01

做獵頭需要用到的網站一站式網站建設公司

做獵頭需要用到的網站,一站式網站建設公司,石家莊建站外貿網站,阿里云clouder網站建設RealSense多相機系統(tǒng)標定實戰(zhàn)#xff1a;從配置到點云拼接的完整指南 【免費下載鏈接】libreals

2026/01/21 19:02:01