wordpress采集網(wǎng)頁文章安卓優(yōu)化大師app下載
目錄
- Java對象內(nèi)存布局
- markWord 數(shù)據(jù)結(jié)構(gòu)
- JDK1.8 JVM 內(nèi)存結(jié)構(gòu)
- JDK1.8堆內(nèi)存結(jié)構(gòu)
- GC垃圾回收
- 如何發(fā)現(xiàn)垃圾
- 如何回收垃圾
- JVM調(diào)優(yōu)參數(shù)
Java對象內(nèi)存布局
markWord 數(shù)據(jù)結(jié)構(gòu)
JDK1.8 JVM 內(nèi)存結(jié)構(gòu)
-
程序計數(shù)器:
線程私有,記錄代碼執(zhí)行的位置. -
Java虛擬機棧:
線程私有,每個線程都有一個自己的Java虛擬機棧 ,默認大小是1M -
本地方法棧:
線程私有,每個線程都有一個自己的本地方法棧,Java虛擬機棧加載的是普通方法,本地方法加載的是native
修飾的方法.native
:表示這個方法不是java原生的,是由C或C++實現(xiàn)的 -
堆:
線程共享,用于存放對象,new的對象都存儲在這個區(qū)域 -
元空間:
線程共享,存儲class信息,類的信息,方法的定義,靜態(tài)變量,常量池 等
- 堆和元空間是線程共享的,在Java虛擬機中只有一個堆、一個元空間,并在JVM啟動的時候就創(chuàng)建,JVM停止才銷毀。
- 棧、本地方法棧、程序計數(shù)器是每個線程私有的,隨著線程的創(chuàng)建而創(chuàng)建,隨著線程的結(jié)束而死亡。
每個存儲位置會產(chǎn)生的異常:
JDK1.8堆內(nèi)存結(jié)構(gòu)
- 年輕代:Eden+S0+S1, S0和S1大小相等, 新創(chuàng)建的對象都在年輕代
- 老年代:經(jīng)過年輕代 多次垃圾回收存活下來的對象存在年老代中.
GC垃圾回收
JVM的垃圾回收動作可以大致分為兩大步:
- 如何發(fā)現(xiàn)垃圾
- 如何回收垃圾
線程私有的不存在垃圾回收,只有線程共享的才會存在垃圾回收,所以堆中存在垃圾回收.
如何發(fā)現(xiàn)垃圾
常見的用于「發(fā)現(xiàn)垃圾」的算法有兩種,引用計數(shù)算法 和 根搜索算法。
-
引用計數(shù)算法
堆中的對象每被引用一次,則計數(shù)器加1,每減少一個引用就減1,當(dāng)對象的引用計數(shù)器為0時可以被當(dāng)作垃圾收集。- 優(yōu)點:快。
- 缺點:無法檢測出循環(huán)引用。如兩個對象互相引用時,他們的引用計數(shù)永遠不可能為0。
-
根搜索算法(也叫根可達性分析)
根搜索算法是把所有的引用關(guān)系 看作一張圖,從根節(jié)點(GCRoot)開始遍歷,找出被根節(jié)點引用的節(jié)點,對于沒有被根節(jié)點指向的節(jié)點,即可以當(dāng)作垃圾。- Java中可作為GCRoot的對象有:
- java虛擬機棧中引用的對象
- 本地方法棧引用的對象
- 元空間中靜態(tài)屬性引用的對象
- 元空間中常量引用的對象
- Java中可作為GCRoot的對象有:
如何回收垃圾
Java中用于「回收垃圾」的常見算法有4種:
-
標(biāo)記-清除算法(markandsweep)
首先標(biāo)記出所有需要回收的對象,在標(biāo)記完成之后統(tǒng)一回收掉所有被標(biāo)記的對象。缺點: 標(biāo)記清除之后會產(chǎn)生大量的不連續(xù)的內(nèi)存碎片
-
標(biāo)記-整理算法
首先標(biāo)記出所有需要回收的對象,讓所有存活的對象移動到另一個位置,在移動過程中清理掉可回收的對象,這個過程叫做整理。優(yōu)點:內(nèi)存被整理后不會產(chǎn)生大量不連續(xù)內(nèi)存碎片
缺點:耗時耗力 -
復(fù)制算法(copying)
將空間分成大小相等的兩塊,每次只使用其中一塊,當(dāng)這塊內(nèi)存使用完了,就將存活的對象復(fù)制到另一塊內(nèi)存上去,然后把使用過的內(nèi)存空間一次清理掉。缺點:可使用的內(nèi)存只有原來一半。在某一個時刻點,總有一個 S 是空的,可能是S0 也可能是S1.。
-
分代收集算法(generation)
當(dāng)前主流JVM都采用分代收集(GenerationalCollection)算法,這種算法會根據(jù)對象存活周期的不同將內(nèi)存劃分為年輕代、年老代,不同生命周期的對象可以采取不同 的回收算法,以便提高回收效率。-
年輕代(YoungGeneration)
- 所有新生成的對象首先都是放在年輕代的。
- 新生代內(nèi)存按照
8:1:1
的比例分為一個eden區(qū)和兩個Survivor(s0,s1)區(qū)。大部分對象在Eden區(qū)中生成。
回收流程:
回收時先將eden區(qū)存活的對象復(fù)制到一個s0區(qū),然后清空eden區(qū),當(dāng)這個s區(qū),也存放滿了時,則將eden區(qū)和s0區(qū)存活對象復(fù)制到另一個s1區(qū),然后清空eden和這個s0區(qū),此時s0區(qū)是空的,然后將s0區(qū)和s1區(qū)交換,即保持s1區(qū)為空,如此往復(fù).-
特殊情況:當(dāng)一個大對象不足于存放到eden區(qū)時,就將存活對象直接存放到老年代。若是老年代也滿了就會觸發(fā)一次
FullGC
,也就是新生代、老年代都進行回收。 -
新生代發(fā)生的GC也叫做MinorGC,MinorGC發(fā)生頻率比較高
-
年老代(OldGeneration)
-
在年輕代中經(jīng)歷了 N次垃圾回收后仍然存活的對象,就會被放到年老代中。因此,可以認為年老代中存放的都是一些生命周期較長的對象。默認是15次,且最大15次。
-
內(nèi)存比新生代也大很多(大概是2倍),當(dāng)老年代內(nèi)存滿時觸發(fā)FullGC,
FullGC發(fā)生頻率比較低,老年代對象存活時間比較長,存活率比較高。
-
-
元空間-持久代(PermanentGeneration)
用于存放靜態(tài)文件,如Java類、方法等。持久代對垃圾回收沒有顯著影響。
-
JVM調(diào)優(yōu)參數(shù)
這里只給出一些常見的性能調(diào)優(yōu)的參數(shù)及其代表的含義。
-Xms8g
: 設(shè)置JVM中堆初始堆大小為8g。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。
-Xmx8g
: 設(shè)置JVM中堆最大可用內(nèi)存為8g。
-Xmn4g
: 設(shè)置年輕代大小為4G。
-XX:NewRatio=2 設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值。設(shè)置為2,則年輕 代與年老代所占比值為1:2,年輕代占整個堆棧的1/3。
-XX:SurvivorRatio=8 ,所以默認值 Eden:S0:S1=8:1:1。
-Xss1m:設(shè)置每個線程的棧大小
-XX:MaxMetaspaceSize=128m
: 設(shè)置元空間最大為為128m ,
-XX:MetaspaceSize=128m
用于設(shè)置元空間的初始大小, 默認值約21M
-XX:MaxTenuringThreshold=15:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進入年老代。 對于年老代比較多的應(yīng)用,可以提高效率。最大不超過15。