日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

【拥抱大厂系列】百度面试官问过的 “JVM内存分配与回收策略原理”,我用这篇文章搞定了

發(fā)布時(shí)間:2025/3/20 83 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【拥抱大厂系列】百度面试官问过的 “JVM内存分配与回收策略原理”,我用这篇文章搞定了 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

點(diǎn)個(gè)贊,看一看,好習(xí)慣!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收錄,這是我花了3個(gè)月總結(jié)的一線大廠Java面試總結(jié),本人已拿騰訊等大廠offer。

在前面的一篇文章深入理解Java虛擬機(jī)-如何利用VisualVM進(jìn)行性能分析中講到了一些關(guān)于JVM調(diào)優(yōu)的知識,但是,其實(shí),還是有一些問題沒有非常清楚的可以回答的,這里先給出幾個(gè)問題,然后,我們再展開這篇文章需要講解的知識。

  • 我們生成的對象最開始在哪分配?Eden?Survivor?還是老年代呢?
  • 進(jìn)入到老年代需要滿足什么條件呢?

接下來,我們就帶著這兩個(gè)問題展開全文。

1 對象優(yōu)先在哪分配

其實(shí),通過前面幾篇文章的講解,這個(gè)問題其實(shí)已經(jīng)見怪不怪了,在大多數(shù)的情況下,對象都是在新生代Eden區(qū)分配的,在前面的文章我們提到,在Eden區(qū)中如果內(nèi)存不夠分配的話,就會進(jìn)行一次Minor GC。同時(shí),我們還知道年輕代中默認(rèn)下Eden:Survivor0:Survivor2 = 8:1:1,同時(shí),還能通過參數(shù)-XX:SurvivorRatio來設(shè)置這個(gè)比例(關(guān)于這些參數(shù)的分析都可以查看這篇文章:深入理解Java虛擬機(jī)-常用vm參數(shù)分析)。

下面我們通過一個(gè)例子來分析是不是這樣的。

1.1 實(shí)例

給定JVM參數(shù):-Xms40M -Xmx40M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=4

前面三個(gè)參數(shù)設(shè)置Java堆的大小為40M,新生代為10M,緊跟著后面兩個(gè)是用于輸入GC信息。更多參數(shù)可以查看這篇文章:深入理解Java虛擬機(jī)-常用vm參數(shù)分析。

/*** @ClassName Test_01* @Description 參數(shù):-Xms40M -Xmx40M -Xmn20M -XX:+PrintGCDetails -XX:+UseSerialGC -XX:SurvivorRatio=8* @Author 歐陽思海* @Date 2019/12/3 16:00* @Version 1.0**/ public class Test_01 {private static final int M = 1024 * 1024;public static void test() {byte[] alloc1, alloc2, alloc3, alloc4;alloc1 = new byte[5 * M];alloc2 = new byte[5 * M];alloc3 = new byte[5 * M];alloc4 = new byte[10 * M];}public static void main(String[] args) {test();}}

輸入結(jié)果:

分析

  • eden:from:to=8:1:1,這個(gè)因?yàn)榍懊嬖O(shè)置了參數(shù)-XX:SurvivorRatio=8。
  • 新生代分配了20M的內(nèi)存,所以前面三個(gè)byte數(shù)組可以分配,但是,分配第四個(gè)的時(shí)候,空間不夠,所以,需要進(jìn)行一次Minor GC,GC之后,新生代從12534K變?yōu)?98K。
  • 前面在新生代分配的內(nèi)存Minor GC之后,進(jìn)入到了Survivor,但是,Survivor不夠分配,所以進(jìn)入到了老年代,老年代已用內(nèi)存達(dá)到了50%。

1.2 回答問題

所以,經(jīng)過上面的例子我們發(fā)現(xiàn),對象一般優(yōu)先在新生代分配的,如果新生代內(nèi)存不夠,就進(jìn)行Minor GC回收內(nèi)存。

2 進(jìn)入到老年代需要滿足什么條件

先給出答案,分為幾點(diǎn)。

  • 條件①:大對象直接進(jìn)入到老年代
  • 條件②:長期存活的對象可以進(jìn)入到老年代
  • 條件③:如果在Survivor空間中相同年齡所有對象的大小的總和大于Survivor空間的一半,年齡大于等于該年齡的對象直接進(jìn)入到老年代

2.1 分析條件①

  • 哪些屬于大對象呢?

一般來說大對象指的是很長的字符串及數(shù)組,或者靜態(tài)對象

  • 那么需要滿足多大才是大對象呢?

這個(gè)虛擬機(jī)提供了一個(gè)參數(shù)-XX:PretenureSizeThreshold=n,只需要大于這個(gè)參數(shù)所設(shè)置的值,就可以直接進(jìn)入到老年代。

step1: 解決了這兩個(gè)問題,首先,我們不設(shè)置上面的參數(shù)的例子,將對象的內(nèi)存大于Eden的大小看看情況。

