JDK ObjectOutputStream的 “内存泄漏” 问题

来源:互联网 发布:设置淘宝全场满38包邮 编辑:程序博客网 时间:2024/06/04 18:54

作者:李成龙

为求方便, 一个小模块的进程间通信, 使用了ObjectOutputStream – ObjectInputStream 机制, 可是万万没有想到从此引入了内存泄漏的Bug. 经过半天的时间浪费, 终于定位到了ObjectOutputStream身上.

 

如果一直使用ObjectOutputStream.writeObject() 方法, 内存将会一直增长, 直到耗光所有内存为止. SUN给我们的解决方案是, 调用reset(), 释放占用的内存.

实际上这个并不是一个Bug, 而是源于对ObjectOutputStream的工作机制缺乏了解, 使用不当造成的.

 

有兴趣的朋友可以参考一下这个Bug报告.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6525563

 

由于时间关系, 没有仔细的去读上面的文章. 我个人猜测和这方面的原因有关系.

 

为了正确的描绘对象之间的引用关系, ObjectOutputStream必须对自己序列化过的对象保持记性. 当再次遇到序列化过的对象的引用时, ObjectOutputStream可以指明这个对象是序列化过的某某对象, 而不是再次序列化. 如果再次序列化, ObjectInputStream会误认为是两份对象, 这样反序列化得到的对象和序列化之前的对象结构就不一致了.

如果在一个持久的连接上 (比如说一个socket连接), 反复的进行请求/响应操作. 每次发送响应时, ObjectOutputStream内部维护的对象引用表会逐步增长. 而实际上, ObjectOutputStream只需要记住一次响应过程中出现的序列化过的对象就可以了, 不必记住全部. 当然, ObjectOutputStream没法知道两次发送响应的边界在哪里, 这个必须由开发者来把握.

reset() 方法用来抹掉这个记忆. 开发者可以适时调用这个函数, 告诉ObjectOutputStream可以抛弃序列化对象的记忆了.