0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Java所承諾的自動(dòng)內(nèi)存管理

存儲(chǔ)界 ? 來(lái)源:未知 ? 作者:李倩 ? 2018-04-29 15:16 ? 次閱讀

Java所承諾的自動(dòng)內(nèi)存管理主要是針對(duì)對(duì)象內(nèi)存的回收和對(duì)象內(nèi)存的分配。

在Java虛擬機(jī)的五塊內(nèi)存空間中,程序計(jì)數(shù)器、Java虛擬機(jī)棧、本地方法棧內(nèi)存的分配和回收都具有確定性,一般在編譯階段就能確定需要分配的內(nèi)存大小,并且由于都是線程私有,因此它們的內(nèi)存空間都隨著線程的創(chuàng)建而創(chuàng)建,線程的結(jié)束而回收。也就是這三個(gè)區(qū)域的內(nèi)存分配和回收都具有確定性,垃圾回收器不需要在這里花費(fèi)太大的精力。

而Java虛擬機(jī)中的方法區(qū)因?yàn)槭怯脕?lái)存儲(chǔ)類信息、常量、靜態(tài)變量,這些數(shù)據(jù)的變動(dòng)性較小,因此不是Java內(nèi)存管理重點(diǎn)需要關(guān)注的區(qū)域。

而對(duì)于堆,所有線程共享,所有的對(duì)象都需要在堆中創(chuàng)建和回收。雖然每個(gè)對(duì)象的大小在類加載的時(shí)候就能確定,但對(duì)象的數(shù)量只有在程序運(yùn)行期間才能確定,因此堆中內(nèi)存的分配具有較大的不確定性。此外,對(duì)象的生命周期長(zhǎng)短不一,因此需要針對(duì)不同生命周期的對(duì)象采用不同的內(nèi)存回收算法,增加了內(nèi)存回收的復(fù)雜性。

綜上所述:Java自動(dòng)內(nèi)存管理最核心的功能是堆內(nèi)存中對(duì)象的分配與回收。

對(duì)象優(yōu)先在Eden區(qū)中分配

目前主流的垃圾收集器都會(huì)采用分代回收算法,因此需要將堆內(nèi)存分為新生代和老年代。

在新生代中為了防止內(nèi)存碎片問(wèn)題,因此垃圾收集器一般都選用“復(fù)制”算法。因此,堆內(nèi)存的新生代被進(jìn)一步分為:Eden區(qū)+Survior1區(qū)+Survior2區(qū)。

每次創(chuàng)建對(duì)象時(shí),首先會(huì)在Eden區(qū)中分配。

若Eden區(qū)已滿,則在Survior1區(qū)中分配。

若Eden區(qū)+Survior1區(qū)剩余內(nèi)存太少,導(dǎo)致對(duì)象無(wú)法放入該區(qū)域時(shí),就會(huì)啟用“分配擔(dān)保”,將當(dāng)前Eden區(qū)+Survior1區(qū)中的對(duì)象轉(zhuǎn)移到老年代中,然后再將新對(duì)象存入Eden區(qū)。

大對(duì)象直接進(jìn)入老年代

所謂“大對(duì)象”就是指一個(gè)占用大量連續(xù)存儲(chǔ)空間的對(duì)象,如數(shù)組。

當(dāng)發(fā)現(xiàn)一個(gè)大對(duì)象在Eden區(qū)+Survior1區(qū)中存不下的時(shí)候就需要分配擔(dān)保機(jī)制把當(dāng)前Eden區(qū)+Survior1區(qū)的所有對(duì)象都復(fù)制到老年代中去。

我們知道,一個(gè)大對(duì)象能夠存入Eden區(qū)+Survior1區(qū)的概率比較小,發(fā)生分配擔(dān)保的概率比較大,而分配擔(dān)保需要涉及到大量的復(fù)制,就會(huì)造成效率低下。

因此,對(duì)于大對(duì)象我們直接把他放到老年代中去,從而就能避免大量的復(fù)制操作。

