我希望我没有找到Java中的错误!我正在运行JDK 7u11(主要是因为这是我雇主允许的制裁JVM),我注意到一个非常奇怪的问题。
即,我正在将数据分块到LinkedHashSet
并使用ObjectOutputStream
通过GZIpOutputStream
更改的readObject()
雏菊将其写入文件(仅在重要的情况下提及此内容)。
现在,当我到达程序的另一端并.size()
时,我注意到大小始终为68,这是我的第一个大小。基础表可以有多于或少于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**
}
时,它也会在68处停止。
Set<Coordinate> coordinates = (Set<Coordinate>) ois.readObject();
阅读时
coordinates.size()
.writeInt()
总是返回68.现在,我可以通过wptSet = new LinkedHashSet<>()
大小来解决方法,但我只能遍历68个成员!
请注意,System.gc()
行实际上解决了这个问题。这个问题的主要问题是,当我在JVisualVM中查看程序时,它会使我的heapsize飙升。
更新:
我实际上刚刚找到了一个可行的解决方法来修复重新实例化wptSet的内存泄漏... .clear()
在每次调用LinkedHashSet
之后调用它实际上会使内存泄漏。
无论哪种方式,我都不应该这样做并且发货{{1}}不应该表现出这种行为。
答案 0 :(得分: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
时,都会有一个&#34;共享参考&#34;写入对象,以便每次反序列化相同的对象。这在the documentation:
使用参考共享机制对单个对象的多个引用进行编码,以便可以将对象图形恢复为与写入原始图像时相同的形状。
在这种情况下,您应该使用writeUnshared(Object)
来绕过此机制,而不是writeObject(Object)
。