日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達者為師

網(wǎng)站首頁 編程語言 正文

JVM中的垃圾回收

作者:忄烰燴 更新時間: 2022-11-14 編程語言

1.為什么要有垃圾回收?

例如在C語言中,通過malloc在堆(和JVM的堆不太一樣)里申請內(nèi)存之后,就得再通過free手動釋放內(nèi)存空間,或者等到程序結(jié)束才會釋放,如果忘記釋放就可能會導(dǎo)致"內(nèi)存泄漏"

內(nèi)存泄漏:內(nèi)存越用越多,可以用的空間越來越少,,空間逐漸用完,程序就會出現(xiàn)問題.

所以申請空間之后就得靠人為記得手動釋放空間,但是只要涉及到人為,就會有不靠譜的時候,所以JVM就實現(xiàn)了垃圾回收這樣的機制(garbage collection)簡稱GC.

2.垃圾回收主要回收哪個內(nèi)存區(qū)域?

棧:棧里面是放的是局部變量,它們出了自己的作用域之后就自動回收了,所以不用刻意去回收.

程序計數(shù)器:每個線程有一個,所需空間是固定的,在線程銷毀的時候跟著銷毀就行了.

方法區(qū):放的是類對象,主要的工作是"類加載",而很少涉及"類卸載",所以需要GC不必太迫切.

堆:這里放的是new出來的對象,這里是GC最主要的工作地點.new出來的對象用完之后就需要回收.

?3.JVM怎么知道誰是垃圾呢?

在垃圾回收中有兩個典型的判定方法:1.引用計數(shù) 2.可達性分析

在JVM中使用的是可達性分析

什么是可達性分析呢?

就是我們設(shè)置一些起點作為GCRoot,從這些GCRoot開始去尋找可以訪問到的對象,將他們標(biāo)記為"可達",當(dāng)這些標(biāo)記完之后,剩下的那些就是"不可達"的也就是需要回收的垃圾了.

哪些可以作為GCRoot呢?

1.局部變量表中的局部變量? (每個線程中有一個棧,每個棧中有很多棧幀,每個戰(zhàn)幀里有一個自己的局部變量表)

2.常量池中的對象

3.方法區(qū)中靜態(tài)引用類型的成員

什么是引用計數(shù)呢?

就是使用額外的計數(shù)器記錄一個對象被多少個引用指向.如果有新的引用指向這個對象,那引用計數(shù)就+1,如果有指向這個對象的引用有減少,則計數(shù)也會跟著-1.直到計數(shù)為0的時候就意味著沒人引用它,也就成了垃圾了.此時就會被回收.

但是引用計數(shù)有兩個比較大的問題:

1.對象如果不大,空間成本高

假如這個對象比較大的話就沒什么問題,假設(shè)這個對象是1000Byte,程序計數(shù)器是4Byte

那加起來也就1004Byte

但是如果這個對象很小,只有2Byte,那加上計數(shù)器(4Byte1)就是6Byte,是原來的3倍大,空間成本太高辣!

2.有循環(huán)引用的問題

?在下面的操作之后就會有循環(huán)引用的問題.

?

兩個對象現(xiàn)在相互引用了,這樣計數(shù)器既不是0,也拿不到對象了,就會一直占著內(nèi)存.我們就稱為循環(huán)引用.

4.垃圾回收的過程

?但是這種清理方法會形成"內(nèi)存碎片",內(nèi)存并不是連續(xù)的,但是以后new對象的時候要的是連續(xù)的空間,所以這樣清理出來的空間也不太能用.

解決方法使用"復(fù)制算法"也就是將標(biāo)記的對象復(fù)制到另外一片內(nèi)存上,再將原來的整片內(nèi)存清空

?這種方法有點類似順序表的刪除操作,優(yōu)點是可以有效解決"內(nèi)存碎片問題",缺點是有點耗時.

?

典型的垃圾回收器:Serial,? ?ParNew,? ?Parallel,? ?Serial Old,? ?Parallel Old,? ?CMS,? ?G1? ?

原文鏈接:https://blog.csdn.net/qq_62592809/article/details/127714582

欄目分類
最近更新