2012-09-20 87 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

唯一的解決辦法我發現是,第一次開始發送線程,檢查線程池是否爲空,在這種情況下,我重置輸出流。 我今天晚上運行這個軟件來檢查這個。

謝謝大家!

利瑪竇