更新時間:2021-08-02 16:58:13 來源:動力節點 瀏覽1309次
Java堆內存管理是影響性能的主要因素之一。
堆內存溢出是Java項目非常常見的故障,在解決該問題之前,必須先了解下Java堆內存是怎么工作的。
先看下JAVA堆內存是如何劃分的,如圖:
在JDK1.8版本廢棄了永久代,替代的是元空間(MetaSpace),元空間與永久代上類似,都是方法區的實現,他們最大區別是:元空間并不在JVM中,而是使用本地內存。
元空間有兩個參數:
移除永久代原因:為融合HotSpot JVM與JRockit VM(新JVM技術)而做出的改變,因為JRockit沒有永久代。
有了元空間就不再會出現永久代OOM問題了
新生成的對象首先放到年輕代Eden區,當Eden空間滿了,觸發Minor GC,存活下來的對象移動到Survivor0區,Survivor0區滿后觸發執行Minor GC,Survivor0區存活對象移動到Survivor1區,這樣保證了一段時間內總有一個survivor區為空。經過多次Minor GC仍然存活的對象移動到老年代。
老年代存儲長期存活的對象,占滿時會觸發Major GC=Full GC,GC期間會停止所有線程等待GC完成,所以對相應要求高的應用盡量減少發生Major GC,避免響應超時。
所有GC都會停止所有應用進程
將對象根據存活概率進行分類,對存活時間長的對象,放到固定區,從而減少掃描垃圾時間及GC頻率。針對分類進行不同的垃圾回收算法,對算法揚長避短。
主要為了解決碎片化。如果內存碎片化嚴重,也就是兩個對象占用不連續的內存,已有的連續內存不夠新對象存放,就會觸發GC。
參數 | 描述 |
-Xms | 堆內存初始大小,單位m、g |
-Xmx(MaxHeapSize) | 堆內存最大允許大小,一般不要大于物理內存的80% |
-XX:PermSize | 非堆內存初始大小,一般應用設置初始化200m,最大1024m就夠了 |
-XX:MaxPermSize | 非堆內存最大允許大小 |
-XX:NewSize(-Xns) | 年輕代內存初始大小 |
-XX:MaxNewSize(-Xmn) | 年輕代內存最大允許大小,也可以縮寫 |
-XX:SurvivorRatio=8 | 年輕代中Eden區與Survivor區的容量比例值,默認為8,即8:1 |
-Xss | 堆棧內存大小 |
紅色是標記的非活動對象,綠色是活動對象。
GC分為兩個階段,標記和清除。首先標記所有可回收的對象,在標記完成后統一回收所有被標記的對象。同時會產生不連續的內存碎片。碎片過多會導致以后程序運行時需要分配較大對象時,無法找到足夠的連續內存,而不得已再次觸發GC。
將內存按容量劃分為兩塊,每次只使用其中一塊。當這一塊內存用完了,就將存活的對象復制到另一塊上,然后再把已使用的內存空間一次清理掉。這樣使得每次都是對半個內存區回收,也不用考慮內存碎片問題,簡單高效。缺點需要兩倍的內存空間。
也分為兩個階段,首先標記可回收的對象,再將存活的對象都向一端移動,然后清理掉邊界以外的內存。此方法避免標記-清除算法的碎片問題,同時也避免了復制算法的空間問題。
一般年輕代中執行GC后,會有少量的對象存活,就會選用復制算法,只要付出少量的存活對象復制成本就可以完成收集。
而老年代中因為對象存活率高,沒有額外過多內存空間分配,就需要使用標記-清理或者標記-整理算法來進行回收。
以上就是動力節點小編介紹的"JVM堆內存",希望對大家有幫助,想了解更多可查看Java虛擬機視頻。動力節點在線學習教程,針對沒有任何Java基礎的讀者學習,讓你從入門到精通,主要介紹了一些Java基礎的核心知識,讓同學們更好更方便的學習和了解Java編程,感興趣的同學可以關注一下。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習