日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里P8架构师谈:JVM的内存分配、运行原理、回收算法机制

發布時間:2024/7/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里P8架构师谈:JVM的内存分配、运行原理、回收算法机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

不管是BAT面試,還是工作實踐中的JVM調優以及參數設置,或者內存溢出檢測等,都需要涉及到Java虛擬機的內存模型、內存分配,以及回收算法機制等,這些都是必考、必會技能。



JVM內存模型

JVM內存模型可以分為兩個部分,如下圖所示,堆和方法區是所有線程共有的而虛擬機棧,本地方法棧和程序計數器則是線程私有的。


1. 堆(Heap)

堆內存是所有線程共有的,可以分為兩個部分:年輕代和老年代。下圖中的Perm代表的是永久代,但是注意永久代并不屬于堆內存中的一部分,同時jdk1.8之后永久代也將被移除。

堆是java虛擬機所管理的內存中最大的一塊內存區域,也是被各個線程共享的內存區域,該內存區域存放了對象實例及數組(但不是所有的對象實例都在堆中)。其大小通過-Xms(最小值)和-Xmx(最大值)參數設置(最大最小值都要小于1G),前者為啟動時申請的最小內存,默認為操作系統物理內存的1/64,后者為JVM可申請的最大內存,默認為物理內存的1/4,默認當空余堆內存小于40%時,JVM會增大堆內存到-Xmx指定的大小,可通過-XX:MinHeapFreeRation=來指定這個比列;當空余堆內存大于70%時,JVM會減小堆內存的大小到-Xms指定的大小,可通過XX:MaxHeapFreeRation=來指定這個比列,當然為了避免在運行時頻繁調整Heap的大小,通常-Xms與-Xmx的值設成一樣。堆內存 = 新生代+老生代+持久代。在我們垃圾回收的時候,我們往往將堆內存分成新生代和老生代(大小比例1:2),新生代中由Eden和Survivor0,Survivor1組成,三者的比例是8:1:1,新生代的回收機制采用復制算法,在Minor GC的時候,我們都留一個存活區用來存放存活的對象,真正進行的區域是Eden+其中一個存活區,當我們的對象時長超過一定年齡時(默認15,可以通過參數設置),將會把對象放入老生代,當然大的對象會直接進入老生代。老生代采用的回收算法是標記整理算法。

2. 方法區(Method Area)

方法區也稱”永久代“,它用于存儲虛擬機加載的類信息、常量、靜態變量、是各個線程共享的內存區域。默認最小值為16MB,最大值為64MB(64位JVM由于指針膨脹,默認是85M),可以通過-XX:PermSize 和 -XX:MaxPermSize 參數限制方法區的大小。它是一片連續的堆空間,永久代的垃圾收集是和老年代(old generation)捆綁在一起的,因此無論誰滿了,都會觸發永久代和老年代的垃圾收集。不過,一個明顯的問題是,當JVM加載的類信息容量超過了參數-XX:MaxPermSize設定的值時,應用將會報OOM的錯誤。參數是通過-XX:PermSize和-XX:MaxPermSize來設定的。

3.虛擬機棧(JVM Stack)

描述的是java方法執行的內存模型:每個方法被執行的時候都會創建一個”棧幀”,用于存儲局部變量表(包括參數)、操作棧、方法出口等信息。每個方法被調用到執行完的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程聲明周期與線程相同,是線程私有的。棧幀由三部分組成:局部變量區、操作數棧、幀數據區。局部變量區被組織為以一個字長為單位、從0開始計數的數組,和局部變量區一樣,操作數棧也被組織成一個以字長為單位的數組。但和前者不同的是,它不是通過索引來訪問的,而是通過入棧和出棧來訪問的,可以看作為臨時數據的存儲區域。除了局部變量區和操作數棧外,java棧幀還需要一些數據來支持常量池解析、正常方法返回以及異常派發機制。這些數據都保存在java棧幀的幀數據區中。

局部變量表: 存放了編譯器可知的各種基本數據類型、對象引用(引用指針,并非對象本身),其中64位長度的long和double類型的數據會占用2個局部變量的空間,其余數據類型只占1個。局部變量表所需的內存空間編譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量是完全確定的,在運行期間棧幀不會改變局部變量表的大小空間。

4.本地方法棧(Native Stack)

與虛擬機?;绢愃?#xff0c;區別在于虛擬機棧為虛擬機執行的java方法服務,而本地方法棧則是為Native方法服務。(棧的空間大小遠遠小于堆)

