簡體   English   中英

ByteArrayOutputStream在java聲音錄制時出現內存不足錯誤

[英]ByteArrayOutputStream Out of memory error while recording in java sound

我遇到了一個非常奇怪的問題。 我正在編寫以下代碼的一部分。

try {
    while (!stopCapture) {
        // Read data from the internal buffer of the data line.
        int cnt = this.recLine.read(tempBuffer, 0, tempBuffer.length);
        if (cnt > 0) {
            // Save data in output stream object.
            byteArrayOutputStream.write(tempBuffer, 0, cnt);
            // System.out.println(" bytes " + tempBuffer[0]);
        }// end if
    }// ends while

    // AudioSystem.write(myAIS, targetType, outputFile);
    byteToWave(byteArrayOutputStream);
    byteArrayOutputStream.close();
} catch (IOException e) {
    // TODO provide runtime exception to reach it to presentation layer
    e.printStackTrace();
} catch (Exception ex) {
    ex.printStackTrace();
}

recLine是TargetDataLine,我將聲音錄制到byteArrayOutputStream中。 它在我的測試中正常工作到40-48秒,但是每當它在下面拋出異常時達到49秒:

Exception in thread "Thread-5" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2786)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
    at com.actura.app.capture.ActuraRecorder.run(ActuraRecorder.java:109)
    at java.lang.Thread.run(Thread.java:619)

我正在使用這種技術,因為我需要記錄的字節,從這些字節我在UI上成功繪制波形。

在測試期間,我發現當byteArrayOutputStream的大小僅為7.3 mb時會引發異常。

我可以將此byteArrayOutputStream寫入隨機訪問文件,然后每次達到其限制時重置此byteArrayOutputStream嗎?

我如何提前知道byteArrayOutputStream的限制?

我檢查了Integer.MAX_VALUE,但正如我所說,它只是在7.3 MB引發異常,所以我無法達到Integer.MAX_VALUE。

這個小程序在互聯網上運行,因此設置內存大小對我沒有幫助。 如何將其設置到客戶端的計算機上?

您的問題是,JVM內存不足,因為您將所有數據保存在內存中。 擴展堆空間有助於暫時,直到您需要使用更長的音頻。

一個想法可能是將FileOutputStreamByteArrayOutputStream交換為臨時File 這不需要將所有音頻數據保存在存儲器中。 一個更好的解決方案是Guavas FileBackedOutputStream ,它只在一個臨時文件中存儲數據,如果它超過某個閾值。

另一種解決方案是直接更新每個緩沖區的波形。 通過創建一種方法,該方法僅接收具有音頻數據的緩沖器並將其應用於波形的當前狀態。 這樣您根本不需要存儲音頻數據。

出現此問題的原因是Hotspot JVM的堆在其大小上具有固定的上限。 默認限制取決於您的平台,但可能低至40Mb。

你正在做的是從你的音頻流中讀取大量數據並在內存中緩沖它們。 鑒於堆具有上限,您的應用程序最終將遇到該限制,結果將是OutOfMemoryError異常。

顯而易見的解決方案是使用-Xmx選項增加JVM的最大堆空間。 (有關此選項的更多信息,請參閱java命令手冊條目。)但是,對於JVM堆積的大小有一個最終限制...取決於您的硬件,操作系統以及您是否使用64位JVM。

您還可以將音頻數據保存到文件或嘗試壓縮或減少它,但這些都會使圖形更復雜。

其他人已經討論了問題的根源。

要解決它,要么:

  1. 一次繪制一點字節,或者..
  2. 存儲一個BufferedImage ,以小塊的形式獲取字節,然后立即將它們繪制到圖像中。

第一種技術可能會導致像You Tube Video中看到的那樣

聲音痕跡

您可以嘗試增加JVM堆空間或嘗試壓縮聲音數據以減少內存消耗。

它肯定會填滿你的記憶,它的行為在不同的計算機上會有所不同。 您可以做的是使用一些FileOutputStream並將數據寫入其中,一旦您的循環結束從那里拉取數據並將其轉換為wav 還要用小包字節(最好是4096)寫入數據。確保tempBuffer的長度不超過4096。

希望這可以幫助..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM