java socket对象内存泄漏

时间:2012-09-20 09:13:59

标签: java sockets stream memory-leaks objectoutputstream

我在java Socket Object通信时出现内存泄漏问题。

这是我的发送帖子。

    // 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个字符)时,我看到其他消息丢失了!

还有另一种清除缓存而不重置它的方法吗?

4 个答案:

答案 0 :(得分:1)

ObjectOutputStream.reset()是不可避免的,因为它是清除本地哈希表的唯一方法,你可以参考ObjectOutputStream的java源代码,了解reset()中发生的事情的细节,否则你最终会得到OutOfMemoryError

但你可以很好地实现像

这样的功能
private void writeObject(Object obj, ObjectOutputStream oos) throws IOException
    {
        synchronized(oos)
        {
            oos.writeObject(obj);
            oos.flush();
            oos.reset();
        }
    }

但是,您必须确保通过此方法对ObjectOutputStream进行所有写入。

答案 1 :(得分:0)

我会定期使用ObjectOutputStream.reset()来清除流的对象缓存。

您甚至可以在发送每个对象后使用它。 ;)

答案 2 :(得分:0)

ciao:),

在ObjectOutputStream.flush()之后,您可以安全地使用ObjectOutputStream.reset()

除非您在另一个线程中使用objWriter somwhere而不使用synchronized(objWriter)语句。 在这种情况下,IMHO最好的方式是在一个线程中使用objWriter,它将从一个同步的队列发送对象(参见队列子类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) thread(记得使用object.clone(),因为objcet本身不是同步的,它可以在你编写它时被其他线程修改或者在队列中!如果你克隆它,你的克隆将是一个安全的副本)。 / p>

这样你就不需要同步的语句了,因为线程和ObjectOutputStream之间的数据流已经同步了,你的错误会少一些

答案 3 :(得分:0)

我找到的唯一解决方案是,首先启动发送线程,检查线程池是否为空,在这种情况下我重置输出流。 我整晚都在运行软件来检查这个。

全部谢谢!

利玛