Java当中jvm运行时区域新生代、老年代、永久代和Garbage Collection垃圾回收机制【杭州多测师】【杭州多测师_王sir】...
?1、本地方法棧和程序計數器 ==》偏底層一般不會接觸到
2、方法區 ==》對應為永久代
3、虛擬機棧(stack) ==》對應為棧
4、堆(heap) ==》對應里面有新生代+老年代
stack(棧內存?)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? heap(堆內存)? ? ? ? ? ? ? ? 永久代
5、棧內存
1)線程私有
2)生命周期和線程相同
3)主要存放內容
4)基本數據類型(int,char,float,double…)
5)對象的引用,指向了對象在堆內存中起始地址 ==》Object object = new Object(); ==》object就是對象的引用
6)通過-Xss參數配置? ==》假設只給棧內存分配了100MB、一個線程假設只分配1MB那么最多只能啟動100個線程、棧內存一般比堆內存要小的多 ==》一般分配為1024KB
6、堆內存示意圖
堆內存示意圖的解釋:【超級重點】1)首先一個對象被創建的時候先進入到新生代里面新生代首先會進入到Eden區域(伊甸園)里面,Eden里面存了很多的對象,那么創建object對象的時候可能會創建成千上萬次、那么隨著創建的次數越多Eden區會滿、那么滿了怎么辦呢??2)這個時候新生代會做一次掃描,掃描Eden區和S1,把里面有用的對象進行標記,然后把Eden和S1里面有用的對象全部復制放進S0里面,那么沒用的對象就會被全部清空,S0接著運行,過一段時間Eden又滿了,那么新生代再次掃描Eden和S0,對有用的對象進行復制然后放進S1區域里面,然后把Eden和S0進行清空,如此循環S0和S1輪流會有一個保持為空,survivor區就叫做存活區域有點像倉庫的概念。3)要是在掃描的時候發現有用的對象很多,要是空的S0或者S1裝不下怎么辦??==》這個時候放不下就會進行升級往老年代內存里面進行存放,老年代的內存一般都是比較大的4)那假如老年代滿了怎么辦呢?就會進行對新生代和老年代的全掃描進行全局的垃圾回收,掃描之后保留有用的對象,大部分沒用的對象其實在新生代就被垃圾回收了,根本上就進入不到老年代里面,真正能進入到S0或者S1區域的對象其實很少,因為一個對象的存活周期非常的短,Eden:S0:S1的空間比例為8:1:15)那么什么時候會進入到老年代內存里面呢?有3種情況可能【重點】1)當新生代內存不夠的時候2)當某個對象在新生代發生GC垃圾回收達到15次之后,任然還是有效的,每存活一次年齡加1,年齡為15的時候那么就可以存放到老年代內存里面了3)如果一個對象剛創建的時候特別大,比如大于5MB,因為新生代本身才1MB,這種就直接進入到老年代
堆內存?=?年輕代+老年代
年輕代?=?Eden+Survivor
Survivor?=?From?Space(s0)+To?Space(s1)
7、堆內存
1)堆內存是Jvm中空間最大的區域 ==》如果總的內存為2GB那么堆內存至少為1024MB要占上1/2
2)所有線程共享堆
3)所有的數組以及內存對象的實例都在此區域分配
4)堆內存大小通過參數進行配置
-Xmx:最大堆內存
-Xms:最小堆內存
5)堆內存構成
–?新生代:包括三塊區域,eden、from?survivor(s0)、to?survivor(s1)
–?老年代:old?gen
Object?o?=?new?Object()
其中,o存放在棧內存中,new?Object()存放在堆內存中,變量o是Object對象的引用,o上存放了Object對象占用內存的起始地址
8、永久代
永久代也叫(Method?Area)
各線程共享,主方法區要存放類信息、常量、靜態變量
如:public?static?int?a?=?10
垃圾回收行為比較少見
年輕代?=?Eden+Survivor
Survivor?=?From?Space(s0)?+?To?Space(s1)
年輕代?=?Eden+From?Space+To?Space
堆內存?=?年輕代+老年代
堆內存=Eden+From?Space+To?Space+老年代
9、Java8的新變化
Java8從Jvm中移除了PermGen,使用Metaspace(元空間)來代替永久代
Metaspace不存在Jvm中,而是存在本地內存中配置元空間初始值和最大值參數:
-XX:MetaspaceSize=64m
-XX:MaxMetaspaceSize=64m10、YoungGC和FullGC的概念(GC指的是垃圾回收?Garbage?Collection)
新生代引發的GC叫YoungGC
老年代引發的GC叫FullGC
FullGC會引起整個Jvm的用戶線程暫停,待垃圾回收完畢后,才繼續運行
11、永久代的垃圾回收
永久代回收"性價比"比較低
主要回收
1)廢棄的常量
2)無用的類
3)類的所有實例都已經被回收
4)加載該類的ClassLoader已經被回收
5)該類的Class對象沒有在任何地方被引用12、堆垃圾回收算法
1)標記-清除算法??==》分為“標記”和“清除”兩個階段,標記完成后,統一回收,缺點是:效率,標記和清除過程效率都不高,空間,標記清除后會產生大量不連續的內存碎片
2)復制算法?==》內存分為相等的兩塊,當一塊內存用完,將存活對象復制到另外一塊中,原內存一次性清理掉,復制時按照順序分配內存,無內存碎片問題,新生代使用此算法?缺點是:將內存分為兩半,利用率低
3)標記-壓縮算法?==》先對存活對象進行標記,讓所有存活對象向一邊移動,清理掉存活對象邊界外的所有內存,老年代使用此算法
4)分代收集算法?==》當代的商業虛擬機都采用“分代收集”,根據對象的存活周期的不同將內存劃分成幾塊,一般Java堆分為新生代和老年代,新生代采用復制算法,老年代采用標記-壓縮算法
垃圾收集器是內存回收算法的具體實現
沒有完美的收集器
Jvm不同的區域可以采用不同的垃圾收集器組合,主要有:
–Serial收集器(串行)
–ParNew收集器(并行)
–CMS收集器(并發)
–G1(時間優先)?==》G1全稱是Garbage?First?Garbage?Collector,在jdk1.7u4中開始支持。Java9中默認的垃圾收集器,G1的設計原則就是簡化性能優化的復雜性
目前CMS收集器和G1收集器用的是最多的==》性能測試jvm垃圾收集器G1和 CMS 的區別【杭州多測師】【杭州多測師_王sir】
13、內存溢出
1)堆內存溢出
堆內存中存在大量對象,這些對象都有被引用,當所有對象占用空間達到堆內存的最大值,?就會出現內存溢出OutOfMemory:Java?heap?space
2)永久代溢出
類的一些信息,如類名、訪問修飾符、字段描述、方法描述等,所占空間大于永久代最大值,就會出現OutOfMemoryError:PermGen?space14、內存溢出的檢測方法
Jdk/bin目錄下有很多檢測工具
圖形界面:
–Jconsole
–Jvisualvm
命令行工具
–Jstat?–gcutil?pid?1000?100
–Jmap?–histo?pid?|?head?-20
–Jmap?–heap?pid?FullGC頻率:建議單次FullGC時間<200ms
垃圾回收和CPU使用率
?內存泄露和TPS
15、jvm常用的參數
-Xms2048m,初始堆大小,建議<物理內存的1/4,默認值為物理內存的1/64
-Xmx2048m,最大堆大小,建議與-Xms保持一致,默認值為物理內存的1/4
-Xmn512m,新生代大小,建議不超過堆內存的1/2
-Xss256k,線程堆棧大小,建議256k
-XX:PermSize=256m,永久代初始值,默認值為物理內存的1/64
-XX:MaxPermSize=256m,永久代最大值,默認值為物理內存的1/4
-XX:SurvivorRatio=8:年輕帶中Eden區和Survivor區的比例,默認為8:1,即Eden(8),?From?Space(1),ToSpace(1)
-XX:+UseConcMarkSweepGC:開啟CMS垃圾回收器
總結
以上是生活随笔為你收集整理的Java当中jvm运行时区域新生代、老年代、永久代和Garbage Collection垃圾回收机制【杭州多测师】【杭州多测师_王sir】...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql ngram 中文_MySQL
- 下一篇: 关于FFmpeg VMAF 的一些记录