我在java套接字对象通信中遇到了内存泄漏问题。
这是我的发送线程。
// create a new thread to send the packet
@Override
public synchronized void run() {
if(!genericSocket.isConnected()){
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_WARN, "Socket is close");
return;
}
int retry = 0;
boolean packetSent = false;
synchronized (objWriter) {
while ((retry < RETRY) && (!packetSent) && (genericSocket.isConnected())) {
try {
objWriter.writeObject(bean);
objWriter.flush();
// Try until the cache is reset and the memory is free
/*
boolean resetDone = false;
while(!resetDone) {
try {
objWriter.reset();
resetDone = true;
} catch (IOException r) {
Thread.sleep(1);
}
}
*/
// No error and packet sent
continuousError = 0;
packetSent = true;
} catch (Exception e) {
continuousError++;
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_ERROR, "Continuous Error [" + continuousError + "] sending message [" + e.getMessage() + "," + e.getCause() + "]");
// control the number of continuous errors
if(continuousError >= CONTINUOUS_ERROR) {
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_WARN, "I close the socket");
genericSocket.disconnect();
}
// next time is the time!
retry++;
}
}
}
}
缓存,当我发送大约 I 数据包每毫秒增长和增长!
如果我添加注释部分,缓存是干净的,但是当我需要发送异步长消息(约 3000 个字符)时,我看到另一条消息丢失了!
还有另一种方法可以在不重置缓存的情况下清理缓存??
不可避免的,因为它是清除本地哈希表的唯一方法,您可以参考 ObjectOutputStream 的 Java 源代码以获取 reset() 中发生的情况的详细信息,否则最终会得到 OutOfMemoryError
但是你可以很好地实现一个函数,比如
private void writeObject(Object obj, ObjectOutputStream oos) throws IOException
{
synchronized(oos)
{
oos.writeObject(obj);
oos.flush();
oos.reset();
}
}
但是,必须确保对 ObjectOutputStream 的所有写入都通过此方法进行。
我找到的唯一解决方案是,首先启动发送线程,检查线程池是否为空,在这种情况下,我重置输出流。我今天晚上一直在运行该软件来检查这一点。
谢谢大家!
马迪奥
我会定期使用ObjectOutputStream.reset()
来清除流的对象缓存。
您甚至可以在发送每个对象后使用它。 ;)
ciao :),
在 ObjectOutputStream.flush() 之后,您可以安全地使用 ObjectOutputStream.reset()
除非您在另一个线程中使用 objWriter somwhere,而不使用 sync (objWriter) 语句。在这种情况下,恕我直言,最好的方法是在线程中使用 objWriter,它将从从另一个线程填充的 syncornized 队列(参见队列子类 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Queue.html,例如 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html)发送对象(请记住使用 object.clone(),因为 objcet 本身没有被 syncornized 它修改,它可以在你编写它或在队列中时被其他线程修改! 如果您克隆它,您的克隆将是一个安全的副本)。
这样你就不需要同步语句了,因为线程和 ObjectOutputStream 之间的数据流已经同步了,而且你不太容易出错。