0

読み取りと書き込みを行うソケット クライアントがあるとします。操作の送受信を行う 2 つのスレッドがあります (要求送信者/応答受信者)。これらのスレッドは、Junit テスト ケースを 1 つずつ実行しています (ストレス テストのように、単純な問い合わせ)。私の場合、クライアントを実行しています。これにより、DB エンドとそれ自体の間でソケット通信が確立されます。このロジックでは、リクエストの送信側スレッドが DB エンドにリクエストを送信し (リクエストをソケットに書き込みます)、受信側スレッドがソケットを読み取ってレスポンスを受け取ります (ソケットからレスポンスを読み取ります)。実際の問題はランダムに表示されます。リクエスト送信者スレッドが request を送信した場合、レスポンス受信者は、送信したリクエストの相手側からのレスポンスをまだ受信していないとします。

byte[] ofsRes = new byte[size]; 

この部分は jVm Out of memory エラーが発生します。応答レシーバースレッドの同時読み取りがこの問題を引き起こし、ヒープ内により多くのサイズのバイトオブジェクトを割り当てていると思われます。

ソケットからのデータの読み取り

int size = dataInputStream.readInt();

誰かがこのメモリ不足エラーを解決するのを手伝ってくれますか/スレッドの同時実行である可能性があります.

private static class ResponseReceiver implements Runnable {

        private InputStream _in;
        private List<String> _responses = new ArrayList<String>();
        private int _expectedCount;
        private volatile boolean _finished = false;

        public ResponseReceiver(InputStream in, int expectedCount) {
            _in = in;
            _expectedCount = expectedCount;
        }

        public List<String> getResponses() {
            return _responses;
        }

        public void run() {
            DataInputStream dataInputStream = new DataInputStream(_in);
            try {
                while (true) {
                    _logger.info("_responses.size() >= _expectedCount : -> " + (_responses.size() >= _expectedCount) +
                            " : " + "_responses.size() -> " + _responses.size() + " : " + "_expectedCount -> " + _expectedCount);
                    if (_responses.size() >= _expectedCount) {
                        _finished = true;
                        return;
                    }
                    int size = dataInputStream.readInt();
                    _logger.info("size captured : " + size);
                    if (size > 0) {
                        int readSize = 0;
                        _logger.info( " ofsRes Creating with this size : " + size);
                        **byte[] ofsRes = new byte[size];**
                        while (size > 0) {
                            _logger.info( " Buffer Creating with this size : " + size);
                            byte[] buffer = new byte[size];
                            int bufferSize = _in.read(buffer);
                            _logger.info( " Reading data created Buffer Size : " + bufferSize);
                            System.arraycopy(buffer, 0, ofsRes, readSize,
                                    bufferSize);
                            readSize += bufferSize;
                            _logger.info( " readSize (readSize += bufferSize): " + readSize);
                            size -= bufferSize;
                            _logger.info( " size (size -= bufferSize): " + size);
                        }
                        _responses.add(new String(ofsRes));
                        _logger.info("ofsRes added..");
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("Error reading data from socket: "
                        + e.getMessage());
            }
        }
    }

実行順序のトレース:


2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: _responses.size() >= _expectedCount: -> false: _responses.size() -> 905: _expectedCount - > 1000 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: キャプチャされたサイズ: 1529 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test. socket.SocketClient$ResponseReceiver run INFO: ofsRes このサイズで作成中: 1529 May 27, 2013 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: Buffer このサイズで作成中: 1529 May 27 , 2013 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: 読み取りデータが作成されました バッファ サイズ: 1529 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket .SocketClient$ResponseReceiver 実行情報: readSize (readSize += bufferSize): 1529 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: サイズ (サイズ -= bufferSize): 0 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver実行情報: ofsRes が追加されました.. 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行 情報: _responses.size() >= _expectedCount: -> false: _responses.size() -> 906 : _expectedCount -> 1000

テスト ケースが応答を待って実行されていると仮定します * ** * ** (906)

2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.SocketClientTest ofsmlEnqSimpleTest13 INFO: OFSML 13 Simple Inquiry テストが進行中です...

別の1つのケースが開始されます

2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient 送信情報: System.currentTimeMillis(): -> 1369635313336: System.currentTimeMillis()- startTime: -> 0: タイムアウト -> 5000 : startTime -> 1369635313336: 条件: true 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver INFO を実行: _responses.size() >= _expectedCount: -> false: _responses。 size() -> 0 : _expectedCount -> 1

*異なる読み取りの可能性があると仮定します*

2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行 情報: キャプチャされたサイズ: 195399 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket. SocketClient$ResponseReceiver 実行 情報: キャプチャされたサイズ: 1195528239 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行 情報: ofsRes このサイズで作成: 195399 2013 年 5 月 27 日 11:45 :13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run 情報: ofsRes このサイズで作成中: 1195528239 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: このサイズでバッファを作成しています: 195399 スレッド "Thread-22" で例外が発生しました java.lang.OutOfMemoryError: Java ヒープ領域 com.xxx.tocf.test.socket.SocketClient$ResponseReceiver.run(SocketClient.java:147) で java.lang.Thread.run(Thread.java:662) 2013 年 5 月 27 日 11:45:13 AM com. xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: データ読み込み中 Buffer Size : 759 May 27, 2013 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: readSize (readSize += bufferSize): 759 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: サイズ (サイズ -= bufferSize): 194640 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: このサイズで作成中のバッファ: 194640 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報:読み取りデータ作成バッファサイズ: 1533 May 27, 2013 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: readSize (readSize += bufferSize): 2292 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver 実行情報: サイズ (サイズ -= bufferSize): 193107 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test.socket.SocketClient$ResponseReceiver run INFO: このサイズで作成中のバッファ: 193107 2013 年 5 月 27 日 11:45:13 AM com.xxx.tocf.test .socket.SocketClient$ResponseReceiver run INFO: 読み取りデータが作成されました バッファ サイズ: 767SocketClient$ResponseReceiver run INFO: データの読み取り中に作成されたバッファ サイズ: 767SocketClient$ResponseReceiver run INFO: データの読み取り中に作成されたバッファ サイズ: 767

4

1 に答える 1

0

送信側スレッドが相手側からの特定の応答を待っていると仮定します。

なんで?すでに受信スレッドがあります。

その間、リクエストをプッシュして実行手段を実行し始める他のテストケース(つまりスレッド)がある場合、レスポンスレシーバースレッドは次のロジックを持ちます

byte[] ofsRes = new byte[size];

の値はsizeどこから来たのですか? そして、送信側スレッドと受信側スレッドの両方が応答を読み取ろうとすることの正確な意味は何ですか? あなたが何を期待しているのかはわかりませんが、何起こるかは完全に未定義です。これは意味がありません。誰が応答を読むべきかを決めて、彼らに読ませる必要があります。おそらく、送信者スレッドと受信者スレッドの間に何らかの同期を導入して、受信者が前の結果を受信するまで送信者が次の要求を送信しないようにする必要があります。さらに良いのは、受信スレッドを取り除き、送信スレッドに独自の応答を受信させることです。

この部分は jVm Out of memory エラーが発生します。

もちろんそうなるでしょう。どこかから基本的にランダムな値を取得し、ランダムなsize量のメモリを割り当てようとしています。

応答レシーバースレッドの同時読み取りがこの問題を引き起こし、ヒープ内により多くのサイズのバイトオブジェクトを割り当てていると思われます。

もう一度。解決策は、それをしないことです。

于 2013-06-04T10:26:36.037 に答える