[英]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內存不足,因為您將所有數據保存在內存中。 擴展堆空間有助於暫時,直到您需要使用更長的音頻。
一個想法可能是將FileOutputStream
的ByteArrayOutputStream
交換為臨時File
。 這不需要將所有音頻數據保存在存儲器中。 一個更好的解決方案是Guavas FileBackedOutputStream
,它只在一個臨時文件中存儲數據,如果它超過某個閾值。
另一種解決方案是直接更新每個緩沖區的波形。 通過創建一種方法,該方法僅接收具有音頻數據的緩沖器並將其應用於波形的當前狀態。 這樣您根本不需要存儲音頻數據。
出現此問題的原因是Hotspot JVM的堆在其大小上具有固定的上限。 默認限制取決於您的平台,但可能低至40Mb。
你正在做的是從你的音頻流中讀取大量數據並在內存中緩沖它們。 鑒於堆具有上限,您的應用程序最終將遇到該限制,結果將是OutOfMemoryError
異常。
顯而易見的解決方案是使用-Xmx
選項增加JVM的最大堆空間。 (有關此選項的更多信息,請參閱java命令手冊條目。)但是,對於JVM堆積的大小有一個最終限制...取決於您的硬件,操作系統以及您是否使用64位JVM。
您還可以將音頻數據保存到文件或嘗試壓縮或減少它,但這些都會使圖形更復雜。
其他人已經討論了問題的根源。
要解決它,要么:
BufferedImage
,以小塊的形式獲取字節,然后立即將它們繪制到圖像中。 第一種技術可能會導致像You Tube Video中看到的那樣
您可以嘗試增加JVM
堆空間或嘗試壓縮聲音數據以減少內存消耗。
它肯定會填滿你的記憶,它的行為在不同的計算機上會有所不同。 您可以做的是使用一些FileOutputStream
並將數據寫入其中,一旦您的循環結束從那里拉取數據並將其轉換為wav
。 還要用小包字節(最好是4096)寫入數據。確保tempBuffer
的長度不超過4096。
希望這可以幫助..
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.