Re: [問題] null 和 GC 與 LinkedList 的原始碼
..原文恕刪
感謝jtmh的回答,在這邊我原文可能沒有表達好,這次重新修改成例子+描述下好了~
(重申一下.. LinkedList.java: http://pastie.org/2730219 ,
很抱歉我原文沒有Po出來~)
假設整個結構長這樣,而element這欄位是否會被GC回收先忽略掉: (size = 3)
註: _Instance1 2 3 是方便用的,實際沒有這變數。
header←═════════════════════════╗
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐║
│ element │ │ element │ │ element │ │ element │║
│┌───┐│ │┌───┐│ │┌───┐│ │┌───┐│║
││ ││ ││ ││ ││ ││ ││ ││║
│└───┘│ │└───┘│ │└───┘│ │└───┘│║
│ │ │ │ │ │ │ │║
│ next │ │ next │ │ next │ │ next │║
│┌───┐│ │┌───┐│ │┌───┐│ │┌───┐│║
││ ╪╪→││ ╪╪→││ ╪╪→││ ╪╪╝
│└───┘│ │└───┘│ │└───┘│ │└───┘│
│ │ │ │ │ │ │ │
│ previous │ │ previous │ │ previous │ │ previous │
│┌───┐│ │┌───┐│ │┌───┐│ │┌───┐│
╔╪╪ ││←╪╪ ││←╪╪ ││←╪╪ ││
║│└───┘│ │└───┘│ │└───┘│ │└───┘│
║└─────┘ └─────┘ └─────┘ └─────┘
║ _Instance1 _Instance2 _Instance3
║ ↑
╚═══════════════════════════╝
圖一、未remove前的狀態
假設現在的remove改成了remove_x,換句話說就是這樣:
private E remove_x(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
size--;
modCount++;
return result;
}
那麼倘若執行了以下敘述:
remove_x(_Instance1);
那麼整個結構就會轉成這副德性:
╔═══════════════════════════╗
↓ ╔═══════════╗ ║
header ║ ↓ ║
┌─────┐║┌─────┐ ┌─────┐ ┌─────┐║
│ element │║│ element │ │ element │ │ element │║
│┌───┐│║│┌───┐│ │┌───┐│ │┌───┐│║
││ ││║││ ││ ││ ││ ││ ││║
│└───┘│║│└───┘│ │└───┘│ │└───┘│║
│ │║│ │ │ │ │ │║
│ next │║│ next │ │ next │ │ next │║
│┌───┐│║│┌───┐│ │┌───┐│ │┌───┐│║
││ ╪╪╝││ ╪╪→││ ╪╪→││ ╪╪╝
│└───┘│ │└───┘│ │└───┘│ │└───┘│
│ │ │ │ │ │ │ │
│ previous │ │ previous │ │ previous │ │ previous │
│┌───┐│ │┌───┐│ │┌───┐│ │┌───┐│
╔╪╪ ││←╪╪ ││╔╪╪ ││←╪╪ ││
║│└───┘│ │└───┘│║│└───┘│ │└───┘│
║└─────┘ └─────┘║└─────┘ └─────┘
║ ↑ _Instance1 ║ _Instance2 _Instance3
║ ╚═══════════╝ ↑
╚═══════════════════════════╝
圖二、remove_x(_Instance1)後的狀態
而現在假設GC還沒把_Instance1這個東西吃掉而繼續執行下面的敘述:
remove_x(_Instance2);
那麼整個結構接著會轉成這副德性:
╔═══════════════════════════╗
↓ ╔═══════════════════╗ ║
header ║ ↓ ║
┌─────┐║┌─────┐ ┌─────┐ ┌─────┐║
│ element │║│ element │ │ element │ │ element │║
│┌───┐│║│┌───┐│ │┌───┐│ │┌───┐│║
││ ││║││ ││ ││ ││ ││ ││║
│└───┘│║│└───┘│ │└───┘│ │└───┘│║
│ │║│ │ │ │ │ │║
│ next │║│ next │ │ next │ │ next │║
│┌───┐│║│┌───┐│ │┌───┐│ │┌───┐│║
││ ╪╪╝││ ╪╪→││ ╪╪→││ ╪╪╝
│└───┘│ │└───┘│ │└───┘│ │└───┘│
│ │ │ │ │ │ │ │
│ previous │ │ previous │ │ previous │ │ previous │
│┌───┐│ │┌───┐│ │┌───┐│ │┌───┐│
╔╪╪ ││←╪╪ ││╔╪╪ ││╔╪╪ ││
║│└───┘│ │└───┘│║│└───┘│║│└───┘│
║└─────┘ └─────┘║└─────┘║└─────┘
║ ↑↑ _Instance1 ║ _Instance2 ║ _Instance3
║ ║╚═══════════╝ ║ ↑
║ ╚════════════════════╝ ║
╚═══════════════════════════╝
圖三、續圖二後remove_x(_Instance2)後的狀態
而現在重點來了~
既定事實: (根據上幾篇看後的推測)
如果現在GC抓_Instance1,是可以回收的!
另一方面,現在GC抓_Instance2,是不可以回收的(因為被_Instance1參照)!
理論上 LinkedList是存取不到 _Instance1和_Instance2。
以及如果GC回收_Instance1,那麼_Instance2也就變得可以回收,
但若倒過來(先回收_Instance2再回收_Instance1)則不行。
問題:
1. 在remove_x二個_Instance後,GC是否還能夠把這二個_Instance回收掉。
2. 如果GC能夠回收掉,那麼寫null的意義為何? 不會是能讓GC更快回收吧?
3. 如果GC不能夠回收掉,那麼寫這null就很必要的了? (好灰暗啊...)
PS: 仍舊老話那句,對於半路出家的我,希望各位能夠指點迷津~~~ =ˇ=
...用記事本編輯好久 orz
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.164.77.96
討論串 (同標題文章)
以下文章回應了本文:
完整討論串 (本文為第 3 之 4 篇):