常寫Java程式或是Java RMI程式可能都知道上述兩個Class是做什麼用的,當要把一個物件包含其狀態,傳送到另外一台機器上並還原,這在分散式系統是常見到的問題,因為當物件A跟物件B有關係,並同時都送到另外一端時,接收端也必須還原這關係,一般來說這蠻複雜的,但在Java程式中傳送端可以使用ObjectOutputStream透過底層的NetworkOutputStream,將一個物件送到遠端,然後接收端直接使用ObjectInputStream從底層的NetworkInputStream接收並還原成物件和關係,為了維護物件之間的關係,ObjectOutputStream有一個Hashtable紀錄所有被傳送過的物件,這就是我們之前找半天一直找不到的盲點,原來Memory leak不在我們的程式裡,而是在Java提供的物件本身裡,為了找出這盲點,花了不少工夫...

  一整天下來,跟琮聖及SPMT試了幾種組合,終於找到一個畫面更新率不錯的組合,唯一的缺點是記憶體,程式跑大概五分鐘,記憶體用完了,本來要繼續實驗,但被老媽的電話Call回家,奶奶到我們家住了,晚上打算出去吃,所以匆匆忙忙回到家,不過奶奶身體狀況實在不適合出門,還是在家裡吃晚餐,只是跑去買了奶奶愛吃的蛋塔跟補血藥,洗完澡後繼續忙Memory leak的問題。

  首先,先用JDK內附的JConsole觀察Heap Memory,但沒看出問題所在,根據網路上的文章,記憶體使用量的曲線確實Memory leak,所以又去找了一套Eclipse上的Memory Analyzer (MAT)外掛,可以分析JVM傾印的Heap檔案,接著啟動程式時用特殊的參數,讓JVM在發生OutOfMemoryException傾印記憶體的內容,然後用MAT分析到底是什麼玩意把記憶體吃光,分析出來的結果就是ObjectOutputStream,原來我們之前實驗半天,似乎都不是對症下藥,只解決了畫面更新的問題,根本的記憶體問題都沒找對,用Google加上對的關鍵字,終於在Java官方論壇中找到解決方法,呼叫ObjectOutputStream.reset()清除Hashtable,此時已經是凌晨了,程式修改完,記憶體不在爆增,而且都維持在規範的百分比內,但同樣地,這問題在ObjectInputStream應該也會有,於是立即使用重播測試,哈~果然,記憶體又快速飆升,但這次麻煩了,Java官方論壇上說:請呼叫對應的ObjectOutputStream.reset(),它會送T_RET訊息到接收端重設ObjectInputStream,嗯,聽起來很合哩,但我們是從檔案讀取資料,哪裡來對應的ObjectOutputStream,這...累了...先睡覺吧!但就在睡著前,腦袋還在運轉,而且解法突然就浮現了,呵~下級待續...

創作者介紹

Spirit的異想世界

dbi1463 發表在 痞客邦 PIXNET 留言(0) 人氣()