5.程序計數器(PC Register)

最小的一塊內存區域,它的作用當前線程所執行的字節碼的行號指示器,在虛擬機的模型里,字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令分支循環、異常處理、線程恢復等基礎功能都需要依賴計數器完成。

6.直接內存

直接內存并不是虛擬機內存的一部分,也不是Java虛擬機規范中定義的內存區域。jdk1.4中新加入的NIO,引入了通道與緩沖區的IO方式,它可以調用Native方法直接分配堆外內存,這個堆外內存就是本機內存,不會影響到堆內存的大小.

JVM垃圾回收算法

1.標記清除

原理

  • 從根集合節點進行掃描,標記出所有的存活對象,最后掃描整個內存空間并清除沒有標記的對象(即死亡對象)

適用場合

  • 存活對象較多的情況下比較高效
  • 適用于年老代(即舊生代)

缺點:

  • 標記清除算法帶來的一個問題是會存在大量的空間碎片,因為回收后的空間是不連續的,這樣給大對象分配內存的時候可能會提前觸發full gc。

2.復制算法

原理:

  • 從根集合節點進行掃描,標記出所有的存活對象,并將這些存活的對象復制到一塊兒新的內存(圖中下邊的那一塊兒內存)上去,之后將原來的那一塊兒內存(圖中上邊的那一塊兒內存)全部回收掉

適用場合:

  • 存活對象較少的情況下比較高效
  • 掃描了整個空間一次(標記存活對象并復制移動)
  • 適用于年輕代(即新生代):基本上98%的對象是”朝生夕死”的,存活下來的會很少

缺點:

  • 需要一塊兒空的內存空間
  • 需要復制移動對象

3.標記整理

原理:

  • 從根集合節點進行掃描,標記出所有的存活對象,最后掃描整個內存空間并清除沒有標記的對象(即死亡對象)(可以發現前邊這些就是標記-清除算法的原理),清除完之后,將所有的存活對象左移到一起。

適用場合:

  • 用于年老代(即舊生代)

缺點:

  • 需要移動對象,若對象非常多而且標記回收后的內存非常不完整,可能移動這個動作也會耗費一定時間
  • 掃描了整個空間兩次(第一次:標記存活對象;第二次:清除沒有標記的對象)

優點:

  • 不會產生內存碎片

4.增量算法

增量算法的基本思想是,如果一次性將所有的垃圾進行處理,需要造成系統長時間的停頓,那么就可以讓垃圾收集線程和應用程序線程交替執行。每次,垃圾收集線程只收集一小片區域的內存空間,接著切換到應用程序線程。依次反復,直到垃圾收集完成。使用這種方式,由于在垃圾回收過程中,間斷性地還執行了應用程序代碼,所以能減少系統的停頓時間。但是,因為線程切換和上下文轉換的消耗,會使得垃圾回收的總體成本上升,造成系統吞吐量的下降。

垃圾回收器

1.Serial收集器

Serial收集器是最古老的收集器,它的缺點是當Serial收集器想進行垃圾回收的時候,必須暫停用戶的所有進程,即stop the world。到現在為止,它依然是虛擬機運行在client模式下的默認新生代收集器,與其他收集器相比,對于限定在單個CPU的運行環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾回收自然可以獲得最高的單線程收集效率。

2.ParNew收集器

ParNew收集器是Serial收集器新生代的多線程實現,注意在進行垃圾回收的時候依然會stop the world,只是相比較Serial收集器而言它會運行多條進程進行垃圾回收。

ParNew收集器在單CPU的環境中絕對不會有比Serial收集器更好的效果,甚至由于存在線程交互的開銷,該收集器在通過超線程技術實現的兩個CPU的環境中都不能百分之百的保證能超越Serial收集器。當然,隨著可以使用的CPU的數量增加,它對于GC時系統資源的利用還是很有好處的。它默認開啟的收集線程數與CPU的數量相同,在CPU非常多(譬如32個,現在CPU動輒4核加超線程,服務器超過32個邏輯CPU的情況越來越多了)的環境下,可以使用-XX:ParallelGCThreads參數來限制垃圾收集的線程數。

3.Parallel Scavenge收集器

Parallel是采用復制算法的多線程新生代垃圾回收器,似乎和ParNew收集器有很多的相似的地方。但是Parallel Scanvenge收集器的一個特點是它所關注的目標是吞吐量(Throughput)。所謂吞吐量就是CPU用于運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量=運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)。停頓時間越短就越適合需要與用戶交互的程序,良好的響應速度能夠提升用戶的體驗;而高吞吐量則可以最高效率地利用CPU時間,盡快地完成程序的運算任務,主要適合在后臺運算而不需要太多交互的任務。

