剖析使用ObjectOutputStream可能引起的内存泄漏 - 编程入门网
ot;c:\\test.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
for (int i = 0; i < 5; i++) {
MyObject myObj = new MyObject();
myObj.str1 = "test1" + i;
myObj.str2 = "test2" + i;
oos.writeObject(myObj);
}
fos.close();
我们再来看一下写入的结果: 清单 7. 写入 5 次不同内容的对象
剖析使用ObjectOutputStream可能引起的内存泄漏(3)时间:2012-01-28 IBM 李锬测试小结 通过上面的测试就很容易的发现,我们虽然写入了 5 次,但是不会每次写入都会插入写入对象和成员变量类型的信息,而是在第一次写入的时候插入一些头信息,以后再写就不会再插入了。这实际是 Java 做的优化,通过该优化从而减少 socket 传输的开销。 我想现在应该有人已经看出问题来了,它之所以可以这么做优化,前提是持有 MyObject 的引用,也就是说,不会释放掉 MyObject 的引用。如果你是长连接的方式(socket 中很常用),ObjectOutputStream 会一直持有你以前发送过的对象的引用,从而导致 JVM 在进行垃圾回收的时候不能回收之前发送的对象的实例,经过漫长时间的运行,最终导致内存溢出。这一点从我通过 Jprobe 跟踪也得到了印证。 避免长连接的情况下出现内存溢出 下面我们来谈谈如何避免该问题,说到这里我们就得提到 ObjectOutputStream 的 reset 方法了,JDK 文档中是这么解释该方法的: “重置将丢弃已写入流中的所有对象的状态。重新设置状态,使其与新的 ObjectOutputStream 相同。将流中的当前点标记为 reset,相应的 ObjectInputStream 也将在这一点重置。以前写入流中的对象不再被视为正位于流中。它们会再次被写入流。” 就是说调用 reset 那么就丢弃所持有对象的状态(也就是释放掉了对对象的引用),同时会在流中设置 reset 标识。 我们来把之前的代码稍作修改,在进行一下测试来看看有什么不同: 清单 8. 重置的方式多次写入
我们来看一下加入 reset 后写入文件的内容: 清单 9. 重置的方式写入的内容
这次跟之前不同的,每一次写入都加入了头信息 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |