自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

三分鐘帶你秒懂對象的內(nèi)存分配流程

開發(fā) 前端
本次我們重點介紹下,創(chuàng)建不同大小的對象,在堆空間中發(fā)生的內(nèi)存分配變化,以便后續(xù)更好的理解 GC 調(diào)優(yōu)過程。

01、背景介紹

本篇綜合之前的知識,重點介紹一下對象的內(nèi)存分配流程。

02、對象的內(nèi)存分配原則

在之前的 JVM 內(nèi)存結(jié)構(gòu)布局的文章中,我們介紹到了 Java 堆的內(nèi)存布局,由 年輕代 (Young Generation) 和老年代 (Old Generation) 組成,默認情況下按照1 : 2的比例來分配空間。

其中年輕代又被劃分為三個不同的區(qū)域:Eden 區(qū)、From Survivor 區(qū)、To Survivor 區(qū),默認情況下按照8 : 1 : 1的比例來分配空間。

Java 堆的內(nèi)存布局,可以用如下圖來概括。

圖片圖片

當創(chuàng)建的對象不再被使用了是需要被回收掉的,以便騰出空間給新的對象使用,這就是對象的垃圾回收,也就是對象的 GC,我們會在后續(xù)的文章中再次介紹對象的垃圾回收算法以及垃圾收集器。

本次我們重點介紹下,創(chuàng)建不同大小的對象,在堆空間中發(fā)生的內(nèi)存分配變化,以便后續(xù)更好的理解 GC 調(diào)優(yōu)過程。

2.1、對象優(yōu)先分配在 Eden 區(qū)

默認情況下,創(chuàng)建的對象會優(yōu)先分配在年輕代的 Eden 區(qū),當 Eden 區(qū)不夠用的時候,會觸發(fā)一次 Minor GC。

什么是 Minor GC 呢?

Minor GC 指的是 JVM 發(fā)生在年輕代的垃圾回收動作,效率高、速度快,但是只清除年輕代的垃圾對象。

與之對應的還有 Major GC 和 Full GC,Major GC 指的是 JVM 發(fā)生在老年代的垃圾回收動作,Major GC 的速度一般要比 Minor GC 慢 10 倍以上;同時,許多 Major GC 是由 Minor GC 引起的,因此把這個過程也稱之為 Full GC,也就是對整個堆進行垃圾回收。

當 Eden 區(qū)滿了以后,會發(fā)生 Minor GC,存活下來的對象會被移動到 Survivor 區(qū),如果 Survivor 區(qū)裝不下這批對象,此時會直接移動到老年代。

通常年輕代的對象存活時間都很短,在 Minor GC 后,大部分的對象都會被回收掉,但是也不排除個例情況,存活下來的對象的年齡會進行 +1,當年齡達到 15歲時,也會被移動到老年代。

用戶可以通過-XX:MaxTenuringThreshold參數(shù)來調(diào)整年齡的閥值,默認是 15,最大值也是 15。

2.2、大對象直接進入老年代

所謂大對象,顧名思義就是占用內(nèi)存比較多的對象,大對象一般可以直接分配到老年代,這是 JVM 的一種優(yōu)化設計。

用戶可以手動通過-XX:PretenureSizeThreshold參數(shù)設置大對象的大小,默認是 0,意味著任何對象都會優(yōu)先在年輕代的 Eden 區(qū)分配內(nèi)存。

試想一下,假如大對象優(yōu)先在 Eden 區(qū)中分配,給其它的對象預留的空間就會變小,此時很容易觸發(fā) Minor GC,經(jīng)過多次 GC 之后,大對象可能會繼續(xù)存活,最終還是會被轉(zhuǎn)移到老年代。

與其如此,還不如直接分配到老年代。

2.3、對象動態(tài)年齡判斷機制

對象動態(tài)年齡判斷,簡單的說就是對 Survivor 區(qū)的對象年齡從小到大進行累加,當累加到 X 年齡(某個年齡)時占用空間的總和大于 50%,那么比 X 年齡大的對象都會移動到老年代。

這種機制是 JVM 的一個預測機制,虛擬機并不是完全要求對象年齡必須達到 15 才能移動到老年代。當 survivor 區(qū)快要滿了并且存在一批可能會長期存活的對象,那不如提前進入老年代,減少年輕代的壓力。

用戶可以使用-XX:TargetSurvivorRatio參數(shù)來設置保留多少空閑空間,默認值是 50。

2.4、逃逸分析

