摘要:年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對象。年老代在年輕代中經(jīng)歷了次垃圾回收后仍然存活的對象,就會被放到年老代中。什么情況下觸發(fā)垃圾回收由于對象進(jìn)行了分代處理,因此垃圾回收區(qū)域時(shí)間也不一樣。
[TOC]
與C/C++相比,java語言不需要程序員直接控制內(nèi)存回收,java程序的內(nèi)存分配和回收都是由JRE在后臺自動進(jìn)行,JRE會負(fù)責(zé)回收那些不再使用的內(nèi)存,這種機(jī)制被稱為垃圾回收機(jī)制(Garbage Collection,GC):
主要負(fù)責(zé)兩件事情發(fā)現(xiàn)無用的對象
回收被無用對象占用的內(nèi)存空間,使之再次被程序使用(一般是在CPU空閑或者內(nèi)存不足時(shí))。
事實(shí)上,除了釋放沒用對象占用的內(nèi)存空間外,垃圾回收也可以清除內(nèi)存紀(jì)錄碎片(由于創(chuàng)建對象和垃圾回收器釋放丟棄對象所占的內(nèi)存空間)特點(diǎn)
垃圾回收機(jī)制的工作目標(biāo)是回收無用對象的內(nèi)存空間,==這些內(nèi)存空間都是jvm堆內(nèi)存(運(yùn)行時(shí)數(shù)據(jù)區(qū),用以保存類的實(shí)例,即對象)里的內(nèi)存空間==,不包含其它物力資源,比如數(shù)據(jù)庫連接、磁盤I/O等;
Java語言沒有顯式的提供分配內(nèi)存和刪除內(nèi)存的方法,一些開發(fā)人員將引用對象設(shè)置為null或者調(diào)用System.gc()或者Runtime.getRuntime.gc()來釋放內(nèi)存(==后兩種方法僅是建議,慎重使用==);
垃圾回收不可預(yù)知,不同的jvm采用不同的垃圾回收機(jī)制和算法,有可能定時(shí)發(fā)生,有可能CPU空閑時(shí)發(fā)生,也有可能內(nèi)存耗盡時(shí)發(fā)生
分代垃圾回收 年輕代(Young Generation)所有新生成的對象首先都是放在年輕代的。
年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對象。
年輕代分三個(gè)區(qū)。一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)(一般而言)。大部分對象在Eden區(qū)中生成。
當(dāng)Eden區(qū)滿時(shí),還存活的對象將被復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè))==(YGC,年輕代垃圾回收)==,當(dāng)這個(gè)Survivor區(qū)滿時(shí),此區(qū)的存活對象將被復(fù)制到另外一個(gè)Survivor區(qū),當(dāng)這個(gè)Survivor區(qū)也滿了的時(shí)候,從第一個(gè)Survivor區(qū)復(fù)制過來的并且此時(shí)還存活的對象,將被復(fù)制“年老區(qū)(Tenured)”。
需要注意,Survivor的兩個(gè)區(qū)是對稱的,沒先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden復(fù)制過來 對象,和從前一個(gè)Survivor復(fù)制過來的對象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過來的對象。而且,Survivor區(qū)總有一個(gè)是空的。
同時(shí),根據(jù)程序需要,Survivor區(qū)是可以配置為多個(gè)的(多于兩個(gè)),這樣可以增加對象在年輕代中的存在時(shí)間,減少被放到年老代的可能。年老代(Old Generation)
在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對象,就會被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長的對象。
持久代(Permanent Generation)用于存放靜態(tài)文件,如今Java類、方法等。持久代對垃圾回收沒有顯著影響,但是有些應(yīng)用可能動態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新增的類。持久代大小通過-XX:MaxPermSize=
由于對象進(jìn)行了分代處理,因此垃圾回收區(qū)域、時(shí)間也不一樣。GC有兩種類型:Minor GC和Full GC。
Minor GC一般情況下,當(dāng)新對象生成,并且在Eden申請空間失敗時(shí),就會觸發(fā)Minor GC,對Eden區(qū)域進(jìn)行GC,清除非存活對象,并且把尚且存活的對象移動到Survivor區(qū)。
然后整理Survivor的兩個(gè)區(qū)。
這種方式的GC是對年輕代的Eden區(qū)進(jìn)行,不會影響到年老代。因?yàn)榇蟛糠謱ο蠖际菑腅den區(qū)開始的,同時(shí)Eden區(qū)不會分配的很大,所以Eden區(qū)的GC會頻繁進(jìn)行。因而,一般在這里需要使用速度快、效率高的算法,使Eden去能盡快空閑出來。
Full GC對整個(gè)堆進(jìn)行整理,包括Young、Tenured和Perm。Full GC因?yàn)樾枰獙φ麄€(gè)對進(jìn)行回收,所以比Minor GC要慢,因此應(yīng)該盡可能減少Full GC的次數(shù)。
在對JVM調(diào)優(yōu)的過程中,很大一部分工作就是對于Full GC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:
年老代(Tenured)被寫滿
持久代(Perm)被寫滿
System.gc()被顯示調(diào)用
上一次GC之后Heap的各域分配策略動態(tài)變化
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/72261.html
摘要:什么是線程餓死,什么是活鎖多線程中的忙循環(huán)是什么變量是什么變量和變量有什么不同類型變量提供什么保證能使得一個(gè)非原子操作變成原子操作嗎 JVM專題 showImg(https://segmentfault.com/img/remote/1460000019943435); (面試題+答案領(lǐng)取方式見個(gè)人主頁) Java 類加載過程? 描述一下 JVM 加載 Class 文件的原理機(jī)制? ...
摘要:內(nèi)存回收此時(shí),局部變量就沒有存在的必要了,因此可以釋放它們的內(nèi)存以供將來使用。局部變量會在它們離開執(zhí)行環(huán)境時(shí)自動被解除引用,如下面這個(gè)例子所示手工解除的引用由于局部變量在函數(shù)執(zhí)行完畢后就離開了其執(zhí)行環(huán)境,因此無需我們顯式地去為它解除引用。 JavaScript 具有自動垃圾收集機(jī)制(GC:Garbage Collecation),也就是說,執(zhí)行環(huán)境會負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。而...
摘要:不能滿足被回收的條件,盡管調(diào)用也還是不能得到回收這就造成了內(nèi)存泄漏。種解決單例中的內(nèi)存泄漏將引用置為銷毀監(jiān)聽使用弱引用將監(jiān)聽器放入弱引用中從弱引用中取出回調(diào)通過第七小點(diǎn)就能完美的解決單例中回調(diào)引起的內(nèi)存泄漏。我們?yōu)槭裁匆獌?yōu)化內(nèi)存 showImg(https://user-gold-cdn.xitu.io/2019/5/12/16aac64e31d8c501); 在 Android 中我們寫的...
摘要:并發(fā)標(biāo)記清除垃圾回收器,使用多個(gè)線程來掃描堆內(nèi)存并標(biāo)記可被清除的對象,然后清除標(biāo)記的對象。垃圾回收器應(yīng)用于大的堆內(nèi)存空間。它將堆內(nèi)存空間劃分為不同的區(qū)域,對各個(gè)區(qū)域并行地做回收工作。它會通過把重復(fù)的值移動到同一個(gè)數(shù)組來優(yōu)化堆內(nèi)存占用。 本文非原創(chuàng),翻譯自Types of Java Garbage Collectors在Java中為對象分配和釋放內(nèi)存空間都是由垃圾回收線程自動執(zhí)行完成的。...
閱讀 3206·2021-10-13 09:40
閱讀 4133·2021-09-22 15:51
閱讀 1601·2021-09-22 15:48
閱讀 1157·2021-09-06 15:00
閱讀 1956·2019-08-30 15:43
閱讀 2453·2019-08-29 18:35
閱讀 1791·2019-08-29 16:18
閱讀 3714·2019-08-29 12:49