3

非常に奇妙な問題に遭遇しました。以下のコードの一部を書いています。

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 は、サウンドを byteArrayOutputStream に録音している TargetDataLine です。私のテストでは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 に到達できませんでした。

このアプレットはインターネット上で実行されるため、メモリ サイズを設定しても役に立ちません。クライアントのコンピュータに設定するにはどうすればよいですか?

4

5 に答える 5

6

問題は、すべてのデータをメモリに保持しているため、JVMのメモリが不足していることです。ヒープスペースを拡張すると、さらに長いオーディオで作業する必要が生じるまで一時的に役立ちます。

1つのアイデアは、を一時的なものに交換することByteArrayOutputStreamです。これは、すべてのオーディオデータをメモリに保持する必要はありません。さらに優れたソリューションは、データが特定のしきい値を超えた場合にのみ一時ファイルにデータを保存するGuavasです。FileOutputStreamFile FileBackedOutputStream

別の解決策は、各バッファの波形を直接更新することです。オーディオデータを含むバッファを受信するだけのメソッドを作成し、それを波形の現在の状態に適用します。これにより、オーディオデータを保存する必要がまったくなくなります。

于 2012-08-22T12:35:23.220 に答える
2

この問題は、Hotspot JVM のヒープのサイズの上限が固定されているために発生します。デフォルトの制限はプラットフォームによって異なりますが、40Mb まで低くなる場合があります。

あなたがしているのは、オーディオ ストリームから大量のデータを読み取り、それらをメモリにバッファリングすることです。ヒープには上限があるため、アプリケーションは最終的にその上限に達し、結果はOutOfMemoryError例外になります。

-Xmx明らかな解決策は、オプションを使用して JVM の最大ヒープ領域を増やすことです。(このオプションの詳細については、java コマンドのマニュアル エントリを参照してください。) ただし、ハードウェア、OS、および 64 を使用しているかどうかによって、JVM ヒープを作成できる大きさには最終的な制限があります。ビットJVM。

また、音声データをファイルに保存したり、圧縮または縮小しようとしたりすることもできますが、これらはすべてグラフ化をより複雑にします。

于 2012-08-22T12:45:00.573 に答える
1

他の人は問題の原因について議論しています。

それを解決するには、次のいずれかを行います。

  1. バイトを少しずつ描画するか、または..
  2. 単一の を 1 つBufferedImage格納し、バイトを小さなチャンクで取得して、すぐに画像に描画します。

最初の手法は、このYou Tube ビデオに見られるような結果になる可能性があります

サウンドトレース

于 2012-08-22T12:48:31.223 に答える
0

それは間違いなくあなたの記憶を満たし、その振る舞いはコンピュータによって異なります。あなたができることは、いくつかを使用FileOutputStreamしてそれにデータを書き込み、ループが終了したらそこからデータをプルしてに変換することwavです。また、バイトの小さなパケット(できれば4096)でデータを書き込みます。の長さがtempBuffer4096を超えないようにします。

お役に立てれば..

于 2012-08-22T12:35:43.063 に答える
0

JVMヒープ スペースを増やすか、サウンド データを圧縮してメモリの消費を抑えることができます。

于 2012-08-22T12:29:33.207 に答える