逃逸分析是一項比較前沿的優(yōu)化技術(shù),它并不是直接優(yōu)化代碼的手段,而是為其它優(yōu)化手段提供了分析技術(shù)。

什么是逃逸分析呢?

當一個對象在方法里面被定義后,它可能被外部方法所引用,例如作為調(diào)用參數(shù)傳遞到其他方法中,這種稱為方法逃逸;甚至還有可能被外部線程訪問到,譬如賦值給可以在其他線程中訪問的實例變量,這種稱為線程逃逸。

如果能證明一個對象不會逃移到方法外或者線程之外,換句話說就是別的方法或線程無法通過任何途徑訪問到這個對象,虛擬機可以通過一些途徑為這個變量進行一些不同程度的優(yōu)化。

比如棧上分配、同步消除、標量替換等優(yōu)化操作。

2.4.1、棧上分配

在上文我們提及到,對象會優(yōu)先在堆上分配,垃圾收集器會定期回收堆內(nèi)存中不再使用的對象,但這塊的內(nèi)存回收很耗時。

如果確定一個對象不會逃逸出方法之外,讓這個對象在棧上分配,對象所占用的內(nèi)存空間就可以隨著棧幀出棧而銷毀,這樣垃圾收集器的壓力將會小很多。

2.4.2、同步消除

線程同步本身是一個相對耗時的操作,如果逃逸分析能夠確定一個變量不會逃逸出線程,無法被其他線程訪問,那么這個變量的讀寫肯定就不會有競爭,此時虛擬機會對這個變量,實施的同步措施進行消除,比如去掉同步鎖來運行方法。

2.4.3、標量替換

標量是指一個數(shù)據(jù)已經(jīng)無法再分解成更小的數(shù)據(jù)來表示了,比如 Java 虛擬機中的原始數(shù)據(jù)類型(int,long 等數(shù)值類型以及 reference 類型)等都不能進一步分解,它們可以稱為標量。相對的,如果一個數(shù)據(jù)可以繼續(xù)分解,那它稱為聚合量。

Java 中最典型的聚合量是對象,如果逃逸分析證明一個對象不會被外部訪問,并且這個對象是可分解的,那程序真正執(zhí)行的時候?qū)⒖赡懿粍?chuàng)建這個對象,而改為直接創(chuàng)建它的若干個被這個方法使用到的成員變量來代替,拆散后的變量便可以被單獨分析與優(yōu)化,可以各自分別在棧幀或寄存器上分配空間,原本的對象就無需整體分配空間了。

默認情況下逃逸分析是關閉的,用戶可以使用-XX:+DoEscapeAnalysis參數(shù)來手動開啟逃逸分析。

03、小結(jié)

綜合以上的內(nèi)容,對象的內(nèi)存分配流程,可以用如下圖來概括。

圖片圖片

由此可知,對象在內(nèi)存分配的時候,會根據(jù)不同情況來判斷合理分配,以便 JVM 更快捷的進行回收資源。

04、參考

1.https://zhuanlan.zhihu.com/p/267223891

2.https://zhuanlan.zhihu.com/p/401057707

3.https://www.cnblogs.com/xrq730/p/4827590.html

4.https://www.jianshu.com/p/3d38cba67f8b

6.https://blog.csdn.net/clover_lily/article/details/80095580

7.https://blog.csdn.net/FIRE_TRAY/article/details/51275788

8.https://blog.csdn.net/yb970521/article/details/108015984

責任編輯:武曉燕 來源: 潘志的研發(fā)筆記
相關推薦

2024-06-06 08:50:43

2024-08-02 08:31:08

2024-02-22 07:37:37

對象JVM內(nèi)存

2022-02-17 09:24:11

TypeScript編程語言javaScrip

2021-04-20 13:59:37

云計算

2024-01-16 07:46:14

FutureTask接口用法

2024-08-30 08:50:00

2020-06-30 10:45:28

Web開發(fā)工具

2021-02-03 14:31:53

人工智能人臉識別

2024-01-12 07:38:38

AQS原理JUC

2024-07-05 09:31:37

2020-03-08 16:45:58

數(shù)據(jù)挖掘學習數(shù)據(jù)量

2017-01-18 15:38:20

語言

2024-09-13 08:49:45

2024-05-16 11:13:16

Helm工具release

2009-11-09 12:55:43

WCF事務

2024-12-18 10:24:59

代理技術(shù)JDK動態(tài)代理

2020-11-03 09:20:30

MySQLOracle數(shù)據(jù)庫

2022-02-21 18:16:38

Go語言枚舉

2023-12-27 08:15:47

Java虛擬線程
點贊
收藏

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