2012-09-20 117 views
0

我在java Socket对象通信中遇到内存泄漏问题。java socket对象内存泄漏

这是我的发送主题。

// 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++; 
      } 
     } 
    } 
} 

缓存,当我发送有关我每包毫秒增长和增长!

如果我添加注释的部分缓存干净,但当我需要发送异步长消息(约3000字符)时,我看到其他消息丢失!

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

回答

1

ObjectOutputStream.reset()是不可避免的,因为它是清除当地的哈希表的唯一手段,你可以参考Java源代码的ObjectOutputStream为复位发生的事情的细节(),否则你将得到的OutOfMemoryError最终

但可以很好地实现诸如

private void writeObject(Object obj, ObjectOutputStream oos) throws IOException 
    { 
     synchronized(oos) 
     { 
      oos.writeObject(obj); 
      oos.flush(); 
      oos.reset(); 
     } 
    } 

功能然而,你必须确保所有写入ObjectOutputStream中发生过这种方法。

0

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

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

+0

我现在但如果我重置缓冲区有很多情况下我丢失数据包(此套接字用于异步和同步消息) –

+0

@MatteoGatto reset()不会导致数据包丢失。 – EJP

+0

@MatteoGatto可能会导致您多次发送相同的对象。流的常见错误是通过两个不同的Streams(例如ObjectOutputStream和PrintWriter)或两个ObjectOutputStreams来写或读。这将导致数据损坏。 –

0

Ciao的:),

后ObjectOutputStream.flush(),您可以使用saftely ObjectOutputStream.reset()

,除非你somwhere使用objWriter在另一个线程不使用同步(objWriter)声明。 在这种情况下,恕我直言,最好的方法是在一个线程中使用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)发送对象。 clone(),因为objcet本身没有被syncornized,所以它可以在你写它的时候被其他线程修改或者在队列中!如果你克隆它,你的克隆将是一个安全的副本)。

这样,你不需要同步statment因为线程和ObjectOutputStream的之间的数据流已经同步,你就会更不容易出错

+0

好的,谢谢我看到没有同步的通信速度更快,但原始问题总是在这里:) –

+0

与我的代码MAYBE你正在优化,但首先你让你的代码非常容易出错。 – Lesto

0

唯一的解决办法我发现是,第一次开始发送线程,检查线程池是否为空,在这种情况下,我重置输出流。 我今天晚上运行这个软件来检查这个。

谢谢大家!

利玛窦