用java声音录制时发生ByteArrayOutputStream内存不足错误

用java声音录制时发生ByteArrayOutputStream内存不足错误,java,Java,我遇到了一个非常奇怪的问题。我正在写下面代码的一部分 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 o

我遇到了一个非常奇怪的问题。我正在写下面代码的一部分

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();
}
倾角是我将声音录制到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.3MB时会引发异常

我是否可以将此byteArrayOutputStream写入随机访问文件,然后在每次达到其限制时重置此byteArrayOutputStream

如何提前知道byteArrayOutputStream的限制

我使用Integer.MAX_值进行了检查,但正如我所说,它只是在7.3MB处引发了一个异常,因此我无法达到Integer.MAX_值


此小程序在internet上运行,因此设置内存大小对我没有帮助。如何将其设置到客户端的计算机上?

您可以尝试增加
JVM
堆空间,或者尝试压缩声音数据以消耗更少的内存。

您的问题是,JVM内存不足,因为您将所有数据都保留在内存中。扩展堆空间暂时有助于您处理更长的音频

一个想法可能是通过
FileOutputStream
ByteArrayOutputStream
交换到一个临时
文件。这不需要将所有音频数据都保存在内存中。一个更好的解决方案是,如果数据超过某个阈值,则只将其存储在临时文件中


另一个解决方案是直接更新每个缓冲区的波形。通过创建一种方法,该方法仅接收缓冲区中的音频数据,并将其应用于波形的当前状态。这样,您根本不需要存储音频数据

它肯定会填满你的内存,在不同的计算机上,它的行为也会有所不同。 您可以使用一些
FileOutputStream
并将数据写入其中,循环结束后从中提取数据并将其转换为
wav
。 还可以将数据写入小字节包(最好是4096字节)。。确保
tempBuffer
的长度增加不超过4096


希望这有帮助。

出现此问题是因为热点JVM的堆大小有一个固定的上限。默认限制取决于您的平台,但可能低至40Mb

您正在做的是从音频流中读取大量数据并将其缓冲到内存中。假设堆有一个上限,应用程序最终将运行到该上限,结果将是
OutOfMemoryError
异常

显而易见的解决方案是使用
-Xmx
选项增加JVM的最大堆空间。(有关此选项的更多信息,请参阅java命令手册条目。)但是,JVM堆的大小有一个极限。。。取决于您的硬件、操作系统以及是否使用64位JVM


您也可以将音频数据保存到文件中,或尝试压缩或减少音频数据,但这些都会使图形更加复杂。

其他人已经讨论了问题的根源

要解决此问题,请执行以下操作之一:

  • 一次画一点字节,或者
  • 存储一个
    buffereImage
    ,抓取小块字节,并立即将它们绘制到图像中
  • 第一种技术可能会产生如下结果:


    你好,安德鲁,你能给我举一个你正在谈论的工作实例吗?谢谢你能拼出所有3个字母的“长”字,比如“是”吗?你没有发送短信。谷歌“this+define”如果你希望得到我的进一步帮助,你需要提高你的努力。请具体说明您不了解的内容,因为我不打算解释我原始评论中的每个单词。不幸的是,FileBackedOutputStreams不允许您指定创建临时文件的文件夹,而是让我自己来创建!可能重复的