java - WriteObject 没有正确写入 Set?

标签 java java-7 objectinputstream objectoutputstream

我希望我不只是发现 Java 中的错误!我正在运行 JDK 7u11(主要是因为这是我的雇主允许的认可的 JVM),并且我注意到一个非常奇怪的问题。

也就是说,我将数据分块到 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不应该表现出这种行为。

最佳答案

好吧,我想我明白你在问什么了。

这是一个重现的示例...

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对此进行了解释。 :

Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.

在这种情况下,您应该使用 writeUnshared(Object)这将绕过此机制,而不是 writeObject(Object)

关于java - WriteObject 没有正确写入 Set?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29421335/

相关文章:

java - 创建 URI 模式匹配器以允许/禁止解码 JWT

java - 可以在资源尝试中返回连接对象

java - 无法实例化 ObjectInputStream

Java - 反序列化包含原始类型的哈希表时出错

java - spring aop - 链接多个方面

java - Gson.toString() 给出错误 "IllegalArgumentException: multiple JSON fields named mPaint"

java - Windows 上的 java.security 文件在哪里?

java - 将eclipse项目升级到jdk1.7时的ManagementFactory问题

java - 我的比较器方法如何违反其一般契约?

java - 为什么 ObjectOutputStream 和 ObjectInputStream 抛出 EOFException 的这种奇怪行为?