2012-08-15 64 views
0

我正在將圖像的字節寫入ByteArrayOutputStream,然後通過套接字發送它。 問題是,當我做Java寫入ByteArrayOutputStream內存泄漏

ImageIO.write(image, "gif", byteArray); 

內存上漲非常多,還挺內存泄漏。

我送使用此

ImageIO.write(image, "gif", byteArrayO);   
byte [] byteArray = byteArrayO.toByteArray(); 
byteArrayO.flush(); 
byteArrayO.reset(); 
Connection.pw.println("" + byteArray.length); 
int old = Connection.client.getSendBufferSize(); 
Connection.client.setSendBufferSize(byteArray.length); 
Connection.client.getOutputStream().write(byteArray, 0, byteArray.length); 
Connection.client.getOutputStream().flush(); 
image.flush(); 
image = null; 
byteArrayO = null; 
byteArray = null; 
System.gc(); 
Connection.client.setSendBufferSize(old); 

正如你可以看到我已經嘗試了所有辦法,當我寫ByteArrayOutputStream,而不是當我將其傳送的錯誤出現。接收器不會出現任何錯誤。

任何方式我可以清除byteArray,並從內存中刪除它的所有內容?我知道reset()確實,但它不在這裏。我想在完成後直接處理ByteArrayOutputStream

+0

「image」有哪些屬性?尺寸,顏色模型等? – lost 2012-08-15 14:21:15

+0

你使用多少內存?你的虛擬機設置?圖像有多大? – 2012-08-15 14:21:20

+0

你實際上是否在'ImageIO.write(...)'上出現'OutOfMemoryError'? – 2012-08-15 15:11:28

回答

4

@ChristofferHammarström可能有最好的解決辦法,但我會添加此試圖解釋的內存使用情況。

這些2線創建圖像數據的3份:

ImageIO.write(image, "gif", byteArrayO); 
byte [] byteArray = byteArrayO.toByteArray(); 

執行此之後,你有存儲圖像數據的一個副本,在ByteArrayOutputStream一個副本和字節數組中另一個副本( toByteArray()不會返回它創建副本的內部緩衝區)。

調用reset()不會釋放ByteArrayOutputStream中的內存,它只是將位置計數器重置爲0.數據仍然存在。

爲了讓內存更早釋放,您可以在完成後立即將每個項目分配給null。這將允許垃圾回收器收集內存,如果它決定更早運行的話。 EG:

ImageIO.write(image, "gif", byteArrayO); 
image = null; 
byte [] byteArray = byteArrayO.toByteArray(); 
byteArrayO = null; 
... 
0

您可以請求虛擬機通過System.gc()運行垃圾回收,但這並不保證實際發生。當虛擬機決定它是必要的還是適當的時候,它會執行垃圾收集。

+0

我在我的代碼結尾處做了這些事情。不會幫助。我將對象和所有這些對象置零,但它仍然保留在內存中。 – 2012-08-15 14:13:03

+0

僅僅因爲你處理了它,並不意味着內存立即被釋放。由VM決定何時釋放內存。 – 2012-08-15 14:18:46

1

這不是您想要的答案,而是您可能希望考慮的問題。

爲什麼不創建一個字節數組池並在需要時重新使用它們。這樣會更有效一些,因爲你不會創建新的數組並且一直拋棄它們。少使用gc總是一件好事。你也可以保證應用程序有足夠的內存來運行。

4

爲什麼你不得不擺弄發送緩衝區的大小?你在這個套接字上使用了什麼樣的協議?它應該只是簡單:

ImageIO.write(image, "gif", Connection.client.getOutputStream()); 

如果你必須使用一個ByteArrayOutputStream,至少使用

byteArrayO.writeTo(Connection.client.getOutputStream()) 

這樣你就不會做出額外的冗餘byte[]

0

你所描述的是非常正常的。它必須把你正在創建的圖像的字節放在某個地方。

除了內存,您可以使用FileOutputStream將字節寫入。然後,您必須使FileInputStream從您寫入的文件中讀取數據,並將字節讀入64k大小的字節數組緩衝區,然後將這些字節寫入連接的輸出流。

您提到錯誤。如果您收到錯誤,錯誤是什麼?

如果使用客戶端JVM(對java的-client參數),則可能會將內存返回給操作系統,並且Java進程將再次收縮。我不確定這一點。

如果你不喜歡JAI被使用多少內存,你可以使用Sanselan嘗試:http://commons.apache.org/imaging/