JAVA內存與GC總結

首先列出內存結構

靜態區

  • permspace(jdk<=1.7)
    `線程共享,存儲常量、靜態變量、加載的類信息,由參數指定大小
  • metaspace(jdk>=1.8)
    線程共享,替代permspace,常量信息移動到堆當中,虛擬機維護

棧區

  • JAVA棧
    線程私有,當前調用棧的上下文、localcar、方法的成員變量等
  • 本地方法棧(native)
    線程私有,虛擬機或jni提供的本地方法的調用上下文
  • 程序計數器
    線程私有,存儲當前線程行號、分支、循環、跳轉、異常信息、同時存儲線程狀態切換等信息

堆區

  • JAVA堆
    共享,存儲java對象,等,分爲多個空間

非堆區

  • 非堆
    程序自己控制的內存區域,可以由NIO的DiretByteBuffer或UNSAFE方法分配

JAVA垃圾回收原理

JAVA中由垃圾回收器負責的空間主要爲堆與靜態區,靜態區在老FGC時均會被整理,且其也會觸發FGC不再闡述

    堆的結構

堆分爲兩個部分,新生代與老年代

  • 新生代:JAVA對象在創建之初都存在於新生代(大對象除外),經過多次GC仍然存在的對象會被移動到老年代,由空間的連續性考慮,新生代的GC比較頻繁,使用只複製法整理空間效率更高,但消耗更多的內存。所以堆在內部又再次劃分爲兩個空間類型,Eden與Survivor,其中Survior內部再次劃分爲兩個空間且一個時間只會使用其中一個,兩個Survior空間在每次GC時交換身份。當GC被觸發時,Eden中存活下來的對象將會移動到正在使用的Survivor當中,當此Survivor滿時,則對其進行整理,仍然存活的對象會被複制到另外一個Survivor當中。
  • 老年代:一個對象在Survivor中多次存活(次數可配),則會被移動到老年代。考慮到空間的使用,與被觸發GC次數較少,使用內部整理的方式來處理連續性,降低了內存開銷與複雜度。
    堆的垃圾收集算法
1)複製算法:*只適用於新生代。內存拆分爲兩份,申請內存時只返回正在使用的那部分,這個空間稱作Eden,另外一個稱爲Survivor,標記回收的對象後,將不需要回收的對象複製到Survivor空間。算法實現有:Serial(單線程);ParNew(多線程收集器);ParallelScavenge(吞吐量優化算法,自動調節策略降低停頓)
2)標記清除算法:*只適用於老年代。首先根據引用計數標記需要回收的對象,隨後統一回收。會產生較多碎片,但性能最高。算法實現有:ConcurrentMarkSweep(CMS,併發清除算法,分三階段執行,僅前兩個階段停頓,停頓最小,產生的碎片智能整理(需要時),也可以配置整理)
3)標記整理算法:*只適用於老年代,申請內存時,只採用一個方向的分配方式,則內存的另一端將不會被使用。之後在將不需要回收的對象向此端複製。算法實現有:SerialOld(單線程),ParallelOld(多線程)
4)分區整理算法:新型的內存結構,不再適用上文中的內存結構,它將JAVA堆內存分割爲多個區域,每個區域都可以成爲新生代或老年代的身份,當空間不足時便對這些分區分個進行整理,存活的對象複製到新的分區中,這樣每次GC都不用對整個空間做整理,停頓非常少。算法實現:GarbageFirst(G1)

GC分析

JAVA當中的GC分爲兩種,Minor GC / Major GC(FGC)
…待整理

內存使用優化思路

    合理使用非堆
非堆的性能優化點在於不在垃圾回收器的工作內容之中,合理使用降低垃圾回收器的負擔,同時,非堆也優化了IO的操作,減少JAVA虛擬機內存向系統內存拷貝的環節,優化性能
    集合的初始化大小
儘量指定集合的初始化大小,降低擴容次數

待整理。。。。。

GC優化思路

待整理。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章