2015-04-02 62 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