為什么先說JVM堆?
JVM的堆是Java對(duì)象的活動(dòng)空間览爵,程序中的類的對(duì)象從中分配空間置鼻,其存儲(chǔ)著正在運(yùn)行著的應(yīng)用程序用到的所有對(duì)象。這些對(duì)象的建立方式就是那些new一類的操作蜓竹,當(dāng)對(duì)象無用后箕母,是GC來負(fù)責(zé)這個(gè)無用的對(duì)象(地球人都知道)储藐。
GC的工作目的很明確:
在堆中,找到已經(jīng)無用的對(duì)象嘶是,并把這些對(duì)象占用的空間收回使其可以重新利用.大多數(shù)垃圾回收的 算法思路都是一致的:把所有對(duì)象組成一個(gè)集合钙勃,或可以理解為樹狀結(jié)構(gòu),從樹根開始找聂喇,只要可以找到的都是活動(dòng)對(duì)象辖源,如果找不到,這個(gè)對(duì)象就是凋零的昨日黃花希太,應(yīng)該被回收了克饶。
JAVA 垃圾回收器的主要任務(wù)是:
1、分配內(nèi)存
2誊辉、確保被引用對(duì)象的內(nèi)存不被錯(cuò)誤地回收
3矾湃、回收不再被引用的對(duì)象的內(nèi)存空間
GC算法
垃圾搜集的算法主要有三種,分別是標(biāo)記-清除算法堕澄、復(fù)制算法邀跃、標(biāo)記-整理算法
1、標(biāo)記-清除算法
這種垃圾回收一次回收分為兩個(gè)階段:標(biāo)記蛙紫、清除坞嘀。首先標(biāo)記所有需要回收的對(duì)象,在標(biāo)記完成后回收所有被標(biāo)記的對(duì)象惊来。這種回收算法會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片丽涩,當(dāng)要頻繁分配一個(gè)大對(duì)象時(shí),jvm在新生代中找不到足夠大的連續(xù)的內(nèi)存塊裁蚁,會(huì)導(dǎo)致jvm頻繁進(jìn)行內(nèi)存回收(目前有機(jī)制矢渊,對(duì)大對(duì)象,直接分配到老年代中)
2枉证、 復(fù)制算法
這種算法會(huì)將內(nèi)存劃分為兩個(gè)相等的塊矮男,每次只使用其中一塊。當(dāng)這塊內(nèi)存不夠使用時(shí)室谚,就將還存活的對(duì)象復(fù)制到另一塊內(nèi)存中毡鉴,然后把這塊內(nèi)存一次清理掉。這樣做的效率比較高秒赤,也避免了內(nèi)存碎片猪瞬。但是這樣內(nèi)存的可使用空間減半,是個(gè)不小的損失入篮。
3陈瘦、 標(biāo)記-整理算法
標(biāo)記/整理算法與標(biāo)記/清除算法非常相似,它也是分為兩個(gè)階段:標(biāo)記和整理潮售。
(1)標(biāo)記:它的第一個(gè)階段與標(biāo)記/清除算法是一模一樣的痊项,均是遍歷GC Roots锅风,然后將存活的對(duì)象標(biāo)記。
(2)整理:移動(dòng)所有存活的對(duì)象鞍泉,且按照內(nèi)存地址次序依次排列皱埠,然后將末端內(nèi)存地址以后的內(nèi)存全部回收。因此咖驮,第二階段才稱為整理階段边器。
缺點(diǎn)就是效率也不高,不僅要標(biāo)記所有存活對(duì)象游沿,還要整理所有存活對(duì)象的引用地址饰抒。從效率上來說肮砾,標(biāo)記/整理算法要低于復(fù)制算法
GC的兩種判定方法:引用計(jì)數(shù) 引用鏈诀黍。
引用計(jì)數(shù) 給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每過一個(gè)引用計(jì)數(shù)器值就+1仗处,少一個(gè)引用就-1眯勾。當(dāng)它的引用變?yōu)?時(shí),該對(duì)象就不能再被使用婆誓。它的實(shí)現(xiàn)簡(jiǎn)單吃环,但是不能解決互相循環(huán)引用的問題。
內(nèi)存泄漏和內(nèi)存溢出的差別
內(nèi)存泄露是指分配出去的內(nèi)存沒有被回收回來洋幻,由于失去了對(duì)該內(nèi)存區(qū)域的控制郁轻,因而造成了資源的浪費(fèi)。Java中一般不會(huì)產(chǎn)生內(nèi)存泄露文留,因?yàn)橛欣厥掌髯詣?dòng)回收垃圾好唯,但這也不絕對(duì),當(dāng)我們new了對(duì)象燥翅,并保存了其引用骑篙,但是后面一直沒用它,而垃圾回收器又不會(huì)去回收它森书,這邊會(huì)造成內(nèi)存泄露靶端,
內(nèi)存溢出是指程序所需要的內(nèi)存超出了系統(tǒng)所能分配的內(nèi)存(包括動(dòng)態(tài)擴(kuò)展)的上限。