我所慣用的找尋問題起因之方法

今天早上起來看到這篇,我也想也不用對號入座了,反正很明顯是在指我之前和 Fred 兄討論 GC 可不可能將變數歸零的事情

我只能說,一開始 Fred 兄要我定義,所以我給了 Fred 兄 Java 界公認的權威性定義,一開始的定義是對方要的,所以我提供了最精確的定義,同時,那些問題應該是寫 Java 的人需要具備的 common sense。

而我也得承認,我真的不知道要怎麼和一個連 F=ma 的公式裡的三個英文字代表什麼意義都不知道的人,去討論火箭動力學相關的問題。

再者,因為我不是神,所以我所習慣找尋問題起因的方法,是當遇到一個神奇的問題時,用自己所有的一切最基礎的知識以及所知的事實去進行推論與釐清,並且推導可能的原因,然後找出可以支持自己所推導出的結論的「證據」。

我只想說,在這一切討論的過程中,我很努力地找出各種理論與佐證資料,並加以證明我認為「這不是 GC 的正常行為」的理由,但同時我也很歡迎其他人能提供理論和證明告訴我我對於 Java / Dalvik VM 的所有基本認知是錯的,然而實情卻是到目前為止都沒看到對方提出可信的佐證資料與實證來支持他的「這是 GC 的問題,是 Delvik 的特性 」的反論。

BTW,這個對話進行到現在,對方連歸零的變數到底是 primitive type 還是 Reference type 都說不清,我真的不知道該怎麼去釐清問題真正發生的原因。

所以即使是在和 Fred 的討論沒有交集而停止之後,我還特地跑去 StackOverflow 問了這個問題,並例舉了一大堆我所能思考到與此相關,但我不確定的問題……因為,如果能夠知道我對於 Java / Dalvik GC 的基本認知真的有問題,我會很高興。

我想追求的是可以解釋的事實真相與可以實證的理由,而不是僅止於沒有證明的猜測。

因為自己不知道的事就是不知道,根本沒必要去猜,畢竟世界上有無數種可能的情況,哪有可能猜得完?

也因為如此,你可以看到我直到現在都仍堅持「我不知道那個變數被歸零的真正原因」,而是提出證據明確地告訴你兩件我所知道的事實而已:

  1. Activity 切換時可能造成外界看起來變數歸零
  2. 以 Java 對於記憶體操作的模型言,GC 將變數歸零不是正常的行為

注意,我從來沒說過那個變數不可能被莫名其妙歸零(畢竟我手上沒有出問題的那些 code,而且我還沒有仔細追過 Dalvik VM 是不是有 bug 會造成這樣的情況),我從頭到尾說的都是「那不是 Java / Dalvik 的 GC 的正常行為」,因為那是我所推導出來,並且有理論和證據支持的事情。

所以即使到現在也是一樣,如果有任何人能告訴我在什麼情況下 Java / Dalvik VM 會出現下面的行為,請務必告訴我:

  1. GC 回收(重置)一個 primitive 整數
  2. 一個 member field 在物件消滅前先被回收或消滅
  3. GC 回收了 Integer 物件後你還能保有指到原來的記憶體空間的 Reference

因為我真的很想知道是不是我對於 Java / Dalvik 的 GC 認知有誤!

強調一次,我不知道的事情就不知道,我不會去猜測,我只能告訴你已知的事實,因為我不是全知的神。

這門學科會叫 Computer Science 不是白叫的,寫程式的本質是科學,科學講究的是可以驗證的事實,同時科學也要求精確的定義。

而在程式設計裡面,精確的定義就叫程式語言的 Spec,可以驗證的事實就是該程式語言實作 Compiler / Runtime 的程式碼以及你自己寫的程式碼。

而我也只能告訴你,在我手上沒有原本出問題的程式碼的情況下,我無法告訴你是不是對方的程式碼本身就有問題,是不是就像 StackOverflow 上其他朋友所講的,可能在隱藏的地方被不小心改到了但卻沒注意到。

同時我也只能告訴你,就我所知道的 Java Spec 和 GC 的實作方式[1] [2],GC 把變數歸零不會是正常的行為,而你在一個物件被回收後,也不應該會繼續持有他的 Reference[3],進而讓你可以存取到原本的那塊記憶體空間內的內容。而上面這些事情,都可以靠著閱讀 Spec 和追蹤程式碼得到實證

如果仔細觀察的話,你應該可以發現在這一切的討論裡,到底是哪一方沒提出任何可信的論證--到底是誰只講了「我推論後認為這這是 GC 的錯」,卻沒提出任何推論的過程以及理由、論述、證明,沒有告訴你在什麼情況下 GC 會發生這樣的事,在什麼時間點 GC 會認為可以回收那個整數,又是怎麼回收的。

最後,我只能說,我重看了這一篇「這是兩碼子事!『犛清問題』與『不是我的問題』!」後我覺得很諷刺……請問到目前為止,有任何人用了任何方式證明了這件事就是 GC 的問題嗎?好。像。沒。有。

我從頭到尾講的都是「我不知道真正的原因」,但卻好像有人可以信誓坦坦的告訴你,他推論這就是 GC 的錯,因為不可能有其他原因(真的不可能有其他原因嗎? ),而且還沒提出任何說明與論證告訴你為什麼這是 GC 的錯。

最後,我只想說,請問一下,這種找問題的起因的態度,和「不是我的問題」有什麼不一樣?

註腳

[1]OpenJDK / Dalvik VM / KVM 你都可以找到原始碼,我自己是大學時追過 KVM 的 GC。
[2]Dalvik VM 的部份我還沒有追,但 Thinker 已經代勞過了。然後如果你仔細看 Thinker 的追蹤結果,會發現在最一開始 Fred 的那篇文章裡所說的「他會自動將目前 Reference 數量稀少的記憶體回收」這句話本身就已經與 Dalvik VM 的運作事實相違背,因為在 Dalvik VM 裡面,一個物件所佔的記憶體釋放與否,和 Reference 的數量是完全無關的
[3]即便是你透過 WeakReference / SoftReference 來放他,在物件被回收之後也無法再從 WeakReference 取得指到原本的物件參考了

回響