問:什麼是氣相色譜?
答:在 J**a 語言中,垃圾集合,GC)是乙個非常重要的概念,它的主要作用是使用程式中不再使用的記憶體
在使用C語言進行程式開發時,開發人員必須仔細管理記憶體的分配和釋放,如果忘記或錯誤地釋放記憶體,往往會導致程式執行不正常甚至崩潰。 為了減輕開發者的工作量,增加系統的安全性和穩定性,J**a 語言提供了垃圾使用者自動檢測物件的作用域,可以自動釋放不再使用的儲存空間。
具體來說,垃圾回收器負責 3 個任務:分配記憶體、確保被引用物件的記憶體不會被錯誤放置,以及不再被引用的物件的記憶體空間。
一方面,垃圾使用者的存在將開發者從釋放記憶體的複雜工作中解放出來,提高了開發者的生產力另一方面,釋放記憶體的方法對開發者進行了遮蔽,可以避免開發者對記憶體的錯誤操作導致應用崩潰,保證程式的穩定性。
但是,垃圾也帶來了乙個問題,為了實現垃圾,垃圾使用者必須跟蹤記憶體使用情況,釋放無用的物件,並在釋放記憶體後處理堆中的碎片,這些操作必然會增加JVM的負擔,從而降低程式的執行效率。
對於物件,如果沒有變數來引用它,那麼程式將無法訪問該物件,因此它可以被視為垃圾郵件,並且可以是**。 只要有多個變數引用該物件,該物件就不會被垃圾郵件傳送。
對於垃圾使用者來說,它使用乙個有向圖來記錄和管理堆記憶體中的所有物件,通過這個有向圖,可以識別哪些物件是“可訪問的”(引用變數引用它是“可訪問的”),哪些物件是“不可訪問的”(沒有引用引用它的變數是不可訪問的),所有“不可訪問”的物件都是垃圾,如下圖
將上述**執行到i2 i1後,記憶體的參考關係如下圖所示:
這時,如果垃圾回收器在做垃圾操作,在遍歷上面的有向圖時,資源 2 占用的記憶體是無法訪問的,垃圾回收器會認為這個記憶體不會再被使用,所以會**記憶體空間。
垃圾**是按照一定的演算法進行的,以下是一些常用的垃圾演算法。
參考計數收集器
引用計數作為一種簡單但效率低下的方法的主要原理如下:堆中的每個物件都有乙個引用計數器;引用物件時,引用計數器遞增 1;當引用留空或超出範圍時,引用計數將減少 1,JVM 不會使用該值,因為此方法不能解決交叉引用問題。
跟蹤收集器
跟蹤演算法使用 JVM 維護的物件引用圖從根節點遍歷物件的應用圖,並標記遍歷的物件。 遍歷結束時,未標記的物件是當前未使用的物件,可以是 **。
CompactingCollector 壓縮收集器
壓縮演算法的主要思想如下:將堆中的活動物件移動到堆的一端,這樣在堆的另一端會留下很大的自由區域,相當於處理堆中的碎片。 雖然這種方法大大簡化了刪除堆碎片的工作,但它在每次處理時都會降低效能。
複製演算法 (copingcollector)。
複製演算法的主要思想如下:將堆分成兩個大小相同的區域,任何時候只使用其中乙個區域,直到這個區域被消耗完畢,這時垃圾使用者會中斷程式的執行,通過遍歷將所有活動物件複製到另乙個區域, 並且在複製過程中它們彼此相鄰排列,這樣可以消除記憶體碎片。複製過程結束後,程式將繼續執行,直到該區域用完,然後繼續使用上述方法進行垃圾處理**。
這種演算法的優點是物件的排列也與垃圾同時排列,從而消除了記憶體碎片。 但它也付出了高昂的代價:指定大小的堆需要兩倍大小的記憶體空間;同時,由於當前執行的程式在記憶體調整過程中中斷,導致程式的執行效率降低。
GenerationalCollector(代際收集器)
複製演算法的主要缺點是每次執行演算法時,都會複製所有活動物件,效率非常低。 由於該程式具有“程式建立的物件大部分壽命較短,只有部分物件壽命較長”的特點,因此可以根據該特性對演算法進行優化。 分代演算法的主要思想如下:將堆分成兩個或多個子堆,每個子堆被認為是乙個代。 該演算法在執行時優先收集“年輕”物件,如果乙個物件在多次收集後仍然“活著”,則可以將該物件轉移到更高的堆中,以減少對其的掃瞄次數。
經常問的書面問題:
以下是可用的**:
在第二行建立浮點物件時,什麼時候可以是垃圾**?
a.4行後。
b.5行後。
c.6行後。
d.7行後。
答案:c。 在第 6 行之後,不再有引用浮點物件的物件,因此它們可能是垃圾**。
2.在以下關於垃圾**的陳述中,正確的是()。
a.一旦乙個物件變成垃圾,它就會立即被**關閉。
b.刪除物件空間後,將執行物件的 finalize 方法。
c.finalize 方法和 c 的析構函式完全是一回事。
d.物件會變成垃圾,因為沒有更多的引用指向它,但執行緒不會。
答:d。 成為垃圾的物件只會在垃圾使用者下次執行時清理,而不是立即清理,因此選項 A 是錯誤的。 finalize 方法在物件空間為 ** 之前呼叫,因此選項 b 是錯誤的。 在 C 語言中,呼叫析構函式後,物件會被銷毀,J**A 語言呼叫 finalize 方法,但垃圾不一定是**,所以 finalize 方法和 C 的析構函式不同,所以選項 C 也是不正確的。 對於 d,當物件不再被引用時,它可能是垃圾,但執行緒即使沒有被引用也可以獨立執行,因此與物件不同。 所以正確答案是d。
3. 是否可以主動通知 JVM 是垃圾**?
答:由於垃圾使用者的存在,J**a 語言本身並沒有為開發者提供顯式釋放分配記憶體的方式,即開發者無法實時呼叫垃圾使用者對乙個物件或所有物件進行垃圾處理。 但是,開發人員可以通過呼叫系統來做到這一點gc() 方法“通知”垃圾使用者執行,當然 JVM 也不保證垃圾機會立即執行。 由於系統gc() 方法的執行會停止所有響應,並檢查記憶體中是否有物件,這將對程式的正常執行和效能造成很大的威脅,因此在實際程式設計時不建議頻繁使用這種方法。