/*** @ClassName Test_01* @Description 參數(shù):-Xms40M -Xmx40M -Xmn20M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC* @Author 歐陽思海* @Date 2019/12/3 16:00* @Version 1.0**/ public class Test_01 {private static final int M = 1024 * 1024;public static void test() {byte[] alloc1, alloc2, alloc3, alloc4; // alloc1 = new byte[5 * M]; // alloc2 = new byte[5 * M]; // alloc3 = new byte[5 * M];alloc4 = new byte[22 * M];}public static void main(String[] args) {test();}}

我們發(fā)現(xiàn)分配失敗,Java堆溢出,因?yàn)槌^了最大值。

step2: 下面我們看一個(gè)例子:設(shè)置-XX:PretenureSizeThreshold=104,857,600,這個(gè)單位是B字節(jié)(Byte/bait),所以這里是100M。

/*** @ClassName Test_01* @Description 參數(shù):-Xms2048M -Xmx2048M -Xmn1024M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:PretenureSizeThreshold=104,857,600* @Author 歐陽思海* @Date 2019/12/3 16:00* @Version 1.0**/ public class Test_01 {private static final int M = 1024 * 1024;public static void test() {byte[] alloc1, alloc2, alloc3, alloc4; // alloc1 = new byte[5 * M]; // alloc2 = new byte[5 * M]; // alloc3 = new byte[5 * M];alloc4 = new byte[500 * M];}public static void main(String[] args) {test();}}

發(fā)現(xiàn)新生代沒有分配,直接在老年代分配。

注意: 參數(shù)PretenureSizeThreshold只對Serial和ParNew兩款收集器有效。

2.2 分析條件②

進(jìn)入老年代規(guī)則:這里需要知道虛擬機(jī)對每個(gè)對象有個(gè)對象年齡計(jì)數(shù)器,如果對象在Eden出生經(jīng)過第一次Minor GC后任然存活,并且能夠被Survivor容納,將被移動到Survivor空間中,并且年齡設(shè)置為1。接下來,對象在Survivor中每次經(jīng)過一次Minor GC,年齡就增加1,默認(rèn)當(dāng)年齡達(dá)到15,就會進(jìn)入到老年代。

晉升到老年代的年齡閾值,可以通過參數(shù)-XX:MaxTenuringThreshold設(shè)置。

在下面的實(shí)例中,我們設(shè)置-XX:MaxTenuringThreshold=1。

/*** @ClassName Test_01* @Description 參數(shù):-Xms2048M -Xmx2048M -Xmn1024M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:MaxTenuringThreshold=1* @Author 歐陽思海* @Date 2019/12/3 16:00* @Version 1.0**/ public class Test_01 {private static final int M = 1024 * 1024;public static void test() {byte[] alloc1, alloc2, alloc3, alloc4;alloc1 = new byte[300 * M];alloc2 = new byte[300 * M];alloc3 = new byte[300 * M];alloc4 = new byte[500 * M];}public static void main(String[] args) {test();}}

從結(jié)果可以看出,from和to都沒有占用內(nèi)存,而老年代則占用了很多內(nèi)存。

2.3 分析條件③

條件③是:如果在Survivor空間中相同年齡所有對象的大小的總和大于Survivor空間的一半,年齡大于等于該年齡的對象直接進(jìn)入到老年代,而不需要等到參數(shù)-XX:MaxTenuringThreshold設(shè)置的年齡。

實(shí)例分析

/*** @ClassName Test_01* @Description 參數(shù):-Xms2048M -Xmx2048M -Xmn1024M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC* @Author 歐陽思海* @Date 2019/12/3 16:00* @Version 1.0**/ public class Test_01 {private static final int M = 1024 * 1024;public static void test() {byte[] alloc1, alloc2, alloc3, alloc4;alloc1 = new byte[100 * M];alloc2 = new byte[100 * M];//分配alloc3之前,空間不夠,所以minor GC,接著分配alloc3=900M大于Survivor空間一半,直接到老年代。alloc3 = new byte[900 * M];// alloc4 = new byte[500 * M];}public static void main(String[] args) {test();}}

輸入結(jié)果:

分配alloc3之前,空間不夠,所以minor GC,接著分配alloc3=900M大于Survivor空間一半,直接到老年代。從而發(fā)現(xiàn),survivor占用0,而老年代占用900M。

3 總結(jié)

這篇文章主要講解了JVM內(nèi)存分配與回收策略的原理,回答了下面的這兩個(gè)問題。

  • 我們生成的對象最開始在哪分配?Eden?Survivor?還是老年代呢?
  • 進(jìn)入到老年代需要滿足什么條件呢?

最后,再分享我歷時(shí)三個(gè)月總結(jié)的 Java 面試 + Java 后端技術(shù)學(xué)習(xí)指南,這是本人這幾年及春招的總結(jié),已經(jīng)拿到了大廠offer,整理成了一本電子書,拿去不謝,目錄如下:

現(xiàn)在免費(fèi)分享大家,在我的公眾號 好好學(xué)java 回復(fù) Java面試 即可獲取。

有收獲?希望老鐵們來個(gè)三連擊,給更多的人看到這篇文章

1、老鐵們,關(guān)注我的原創(chuàng)微信公眾號「好好學(xué)java」,專注于Java、數(shù)據(jù)結(jié)構(gòu)和算法、微服務(wù)、中間件等技術(shù)分享,保證你看完有所收獲。

2、給俺點(diǎn)個(gè)贊唄,可以讓更多的人看到這篇文章,順便激勵下我繼續(xù)寫作,嘻嘻。

點(diǎn)贊是對我最大的鼓勵
↓↓↓↓↓↓

總結(jié)

以上是生活随笔為你收集整理的【拥抱大厂系列】百度面试官问过的 “JVM内存分配与回收策略原理”,我用这篇文章搞定了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。