關於 NE弱引用的一些個人理解

2022-02-24 16:01:10 字數 1755 閱讀 4468

首先為什麼要有弱引用:

這個問題比較有意思,大家都知道乙個物件有引用就不可能被gc,沒有引用就會被gc,而有一種物件有引用依然會被gc掉,哈哈,是不是有點費解。

其實有這麼一種應用:比如我想為了程式需要建立乙個硬碟的所有檔案目錄列表,出於效能考慮這個列表被放置在記憶體中,而程式去作其他事情的時候,把這個目錄放到若引用上,當程式記憶體比較吃力時,gc來臨**該目錄,當程式記憶體夠用時,不進行gc則這個目錄依然在記憶體中,這樣就方便了程式對記憶體的控制,記憶體緊我就乾掉你,記憶體不緊就留這你,像個戰士,戰事緊你就犧牲,戰事不緊你就活著。

用法:

void method()else

}

弱引用的內部原理

在上面的討論中,很明顯弱應用跟其它型別表現得不太一樣。通常,如果你的程式根存在乙個對該物件的引用,該物件又引用了另乙個

物件,那麼兩個物件就是可訪問的,且gc不可以重新分配這兩個物件的記憶體。但是,如果你的程式根集存在乙個弱引用物件,那麼該

弱引用指向的物件不被認為是可達的,可能被**。

為了更好的理解弱引用是如何工作的,我們在來看看託管對的內部。託管堆包含了兩個內部資料結構母的是用於管理弱引用物件:

短弱引用表和長弱引用表。這兩個表包含了指向託管對物件的指標。

初始化時候,兩個表都是空的。當你建立乙個弱應用物件,物件不會從託管對分配資源,而是從弱引用表中分配乙個空的槽,

短弱引用型別使用短弱引用型別表,而長弱引用型別則使用長弱引用型別表。

一旦發現乙個空槽,該槽的則就會被設定成為你想追蹤物件的位址--也就是從weakreference建構函式傳遞進去的物件指標。

例項化操作返回的就是該槽的位址。顯然,兩個弱引用表並不是程式根集合的一部分或者gc無法重新分配表中的物件指標。

現在,我們來看看gc執行時會發生什麼情況:

1. gc建立乙個可到達物件的圖,文章第一部分 已經討論過gc是如何實現。

2. gc搜尋短弱引用表,如果表中指標指向的物件不是物件圖的一部分,那麼指標指向的是乙個不可訪問的物件,而該槽也會被

設定為null。

3. gc搜尋finalization佇列,如果佇列中的指標指向的物件不是物件圖的內容,那麼指標表示的是乙個不可訪問物件,該指標

從finalization佇列移動到freachable佇列。在這點上,物件被新增到物件圖中因為物件被認為是可訪問的。

4. gc遍歷長引用型別表,如果弱引用物件的指標不是圖中的一部分(而在freachable佇列包含了該物件的指標),那麼指標

表示的是乙個不可達的物件,同時該槽被設定為null

5. gc壓縮記憶體,壓縮那些unreachable物件留下來的空間。

一旦你了解了gc的執行邏輯,那麼理解弱引用是如何工作就很容易了。訪問弱引用的target屬性時,會使得系統反正的弱應用表中

的槽。如果該槽為null,那麼物件就已經給**了。

短弱引用是不會追蹤重生的。這意味著,gc一旦認為物件是不可達的時候,則將短弱引用表中的指標設定成為null。如果物件具有

finalize方法,這個方法還沒被呼叫時,則這個物件還存在。如果程式訪問弱引用型別的target屬性,則返回null,即使物件還存在。

乙個長弱引用會追蹤重生,這意味著當物件的儲存空間被**時,那麼長弱引用表的指標則會設定成null。如果物件使用了finalize

方法,那麼finalize會被呼叫,物件不再重生。

引用:

關於SpringIOC的一些個人理解

根據上面這個思路接著說的話,那就順理成章了,首先spring容器將所有的bean都放在一起進行管理,然後當某個應喲經程式需要用到某個bean物件的時候,說一下,然後spring自動給這個程式分配他所需要的物件。這就是所謂的控制反轉了吧?本來這個宣告建立bean物件的過程應該由程式自己進行,建立呼叫然...

關於git命令一些個人理解

對於git reset hard 版本號 如果工作區新增了乙個檔案,那個檔案不會被刪除,因為沒有add過,不能對它追蹤。同樣,假如工作區新增了新檔案,如果git reset 版本號 再git checkout 新檔名 是會報錯的,也是沒有追蹤那個新檔案。這個時候如果git status,會顯示有新檔...

關於拓撲排序的一些個人理解

拓撲排序首先針對的是有向無環圖,其主要的目的是將乙個有向圖變為乙個線性序列,就像任務排序那樣的感覺。對於任何任務,必然先要完成其先導任務,對於同等級的任務,就可以隨意進行排序處理,當是乙個正常可完成的無環圖,必然可以使得生成乙個同節點個數的線性序列 對於拓撲排序,核心的步驟要借助佇列進行 首先,根據...