2015-04-02 60 views
0

我希望我不會在Java中發現一個錯誤!我正在運行JDK 7u11(主要是因爲這是我的僱主允許的批准JVM),我注意到一個非常奇怪的問題。WriteObject沒有正確寫入Set?

也就是說,我分塊數據爲LinkedHashSet並將其寫入使用ObjectOutputStream菊花文件通過GZIpOutputStream(提到這一點,以防萬一它事項)改變。

現在,當我到達程序的另一端和readObject()時,我注意到大小始終爲68,這是我的第一個大小。基礎表可以有很多比68多跌少,但.size()方法總是返回68.更令人不安的是,當我嘗試手動循環底層Set,它也停在68

while(...) { 
    oos.writeInt(p_rid); 
    oos.writeObject(wptSet); 
    wptSet.clear(); 
    // wptSet = new LinkedHashSet<>(); // **This somehow causes the heapsize to increase dramatically, but it does solve the problem** 
} 

,在讀取時它

Set<Coordinate> coordinates = (Set<Coordinate>) ois.readObject(); 

coordinates.size()總是返回68.現在,我可以也.writeInt()大小做一個變通方法,但我只能通過68個成員重複!

注意wptSet = new LinkedHashSet<>()行實際上解決了這個問題。這個問題的主要問題是,當在JVisualVM中查看程序時,它讓我大吃一驚。

更新: 其實我只是找到了一個可行的解決方法,修復再實例wptSet ... System.gc()調用每次調用.clear()後實際保留的內存泄漏掉的內存泄漏。

無論哪種方式,我不應該這樣做,並運出LinkedHashSet不應該表現出這種行爲。

+1

您的'Coordinate'類是否實現了['Serializable'](http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html)? – Powerlord 2015-04-02 19:57:59

+0

是的,它'類座標實現可序列化{' – 2015-04-02 19:58:23

+2

請顯示[最小完整示例](http://stackoverflow.com/help/mcve)重現。否則,我們基本上是猜測。 – Radiodef 2015-04-02 19:58:33

回答

1

好吧,我想我明白你在問什麼。

這裏是重現一個例子...

import java.util.*; 
import java.io.*; 

class Example { 
    public static void main(String[] args) throws Exception { 
     Set<Object> theSet = new LinkedHashSet<>(); 
     final int size = 3; 

     for(int i = 0; i < size; ++i) { 
      theSet.add(i); 
     } 

     ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 
     ObjectOutputStream objectsOut = new ObjectOutputStream(bytesOut); 

     for(int i = 0; i < size; ++i) { 
      objectsOut.writeObject(theSet); 
      theSet.remove(i); // mutate theSet for each write 
     } 

     ObjectInputStream objectsIn = new ObjectInputStream(
      new ByteArrayInputStream(bytesOut.toByteArray())); 

     for(;;) { 
      try { 
       System.out.println(((Set<?>)objectsIn.readObject()).size()); 
      } catch(EOFException e) { 
       break; 
      } 
     } 
    } 
} 

輸出是

3 
3 
3 

這到底是怎麼回事是ObjectOutputStream檢測到您的每一次寫同一個對象。每寫入一次theSet,都會寫入對該對象的「共享引用」,以便每次都對同一個對象進行反序列化。這在the documentation說明:

到單個對象的多個參考文獻都使用參考共享機制編碼使物體的圖形可以恢復到相同的形狀當原始被寫爲。

在這種情況下,您應該使用writeUnshared(Object)這將繞過此機制,而不是writeObject(Object)

+0

賓果!我知道這裏必須要有一些Java技巧!謝謝! – 2015-04-02 23:34:23

+0

不客氣。作爲一個方面說明,你應該試着更清楚地解釋你的問題,例如我推斷你實際上在使用'ObjectOutputStream',因爲'DataOutputStream'沒有'writeObject'方法。我還不清楚你是在做多重寫操作,直到我看到你的評論,你在循環中調用clear。也映射/設置混亂。也許這個問題寫得太倉促了。 – Radiodef 2015-04-02 23:38:50