4.CMS收集器

CMS(Concurrent Mark Swep)收集器是一個比較重要的回收器,現在應用非常廣泛,我們重點來看一下,CMS一種獲取最短回收停頓時間為目標的收集器,這使得它很適合用于和用戶交互的業務。從名字(Mark Swep)就可以看出,CMS收集器是基于標記清除算法實現的。它的收集過程分為四個步驟:

  • 初始標記(initial mark)
  • 并發標記(concurrent mark)
  • 重新標記(remark)
  • 并發清除(concurrent sweep)
  • 注意初始標記和重新標記還是會stop the world,但是在耗費時間更長的并發標記和并發清除兩個階段都可以和用戶進程同時工作。

    不過由于CMS收集器是基于標記清除算法實現的,會導致有大量的空間碎片產生,在為大對象分配內存的時候,往往會出現老年代還有很大的空間剩余,但是無法找到足夠大的連續空間來分配當前對象,不得不提前開啟一次Full GC。

    為了解決這個問題,CMS收集器默認提供了一個-XX:+UseCMSCompactAtFullCollection收集開關參數(默認就是開啟的),用于在CMS收集器進行FullGC完開啟內存碎片的合并整理過程,內存整理的過程是無法并發的,這樣內存碎片問題倒是沒有了,不過停頓時間不得不變長。虛擬機設計者還提供了另外一個參數-XX:CMSFullGCsBeforeCompaction參數用于設置執行多少次不壓縮的FULL GC后跟著來一次帶壓縮的(默認值為0,表示每次進入Full GC時都進行碎片整理)。

    不幸的是,它作為老年代的收集器,卻無法與jdk1.4中已經存在的新生代收集器Parallel Scavenge配合工作,所以在jdk1.5中使用cms來收集老年代的時候,新生代只能選擇ParNew或Serial收集器中的一個。ParNew收集器是使用-XX:+UseConcMarkSweepGC選項啟用CMS收集器之后的默認新生代收集器,也可以使用-XX:+UseParNewGC選項來強制指定它。

    5.G1收集器

    G1收集器是一款面向服務端應用的垃圾收集器。HotSpot團隊賦予它的使命是在未來替換掉JDK1.5中發布的CMS收集器。與其他GC收集器相比,G1具備如下特點:

  • 并行與并發:G1能更充分的利用CPU,多核環境下的硬件優勢來縮短stop the world的停頓時間。
  • 分代收集:和其他收集器一樣,分代的概念在G1中依然存在,不過G1不需要其他的垃圾回收器的配合就可以獨自管理整個GC堆。
  • 空間整合:G1收集器有利于程序長時間運行,分配大對象時不會無法得到連續的空間而提前觸發一次GC。
  • 可預測的非停頓:這是G1相對于CMS的另一大優勢,降低停頓時間是G1和CMS共同的關注點,能讓使用者明確指定在一個長度為M毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒。
  • 在使用G1收集器時,Java堆的內存布局和其他收集器有很大的差別,它將這個Java堆分為多個大小相等的獨立區域,雖然還保留新生代和老年代的概念,但是新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續)的集合。

    雖然G1看起來有很多優點,實際上CMS還是主流。

    與GC相關的常用參數

    除了上面提及的一些參數,下面補充一些和GC相關的常用參數:

    • -Xmx: 設置堆內存的最大值。
    • -Xms: 設置堆內存的初始值。
    • -Xmn: 設置新生代的大小。
    • -Xss: 設置棧的大小。
    • -PretenureSizeThreshold: 直接晉升到老年代的對象大小,設置這個參數后,大于這個參數的對象將直接在老年代分配。
    • -MaxTenuringThrehold: 晉升到老年代的對象年齡。每個對象在堅持過一次Minor GC之后,年齡就會加1,當超過這個參數值時就進入老年代。
    • -UseAdaptiveSizePolicy: 在這種模式下,新生代的大小、eden 和 survivor 的比例、晉升老年代的對象年齡等參數會被自動調整,以達到在堆大小、吞吐量和停頓時間之間的平衡點。在手工調優比較困難的場合,可以直接使用這種自適應的方式,僅指定虛擬機的最大堆、目標的吞吐量 (GCTimeRatio) 和停頓時間 (MaxGCPauseMills),讓虛擬機自己完成調優工作。
    • -SurvivorRattio: 新生代Eden區域與Survivor區域的容量比值,默認為8,代表Eden: Suvivor= 8: 1。
    • -XX:ParallelGCThreads:設置用于垃圾回收的線程數。通常情況下可以和 CPU 數量相等。但在 CPU 數量比較多的情況下,設置相對較小的數值也是合理的。
    • -XX:MaxGCPauseMills:設置最大垃圾收集停頓時間。它的值是一個大于 0 的整數。收集器在工作時,會調整 Java 堆大小或者其他一些參數,盡可能地把停頓時間控制在 MaxGCPauseMills 以內。
    • -XX:GCTimeRatio:設置吞吐量大小,它的值是一個 0-100 之間的整數。假設 GCTimeRatio 的值為 n,那么系統將花費不超過 1/(1+n) 的時間用于垃圾收集。

    你可能也喜歡:

  • Java必考題目之JVM面試題目和答案
  • 直通BAT必考題系列:深入詳解JVM內存模型與JVM參數詳細配置
  • 直通BAT必考題系列:JVM的4種垃圾回收算法、垃圾回收機制與總結
  • 直通BAT必考題系列:7種JVM垃圾收集器特點,優劣勢、及使用場景
  • 4大JVM性能分析工具詳解,及內存泄漏分析方案
  • 直通BAT必考題系列:深入剖析JVM之G1收集器、及回收流程、與推薦用例

  • 總結

    以上是生活随笔為你收集整理的阿里P8架构师谈:JVM的内存分配、运行原理、回收算法机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 夜夜欢天天干 | 亚洲精品97久久中文字幕 | 国产第一色 | 爱插网| 上海女子图鉴 | 黄色无遮挡网站 | 亚洲一区二区动漫 | 特级特黄aaaa免费看 | 欧美一级一级 | 久久婷婷国产麻豆91 | 日本三级韩国三级三级a级按摩 | 日本免费网站在线观看 | 欧美激情首页 | 欧美精品一卡 | 欧洲亚洲激情 | 爱涩av | 狠狠人妻久久久久久 | 成人h动漫精品一区 | 奴性白洁会所调教 | 色老头av| jjzz日本女人 | 伊人黄色片 | 色播综合| 欧美日韩亚洲色图 | 91色噜噜| 在线h片 | 国产1区在线 | 色一情一区二区三区四区 | 久久久久久久久久久久久久久久久久久 | 久青草资源福利视频 | av一区二区在线播放 | 91精品国产色综合久久不卡蜜臀 | 亚州福利 | 国产激情小视频 | 4虎最新网址| 中文字幕一区二区人妻视频 | 一级一级黄色片 | 中文字幕第三页 | 午夜激情av在线 | 91综合精品| 1级av| 私人av | 美女福利影院 | 草草久久久无码国产专区 | 中文字幕一区电影 | 国产97色在线 | 日韩 | 黄色一级录像片 | 精品视频一区二区 | 亚洲免费视频一区 | juliaann办公室丝袜大战 | 不卡在线一区二区 | 99久久网站| 五月天激情社区 | 国产91小视频 | 亚洲成色网 | 台湾av在线播放 | 日韩香蕉网 | 久久手机视频 | 日韩欧美视频 | 国产二级一片内射视频播放 | 午夜伦伦电影理论片费看 | 久久久在线观看 | 日韩一级伦理片 | 激情草逼 | 亚洲精品成人影视 | a级片在线免费观看 | 综合色av | 少妇人妻偷人精品无码视频新浪 | 久久国产精品综合 | 国产香蕉精品 | 久久综合社区 | 91av免费| 国产一区二区三区四区在线观看 | www.成人在线| 国产卡一卡二卡三无线乱码新区 | 久久久久久人妻一区二区三区 | 欧洲黄色网 | 一区二区三区国产精品视频 | 天天综合网入口 | av无遮挡| 久久午夜精品人妻一区二区三区 | 五月婷婷六月激情 | 精品亚洲一区二区三区四区五区 | 亚洲熟女乱色一区二区三区久久久 | 97精品人人a片免费看 | 国产激情视频一区二区三区 | 疯狂做受xxxx高潮人妖 | 久久精品视频8 | 免费观看成人 | 先锋av在线资源 | 国内91视频| 国产精品久久午夜夜伦鲁鲁 | 欧美影院一区 | 黄色片网站免费 | 无码播放一区二区三区 | 深夜小视频在线观看 | 亚洲精品国产精品乱码在线观看 | 成人免费看aa片 | 人人狠狠|