我有一个非常大的对象,我希望序列化。在序列化过程中,它占用了大约130MB的堆作为weblogic.utils.io.UnsyncByteArrayOutputStream。我正在使用BufferedOutputStream来加速将数据写入磁盘,这减少了此对象在内存中保留的时间。
是否可以使用缓冲区来减小内存中对象的大小?如果有一种方法可以一次串行化x个字节并将这些字节写入磁盘,那就太好了。
如果有任何用途,示例代码如下。虽然我不认为,但没有太多可继续的事情。如果是这种情况需要有一个完整的内存副本来处理序列化的对象(因此没有序列化缓冲区的概念)那么我想我就被卡住了。
ObjectOutputStream tmpSerFileObjectStream = null;
OutputStream tmpSerFileStream = null;
BufferedOutputStream bufferedStream = null;
try {
tmpSerFileStream = new FileOutputStream(tmpSerFile);
bufferedStream = new BufferedOutputStream(tmpSerFileStream);
tmpSerFileObjectStream = new ObjectOutputStream(bufferedStream);
tmpSerFileObjectStream.writeObject(siteGroup);
tmpSerFileObjectStream.flush();
} catch (InvalidClassException invalidClassEx) {
throw new SiteGroupRepositoryException(
"Problem encountered with class being serialised", invalidClassEx);
} catch (NotSerializableException notSerializableEx) {
throw new SiteGroupRepositoryException(
"Object to be serialized does not implement " + Serializable.class,
notSerializableEx);
} catch (IOException ioEx) {
throw new SiteGroupRepositoryException(
"Problem encountered while writing ser file", ioEx);
} catch (Exception ex) {
throw new SiteGroupRepositoryException(
"Unexpected exception encountered while writing ser file", ex);
} finally {
if (tmpSerFileObjectStream != null) {
try {
tmpSerFileObjectStream.close();
if(null!=tmpSerFileStream)tmpSerFileStream.close();
if(null!=bufferedStream)bufferedStream.close();
} catch (IOException ioEx) {
logger.warn("Exception caught on trying to close ser file stream", ioEx);
}
}
}
答案 0 :(得分:2)
这在很多层面都是错误的。这是对序列化的大规模滥用。序列化主要用于临时存储对象。例如,
Java的序列化不会处理对象的长期存储(没有版本控制支持),也可能无法很好地处理大对象。
对于那么大的东西,我会先建议一些调查:
如果一切都是正确的,你将不得不研究java.io.Serialization的替代方案。通过java.io.Externalization进行更多控制可能会有效。但我建议像json或xml表示。
更新:
调查:
答案 1 :(得分:0)
为什么它将所有这些字节作为非同步字节数组输出流占用?
这不是默认序列化的工作原理。你必须有一些特殊的代码才能做到这一点。解决方案:不要。
答案 2 :(得分:0)
听起来你正在使用的运行时具有一个不太理想的对象序列化实现,你可能无法控制。
这里提到类似的抱怨,虽然它已经很老了。 http://objectmix.com/weblogic/523772-outofmemoryerror-adapter.html
您可以使用较新版本的weblogic吗?你能在单元测试中重现这个吗?如果是这样,请尝试在不同的JVM下运行它,看看会发生什么。
答案 3 :(得分:0)
我不知道weblogic(即我认为是JRockit)特别是序列化:说实话,我认为没有理由使用ByteArrayOutputStreams ......
如果您需要更多地控制对象的序列化方式,或者切换到完全不同的序列化系统(例如:Terracotta),如果您不想写,则可能需要实现java.io.Externalizable
自己读/写方法(如果你有很多大班)。
答案 4 :(得分:0)
您尝试保存的“siteGroup”对象是什么?我问,因为任何一个对象的大小不可能是130MB,除非它有一个巨大的列表/数组/映射/其中的任何内容 - 如果是这样的话,答案就是将数据保存在数据库中。
但是如果对象中没有怪物集合,那么问题可能是对象树包含对bagillion对象的引用,并且序列化当然会进行深层复制(这个事实已被用作实现克隆的快捷方式()很多次),所以一切都以自上而下的方式一次性编目。
如果这是问题所在,那么解决方案就是实现自己的序列化方案,其中每个对象以自下而上的方式进行序列化,可能在多个文件中,并且只将引用保留到其他对象,而不是整个对象。这将允许您单独编写每个对象,这将产生您正在寻找的效果:由于以块的形式写出数据而导致内存占用更少。
但是,实现自己的序列化(如实现clone()方法)并不是那么容易。所以这是一个成本/收益的事情。