WEB开发网
开发学院软件开发Java 剖析使用 ObjectOutputStream 可能引起的内存泄漏... 阅读

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

 2010-05-10 00:00:00 来源:WEB开发网   
核心提示: 避免长连接的情况下出现内存溢出下面我们来谈谈如何避免该问题,说到这里我们就得提到 ObjectOutputStream 的 reset 方法了,剖析使用 ObjectOutputStream 可能引起的内存泄漏(4),JDK 文档中是这么解释该方法的:“重置将丢弃已写入流中的所有对象

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

下面我们来谈谈如何避免该问题,说到这里我们就得提到 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 

这次跟之前不同的,每一次写入都加入了头信息且每一次末尾都加入了 y,我想这个标识应该就是 reset 标识,至于具体是什么,我们没必要深究了。

结论及一些建议

通过上面一系列的测试,我们大概对 Object 流有了一定了解,那么具体到我们日常编码中到底该不该调用 reset 呢,这个我想不能一概而论了。我们通过测试也看到了,在不调用 reset 的方式下,Java 的优化对于减轻 socket 开销还是很可观的,当然代价是有的,那就是直到你调用 reset 或者是关闭输出流之前,对于发送过的对象的实例是不会释放的。

如果你的程序需要很长时间的运行,建议你还是调用 reset 避免最后内存溢出程序崩溃,但是如果你又要长时间运行,且发送的消息量又很大,那么调用 reset 无疑会增加开销,那么这个时候最好的做法我觉得是自己实现一套机制,定时的调用 reset 或者是定量,比如查看到内存已经涨到一个水平后调用一下,这样既可以避免内存无限的增长下去,又可以减少不少 socket 通信的开销。

上一页  1 2 3 4 

Tags:剖析 使用 ObjectOutputStream

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接