-2

このように ByteArrayOutputStreams を使用してソケット経由で画像を送信しています。

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

すべて正常に動作し、画像は最終的に 130kb のようになり、このように受け取ります

int nbrToRead = Integer.parseInt(slave.input.readLine().trim());
            int old = slave.socket.getReceiveBufferSize();
            slave.socket.setReceiveBufferSize(nbrToRead);
            byte[] byteArray = new byte[nbrToRead];
            int nbrRd = 0;
            int nbrLeftToRead = nbrToRead;
            while (nbrLeftToRead > 0) {
                int rd = slave.socket.getInputStream().read(byteArray, nbrRd, nbrLeftToRead);
                if (rd < 0)
                    break;
                nbrRd += rd; 
                nbrLeftToRead -= rd;
            }

            ByteArrayInputStream byteArrayI = new ByteArrayInputStream(byteArray);

            BufferedImage img = ImageIO.read(byteArrayI);

うまく機能しますが、Java のメモリ ヒープに送信されるすべての画像が 50 MB ほど増加します。receivebuffersize を設定しようとしましたが、それでもそのままです。ヒープが最大になり、しばらく留まってから停止します。

バッファをクリアして、バイトを受信したときにそれらを破棄するにはどうすればよいですか?

4

5 に答える 5

1

いくつかのことが頭に浮かびます:

  • オブジェクトへの参照を保持している可能性があり、ガベージ コレクションによってクリーンアップされません。作業を行っているクラスがシングルトンの場合、これは非常に一般的な問題です。
  • 使用している IO クラス (BufferedInputSteam など) で必ず close() を呼び出してください。
于 2012-08-14T16:15:37.340 に答える
0

すべてのメソッドを示したわけではありませんが、次の画像を待っている間、スコープ内に大容量メモリのローカル変数がある可能性があります。

これを試して:

// after you've finished with the input, dereference the memory-heavy objects...
byteArray = null;
byteArrayI = null;

また、スレッドを呼び出して生成することにより、JVMをガベージコレクションに「ナッジ」することができます(ガベージコレクションにすることはできません) 。System.gc()nullだけでは機能しない場合は、これを追加してみてください

System.gc(); // "suggest" garbage collection to execute
Thread.yield(); // I have seen this encourage garbage collection to execute
于 2012-08-14T17:40:27.160 に答える
0

Connectionを保持することに賭けても構わないと思っていますObjectOutputStream。それが本当なら、あなたはreset()そのストリームを呼び出す必要があります。

于 2012-08-14T18:21:18.387 に答える
0

コメントしましたが、それも答えにしています。

インメモリ を作成するときは、それらを使い終わったときにそれらBufferedImageを呼び出す必要があります。flush()あなたのメモリリークがそこから来たのではないかと強く疑っています。

そして、Malache が言ったように、すべて (BufferedImages、I/O 参照など) にgc、それらの作品に対するいかなる種類の参照も残さないようにしてください。

System.gc()物理メモリがプログラムよりも実際に小さいという状況でない場合は、解決策ではないmemory-leak-freeため、自分で動作させる前に試してみる必要がありますgc

于 2012-08-15T07:07:07.320 に答える
0

参照が残っているとイメージがメモリに保持されるため、オブジェクトを送信したら、オブジェクトが逆参照されていることを確認してください。そのオブジェクトのすべてのインスタンスを に設定することで、これを行うことができますnull

さらに、呼び出しflush()close()完了時にメモリ使用量を大幅に改善できます。

これが役立つことを願っています!

于 2012-08-14T16:50:50.687 に答える