2

我有以下的無限循環監聽傳入消息:java的無限循環調用DataInputStream所接收內存溢出異常

public static void listenForMessages(){ 
      while (true) { 

       dsocket.receive(receivepacket); 
       byte[] rcvMsg = receivepacket.getData(); 



       MessageCreator tmc = new MessageCreator(); 
       TrafficMessage message = tmc.constructMessageFromBinary(rcvMsg); 

       System.out.println("message: "+message); 


     } 
} 

這需要讀取字節數組轉換爲字符串,並填充一個消息對象的方法。

public Message constructMessageFromBinary(byte[] rcvMsg) 
      throws IOException { 
     ByteArrayInputStream bais = new ByteArrayInputStream(rcvMsg); 
     DataInputStream dis = new DataInputStream(bais); 
     StringBuffer inputLine = new StringBuffer(); 
     String tmp; 

     while ((tmp = dis.readLine()) != null) { 
      inputLine.append(tmp); 

     } 

    dis.close(); 

     Message message = new Message(); 
     message.setDescriptions(tmp); 

     return message; 

    } 

這個簡單的過程,慢慢地在幾個小時內發生內存泄漏和我收到一個內存異常。

這個邏輯有什麼問題嗎?

+0

提供[SSCCE](http://sscce.org)可以幫助我們更快地找出您的問題。如果你不能提供這樣一個例子,你可能要考慮自己分析你的應用程序。我相信JVisualVM附帶Oracle的JDK,但是有很多[alternatives](https://code.google.com/a/eclipselabs.org/p/jvmmonitor/)[2](https://code.google。 com/p/java-profiler /)。 – Jeffrey

+4

這裏確實沒有足夠的信息。我在代碼中看到的唯一兩個對象引用可能會泄漏內存,具體取決於它們是什麼以及它們是如何處理的,它們是{dis}和{dsocket}。通常不能通過塊本地的變量泄漏內存;引用位於堆棧上,當該塊退出時,它們可用於垃圾收集。通常你需要尋找一些不在堆棧中的東西,或者在一個永不返回的方法中。無限循環塊中的變量每次通過循環都被替換,所以不應該是泄漏。 – arcy

回答

1

問題是我打開了一個數據庫連接。我想讓它開放以傳遞數據,而不必擔心停止和啓動連接。我現在每次打開和關閉連接都很好。

-1

這裏最好的選擇是將所有可能的對象實例移到循環之外。例如,在第一個代碼段,每次迭代創建

MessageCreator tmc. 

關於第二個片段,每次調用該方法將創建一個

StringBuffer inputLine. 

這個實例化過程可能會慢慢蠶食你的記憶。

+0

垃圾回收將回收該內存。 – Jeffrey

+0

即使它不是null並且在相同的調用堆棧位置運行?這是值得一試... – Zeh

+0

@Jeffrey你說什麼解決方案是什麼呢? – Atma