那么,什么樣的對(duì)象才是“大對(duì)象”呢?

通過(guò)-XX:PretrnureSizeThreshold參數(shù)設(shè)置大對(duì)象

該參數(shù)用于設(shè)置大小超過(guò)該參數(shù)的對(duì)象被認(rèn)為是“大對(duì)象”,直接進(jìn)入老年代。

注意:該參數(shù)只對(duì)Serial和ParNew收集器有效。

生命周期較長(zhǎng)的對(duì)象進(jìn)入老年代

老年代用于存儲(chǔ)生命周期較長(zhǎng)的對(duì)象,那么我們?nèi)绾闻袛嘁粋€(gè)對(duì)象的年齡呢?

新生代中的每個(gè)對(duì)象都有一個(gè)年齡計(jì)數(shù)器,當(dāng)新生代發(fā)生一次MinorGC后,存活下來(lái)的對(duì)象的年齡就加一,當(dāng)年齡超過(guò)一定值時(shí),就將超過(guò)該值的所有對(duì)象轉(zhuǎn)移到老年代中去。

使用-XXMaxTenuringThreshold設(shè)置新生代的最大年齡

設(shè)置該參數(shù)后,只要超過(guò)該參數(shù)的新生代對(duì)象都會(huì)被轉(zhuǎn)移到老年代中去。

相同年齡的對(duì)象內(nèi)存超過(guò)Survior內(nèi)存一半的對(duì)象進(jìn)入老年代

如果當(dāng)前新生代的Survior中,年齡相同的對(duì)象的內(nèi)存空間總和超過(guò)了Survior內(nèi)存空間的一半,那么所有年齡相同的對(duì)象和超過(guò)該年齡的對(duì)象都被轉(zhuǎn)移到老年代中去。無(wú)需等到對(duì)象的年齡超過(guò)MaxTenuringThreshold才被轉(zhuǎn)移到老年代中去。

“分配擔(dān)?!辈呗栽斀?/p>

當(dāng)垃圾收集器準(zhǔn)備要在新生代發(fā)起一次MinorGC時(shí),首先會(huì)檢查“老年代中最大的連續(xù)空閑區(qū)域的大小 是否大于 新生代中所有對(duì)象的大???”,也就是老年代中目前能夠?qū)⑿律兴袑?duì)象全部裝下?

若老年代能夠裝下新生代中所有的對(duì)象,那么此時(shí)進(jìn)行MinorGC沒(méi)有任何風(fēng)險(xiǎn),然后就進(jìn)行MinorGC。

若老年代無(wú)法裝下新生代中所有的對(duì)象,那么此時(shí)進(jìn)行MinorGC是有風(fēng)險(xiǎn)的,垃圾收集器會(huì)進(jìn)行一次預(yù)測(cè):根據(jù)以往MinorGC過(guò)后存活對(duì)象的平均數(shù)來(lái)預(yù)測(cè)這次MinorGC后存活對(duì)象的平均數(shù)。

如果以往存活對(duì)象的平均數(shù)小于當(dāng)前老年代最大的連續(xù)空閑空間,那么就進(jìn)行MinorGC,雖然此次MinorGC是有風(fēng)險(xiǎn)的。

如果以往存活對(duì)象的平均數(shù)大于當(dāng)前老年代最大的連續(xù)空閑空間,那么就對(duì)老年代進(jìn)行一次Full GC,通過(guò)清除老年代中廢棄數(shù)據(jù)來(lái)擴(kuò)大老年代空閑空間,以便給新生代作擔(dān)保。

這個(gè)過(guò)程就是分配擔(dān)保。

注意:

1. 分配擔(dān)保是老年代為新生代作擔(dān)保;

2. 新生代中使用“復(fù)制”算法實(shí)現(xiàn)垃圾回收,老年代中使用“標(biāo)記-清除”或“標(biāo)記-整理”算法實(shí)現(xiàn)垃圾回收,只有使用“復(fù)制”算法的區(qū)域才需要分配擔(dān)保,因此新生代需要分配擔(dān)保,而老年代不需要分配擔(dān)保。

