《JVM G1源碼分析和調(diào)優(yōu)》 —2.5 內(nèi)存分配和管理

      網(wǎng)友投稿 1080 2025-04-02

      2.5 內(nèi)存分配和管理

      C/C++程序員和Java程序員最大的區(qū)別之一就是對(duì)內(nèi)存管理的工作,Java程序員不需要管理內(nèi)存,因?yàn)橛蠮VM幫助管理。所以JVM的所謂開(kāi)發(fā)必然涉及內(nèi)存的分配和管理。我們這里盡可能地簡(jiǎn)化描述內(nèi)存分配和管理,只描述和GC算法相關(guān)的部分。本質(zhì)上來(lái)說(shuō),了解這一部分內(nèi)容越多,特別是了解JVM如何與操作系統(tǒng)交互的部分,越容易對(duì)JVM調(diào)優(yōu)。

      JVM作為內(nèi)存分配的管理器,一定涉及如何與內(nèi)存交互。那么JVM是如何管理內(nèi)存的?實(shí)際上內(nèi)存管理的算法很多,簡(jiǎn)單來(lái)說(shuō)JVM從操作系統(tǒng)申請(qǐng)一塊內(nèi)存,然后根據(jù)不同的GC算法進(jìn)行管理。下面以Linux為例看一下JVM是如何做的。

      首先JVM先通過(guò)操作系統(tǒng)的系統(tǒng)調(diào)用(system call)進(jìn)行內(nèi)存的申請(qǐng),典型的就是mmap。在這里提一個(gè)問(wèn)題,眾所周知glibc提供了我們常用的內(nèi)存管理函數(shù)如malloc/free/realloc/memcopy/memset等。為什么JVM不直接使用這些函數(shù)?glibc里面的malloc也是通過(guò)mmap等系統(tǒng)調(diào)用來(lái)完成內(nèi)存的分配,之后glibc再對(duì)已經(jīng)分配到的內(nèi)存進(jìn)行管理。GC算法實(shí)現(xiàn)了一套自己的管理方式,所以再基于malloc/free實(shí)現(xiàn)效率肯定不高。mmap必須以PAGE_SIZE為單位進(jìn)行映射,而內(nèi)存也只能以頁(yè)為單位進(jìn)行映射,若要映射非PAGE_SIZE整數(shù)倍的地址范圍,要先進(jìn)行內(nèi)存對(duì)齊,強(qiáng)行以PAGE_SIZE的倍數(shù)大小進(jìn)行映射。還要注意一點(diǎn),操作系統(tǒng)對(duì)內(nèi)存的分配管理典型地分為兩個(gè)階段:保留(reserve)和提交(commit)。保留階段告知系統(tǒng)從某一地址開(kāi)始到后面的dwSize大小的連續(xù)虛擬內(nèi)存需要供程序使用,進(jìn)程其他分配內(nèi)存的操作不得使用這段內(nèi)存;提交階段將虛擬地址映射到對(duì)應(yīng)的真實(shí)物理內(nèi)存中,這樣這塊內(nèi)存就可以正常使用。

      對(duì)于保留和提交,Windows在使用VirtualAlloc分配內(nèi)存時(shí)傳遞不同的參數(shù)MEM_RESERVE/MEM_COMMIT,Linux在mmap保留內(nèi)存時(shí)使用MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS,提交內(nèi)存時(shí)使用MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS。其中MAP_NORESERVE指不要為這個(gè)映射保留交換空間,MAP_FIXED使用指定的映射起始地址。

      在JVM中我們還看到了使用類(lèi)庫(kù)函數(shù)malloc/free的地方。這和JVM內(nèi)存管理策略有關(guān),JVM內(nèi)部也有很多數(shù)據(jù)需要在堆中分配,而這和Java堆空間沒(méi)有關(guān)系,所以直接使用類(lèi)庫(kù)函數(shù)。另外需要提一下JVM推薦使用jemalloc替代glibc,原因是其效率更高。

      JVM中常見(jiàn)的對(duì)象類(lèi)型有以下6種:

      ResourceObj:線程有一個(gè)資源空間(Resource Area),一般ResourceObj都位于這里。定義資源空間的目的是對(duì)JVM其他功能的支持,如CFG、在C1/C2優(yōu)化時(shí)可能需要訪問(wèn)運(yùn)行時(shí)信息(這些信息可以保存在線程的資源區(qū))。

      StackObj:棧對(duì)象,聲明的對(duì)象使用棧管理。其實(shí)棧對(duì)象并不提供任何功能,且禁止New/Delete操作。對(duì)象分配在線程棧中,或者使用自定義的棧容器進(jìn)行管理。

      ValueObj:值對(duì)象,該對(duì)象在堆對(duì)象需要進(jìn)行嵌套時(shí)使用,簡(jiǎn)單地說(shuō)就是對(duì)象分配的位置和宿主對(duì)象(即擁有這個(gè)ValueObj對(duì)象的對(duì)象)是一樣的。

      AllStatic:靜態(tài)對(duì)象,全局對(duì)象,只有一個(gè)。值得一提的是C++中靜態(tài)對(duì)象的初始化并沒(méi)有通過(guò)規(guī)范保證,可能會(huì)有一個(gè)問(wèn)題,就是兩個(gè)靜態(tài)對(duì)象相互依賴(lài),那么在初始化的時(shí)候可能出錯(cuò)。JVM中的很多靜態(tài)對(duì)象的初始化,都是顯式調(diào)用靜態(tài)初始化函數(shù)。

      MetaspaceObj:元對(duì)象,比如InstanceKlass這樣的元數(shù)據(jù)就是元對(duì)象。

      CHeapObj:這是堆空間的對(duì)象,由new/delete/free/malloc管理。其包含的內(nèi)容很多,比如Java對(duì)象、InstanceOop(后面提到的G1對(duì)象分配出來(lái)的對(duì)象)。除了Java對(duì)象,還有其他的對(duì)象也在堆中。

      JVM中為了準(zhǔn)確描述這些堆中的對(duì)象,以方便對(duì)JVM進(jìn)行優(yōu)化,所以又定義了更具體的子類(lèi)型,代碼如下所示:

      hotspot/src/share/vm/memory/allocation.hpp

      // JVM中使用的內(nèi)存類(lèi)型

      mtJavaHeap????????? = 0x00,? // Java堆

      mtClass???????????? = 0x01,? // JVM中Java類(lèi)

      mtThread??????????? = 0x02,? // JVM中線程對(duì)象

      mtThreadStack?????? = 0x03,

      mtCode????????????? = 0x04,? // JVM中生成的編譯代碼

      mtGC??????????????? = 0x05,? // GC的內(nèi)存

      mtCompiler????????? = 0x06,? // 編譯器使用的內(nèi)存

      mtInternal????????? = 0x07,? // JVM中內(nèi)部使用的類(lèi)型,不屬于上述任何類(lèi)型

      mtOther???????????? = 0x08,? // 不是由JVM使用的內(nèi)存

      mtSymbol??????????? = 0x09,? // 符號(hào)表使用的內(nèi)存

      mtNMT?????????????? = 0x0A,? // NMT使用的內(nèi)存

      mtClassShared?????? = 0x0B,? // 共享類(lèi)數(shù)據(jù)

      mtChunk???????????? = 0x0C,? // Chunk用于緩存

      mtTest????????????? = 0x0D,

      mtTracing?????????? = 0x0E,

      mtNone????????????? = 0x0F,

      《JVM G1源碼分析和調(diào)優(yōu)》 —2.5 內(nèi)存分配和管理

      這些信息描述了JVM使用內(nèi)存的情況,這一部分信息能夠幫助定位JVM本身運(yùn)行時(shí)出現(xiàn)的問(wèn)題,我們將在最后的附錄B中通過(guò)本地內(nèi)存跟蹤(Native Memory Tracking)來(lái)進(jìn)一步解讀這些信息。

      JVM

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:萬(wàn)一網(wǎng)保險(xiǎn)資料下載網(wǎng)站 ?這行字怎么刪除
      下一篇:excel表格中如何把相同的內(nèi)容進(jìn)行匯總(如何將表格內(nèi)相同內(nèi)容匯總)
      相關(guān)文章
      久久精品国产亚洲av麻豆| mm1313亚洲国产精品美女| 国产L精品国产亚洲区久久| 亚洲AV网一区二区三区| 亚洲人成自拍网站在线观看| 亚洲国产乱码最新视频| 亚洲人成电影网站| 亚洲a级片在线观看| 亚洲AV无码一区二区三区人| 亚洲香蕉久久一区二区三区四区| 亚洲va精品中文字幕| 国产精品亚洲专区在线观看| jiz zz在亚洲| 亚洲国产欧洲综合997久久| 亚洲AV无码一区二区三区网址| 亚洲精品美女久久7777777| 亚洲av无码专区青青草原| 精品国产亚洲AV麻豆| 亚洲精品乱码久久久久久不卡| 国产啪亚洲国产精品无码| 久久久亚洲精品蜜桃臀| 亚洲色欲久久久综合网| 亚洲AV无码国产精品麻豆天美 | 久久亚洲成a人片| 亚洲2022国产成人精品无码区 | 国产亚洲精品欧洲在线观看| 亚洲?V无码成人精品区日韩| 亚洲七七久久精品中文国产| 亚洲无人区一区二区三区| 亚洲AV无码乱码在线观看裸奔| 亚洲国产女人aaa毛片在线| 亚洲老熟女@TubeumTV| 亚洲色欲色欲www| 人人狠狠综合久久亚洲| 亚洲一区二区三区国产精品| 亚洲国产婷婷六月丁香| 亚洲男人都懂得羞羞网站| 亚洲国产成人91精品| 亚洲国产AV一区二区三区四区| 亚洲国产av无码精品| 亚洲狠狠婷婷综合久久久久|