快速业务通道

剖析使用ObjectOutputStream可能引起的内存泄漏 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-13
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 次不同内容的对象

#sr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test10t #test20q ~ #sq ~ t #test11t #test21q ~ #sq ~ t #test12t #test22q ~ #sq ~ t #test13t #test23q ~ #sq ~ t #test14t #test24q ~ #

剖析使用ObjectOutputStream可能引起的内存泄漏(3)

时间:2012-01-28 IBM 李锬

测试小结

通过上面的测试就很容易的发现,我们虽然写入了 5 次,但是不会每次写入都会插入写入对象和成员变量类型的信息,而是在第一次写入的时候插入一些头信息,以后再写就不会再插入了。这实际是 Java 做的优化,通过该优化从而减少 socket 传输的开销。 我想现在应该有人已经看出问题来了,它之所以可以这么做优化,前提是持有 MyObject 的引用,也就是说,不会释放掉 MyObject 的引用。如果你是长连接的方式(socket 中很常用),ObjectOutputStream 会一直持有你以前发送过的对象的引用,从而导致 JVM 在进行垃圾回收的时候不能回收之前发送的对象的实例,经过漫长时间的运行,最终导致内存溢出。这一点从我通过 Jprobe 跟踪也得到了印证。

避免长连接的情况下出现内存溢出

下面我们来谈谈如何避免该问题,说到这里我们就得提到 ObjectOutputStream 的 reset 方法了,JDK 文档中是这么解释该方法的:

“重置将丢弃已写入流中的所有对象的状态。重新设置状态,使其与新的 ObjectOutputStream 相同。将流中的当前点标记为 reset,相应的 ObjectInputStream 也将在这一点重置。以前写入流中的对象不再被视为正位于流中。它们会再次被写入流。”

就是说调用 reset 那么就丢弃所持有对象的状态(也就是释放掉了对对象的引用),同时会在流中设置 reset 标识。

我们来把之前的代码稍作修改,在进行一下测试来看看有什么不同:

清单 8. 重置的方式多次写入

FileOutputStream fos = new FileOutputStream("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);    oos.reset(); } fos.close();

我们来看一下加入 reset 后写入文件的内容:

清单 9. 重置的方式写入的内容

#sr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test10t #test20q ~ #ysr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test11t #test21q ~ #ysr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test12t #test22q ~ #ysr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test13t #test23q ~ #ysr #com.travelsky.test.MyObject €喳 +?^`# #L #str1t #Ljava/lang/String;L #str2q ~ #xpt #test14t #test24q ~ #y

这次跟之前不同的,每一次写入都加入了头信息

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号