名詞解釋:

GC:垃圾收集器

Minor GC:新生代GC,指發(fā)生在新生代的垃圾收集動(dòng)作,所有的Minor GC都會(huì)觸發(fā)全世界的暫停(stop-the-world),停止應(yīng)用程序的線程,不過(guò)這個(gè)過(guò)程非常短暫。

Major GC/Full GC:老年代GC,指發(fā)生在老年代的GC。

JVM:Java Virtual Machine(Java虛擬機(jī))的縮寫(xiě)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3025

    瀏覽量

    74054
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2967

    瀏覽量

    104758

原文標(biāo)題:JVM學(xué)習(xí),對(duì)象內(nèi)存的分配策略

文章出處:【微信號(hào):cunchujie,微信公眾號(hào):存儲(chǔ)界】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Java程序內(nèi)存低效使用問(wèn)題的分析

    Java程序內(nèi)存的低效使用是導(dǎo)致其性能問(wèn)題的主要因素。該文分析了泄漏對(duì)象、蚍蜉對(duì)象和空閑對(duì)象3類導(dǎo)致內(nèi)存低效使用的情況,探討解決上述問(wèn)題的方法,并提出構(gòu)造對(duì)象行為模式
    發(fā)表于 04-09 09:39 ?12次下載

    java線程內(nèi)存模型

    一、Java內(nèi)存模型 按照官方的說(shuō)法:Java 虛擬機(jī)具有一個(gè)堆,堆是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,所有類實(shí)例和數(shù)組的內(nèi)存均從此處分配。 JVM主要管理
    發(fā)表于 09-27 10:55 ?0次下載
    <b class='flag-5'>java</b>線程<b class='flag-5'>內(nèi)存</b>模型

    實(shí)例分析內(nèi)存回收機(jī)制在java中的應(yīng)用

    Java中,它的內(nèi)存管理包括兩方面:內(nèi)存分配(創(chuàng)建Java對(duì)象的時(shí)候)和內(nèi)存回收,這兩方面工作
    發(fā)表于 09-27 15:10 ?0次下載
    實(shí)例分析<b class='flag-5'>內(nèi)存</b>回收機(jī)制在<b class='flag-5'>java</b>中的應(yīng)用

    Java內(nèi)存模型及原理分析

    一、Java內(nèi)存模型 按照官方的說(shuō)法:Java 虛擬機(jī)具有一個(gè)堆,堆是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,所有類實(shí)例和數(shù)組的內(nèi)存均從此處分配。 JVM主要管理
    發(fā)表于 09-28 11:49 ?0次下載
    <b class='flag-5'>Java</b><b class='flag-5'>內(nèi)存</b>模型及原理分析

    Java內(nèi)存區(qū)域分配、Java虛擬機(jī)棧、對(duì)象的訪問(wèn)方式和GC

    對(duì)于Java程序員來(lái)說(shuō),在虛擬機(jī)的自動(dòng)內(nèi)存管理機(jī)制的幫助下,不再需要為每一個(gè)new操作去寫(xiě)配對(duì)的delete/free代碼,而且不容易出現(xiàn) 內(nèi)存
    發(fā)表于 12-11 16:28 ?2291次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>內(nèi)存</b>區(qū)域分配、<b class='flag-5'>Java</b>虛擬機(jī)棧、對(duì)象的訪問(wèn)方式和GC

    Android內(nèi)存泄漏問(wèn)題如何優(yōu)化?

    作者:無(wú)名之輩FTER 來(lái)源:CSDN博客 眾所周知,Java因其擁有獨(dú)特的虛擬機(jī)(JVM)設(shè)計(jì),使其成為一門(mén)跨平臺(tái)、內(nèi)存自動(dòng)管理的高級(jí)開(kāi)發(fā)語(yǔ)言。所謂跨平臺(tái),即一次編譯,多次運(yùn)行,從而
    的頭像 發(fā)表于 09-11 15:55 ?1801次閱讀

    詳解Java虛擬機(jī)的JVM內(nèi)存布局

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過(guò)程中內(nèi)存申請(qǐng)、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的JVM對(duì)于內(nèi)存的劃分方式和
    的頭像 發(fā)表于 07-13 09:52 ?525次閱讀
    詳解<b class='flag-5'>Java</b>虛擬機(jī)的JVM<b class='flag-5'>內(nèi)存</b>布局

    java內(nèi)存溢出的幾種原因和解決辦法

    Java是一種使用垃圾回收機(jī)制的編程語(yǔ)言,由于自動(dòng)內(nèi)存管理機(jī)制的存在,Java程序中發(fā)生內(nèi)存溢出
    的頭像 發(fā)表于 11-23 14:44 ?6185次閱讀

    java內(nèi)存溢出排查方法

    Java內(nèi)存溢出(Memory overflow)是指Java虛擬機(jī)(JVM)中的堆內(nèi)存無(wú)法滿足對(duì)象分配的需求,導(dǎo)致程序拋出OutOfMemoryError異常。
    的頭像 發(fā)表于 11-23 14:46 ?3242次閱讀

    如何查看java程序的內(nèi)存分布

    。 程序計(jì)數(shù)器: 程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,它的作用是指示當(dāng)前線程執(zhí)行的字節(jié)碼指令的行號(hào)。在多線程環(huán)境下,每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,用于記錄當(dāng)前線程執(zhí)行的字節(jié)碼指令。 Java虛擬機(jī)棧:
    的頭像 發(fā)表于 11-23 14:47 ?1059次閱讀

    jvm運(yùn)行時(shí)內(nèi)存區(qū)域劃分

    JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫(xiě),它是Java編程語(yǔ)言的運(yùn)行環(huán)境。JVM的主要功能是將Java源代碼轉(zhuǎn)換為機(jī)器代碼,并且在運(yùn)行時(shí)
    的頭像 發(fā)表于 12-05 14:08 ?537次閱讀

    jvm管理內(nèi)存包括哪幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存

    JVM(Java虛擬機(jī))是Java程序的運(yùn)行環(huán)境,它提供了內(nèi)存管理機(jī)制來(lái)管理Java程序所需的運(yùn)
    的頭像 發(fā)表于 12-05 14:09 ?564次閱讀

    jvm內(nèi)存區(qū)域由哪幾部分組成

    。下面將詳細(xì)介紹這些部分。 堆內(nèi)存(Heap Memory):堆內(nèi)存是JVM中最大的一塊內(nèi)存區(qū)域,用來(lái)存儲(chǔ)對(duì)象實(shí)例和數(shù)組對(duì)象。堆內(nèi)存被所有線程
    的頭像 發(fā)表于 12-05 14:10 ?825次閱讀

    java虛擬機(jī)內(nèi)存包括遠(yuǎn)空間內(nèi)存

    詳細(xì)介紹JVM內(nèi)存的各個(gè)部分及其作用。 Java堆(Heap) Java堆是JVM管理的最大一塊內(nèi)存區(qū)域,用于存放
    的頭像 發(fā)表于 12-05 14:15 ?409次閱讀

    深入理解Java 8內(nèi)存管理機(jī)制及故障排查實(shí)戰(zhàn)指南

    Java自動(dòng)內(nèi)存管理機(jī)制是由 JVM 中的垃圾收集器來(lái)實(shí)現(xiàn)的,垃圾收集器會(huì)定期掃描堆內(nèi)存中的對(duì)象,檢測(cè)并清除不再使用的對(duì)象,以釋放
    的頭像 發(fā)表于 04-04 08:10 ?1005次閱讀
    深入理解<b class='flag-5'>Java</b> 8<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>機(jī)制及故障排查實(shí)戰(zhàn)指南