3

Interactive Brokers Java APIの上に構築された最初の Java プログラムを作成しました。それは重要かもしれないし、そうでないかもしれません。メインの API クラスをいくつかの新しいクラスで拡張しました。

プログラムは、リモート サーバーに対してデータ クエリを実行しています。サーバーが応答すると、受信したデータをローカルの MySQL データベースに記録します。プログラムがデータのログ記録を完了すると、プログラムは次のデータ要求を行います。

数百のサーバー要求を行った後、プログラムをしばらく実行したままにした後、問題が発生しました。このエラーが表示され、プログラムは実行を継続しません。

java.lang.OutOfMemoryError: Java heap space

私はいくつかの調査を行い、読んだ内容から、プログラムは多くの新しい変数を作成しており、古い価値のない変数を破壊していないと結論付けています。私は開発に Netbeans を使用しているので、Netbeans プロファイラーを使用して、これが当てはまるかどうかを調べました。ここの写真を見てください:

ここに画像の説明を入力

かなり長い間プログラムを実行した後、ますます多くのメモリが によって使い果たされByteます。ですから、私の理論はまだ正しいようです。

ここからどこへ行けばいいのかわからない。クラスまたは特定の変数への参照はなく、変数の型のみです。問題の原因を特定するにはどうすればよいですか?

アップデート

コメントで BigMike が言及した特定の問題を修正しました。以前は、JDBC MySQL コネクタ API で多くのステートメントを作成していて.execute()、ステートメントを実行するために呼び出していましたが、ステートメントを で閉じていませんでした.close()

statement.close()各実行後に呼び出しを追加することを確認したところ、プログラムの実行が大幅に改善されました。このプログラムの RAM 使用量を見ると、問題は解決したようです。また、Java heap spaceエラーが表示されなくなりました。これは素晴らしいことです。

ありがとう!

4

2 に答える 2

2

単純に何が間違っているのかを言うのは非常に困難です。

必要がなくなったときに閉じられていない、開いているストリームに関係している可能性があります。特にデータをストリームに読み込む場合は、リソースを割り当てるメソッド (ファイル、データベースなどからの読み取り) を再確認し、finally 句でそれらのストリームを閉じていることを確認してください。

それとは別に、どのメソッドがより頻繁に呼び出されているかなどを試してプロファイルし、問題をコードの特定の部分に絞り込むことができます。

ガベージ コレクションがどのように機能するか、および OutOfMemoryErrors の原因について合理的に説明しているサイトを見つけました。

http://www.kdgregory.com/index.php?page=java.outOfMemory

それを読んだ場合、Object[] と byte[] の高い割り当てへの特定の参照があり、正しい方向を示している可能性があります。

于 2013-03-14T15:36:06.057 に答える
1

一般的に言えば、これは次の 2 つの理由のいずれかで発生します。

  1. アプリケーションでメモリ リークが発生し、アプリケーションがガベージ コレクション用のアイテムを解放できず、時間の経過とともに JVM のメモリが不足する。

  2. アプリケーションが、使用可能なメモリよりも多くのメモリを必要とする 1 回限りの操作を試みたため、その操作のために JVM のメモリが不足しました。

あなたの出力は、メモリの大部分が文字通り100万以上の小さなバイト配列によって消費されていることを示しているように見えるので、私の推測では、#1がおそらく原因です。ただし、これを確認するには、アプリケーションを再起動し、時間の経過に伴うメモリ消費を監視します。跳ねたり跳ねたりしますが、実際には消費の動向を注視するだけで十分です。消費平均が時間の経過とともに上昇し続ける場合は、メモリ リークが発生しています。

この問題を解決するには、通常、ソース コードが必要であり、問​​題のあるオブジェクトが作成され、使用され、最後に使用されてからずっと「保存」されているコードの部分を見つける必要があります。解決策は、それらを保存しないようにコードを修正することです。HashMap、List、およびその他のコレクションは、多くの場合、メモリ リークの問題に加担しています。

ソースコードがない場合は、メモリ消費の傾向を測定し、アプリケーションのシャットダウンと再起動をスケジュールして、アプリケーションがダウンタイムを選択するのを見るのではなく、ダウンタイムを選択するように効果的に「クロックをリセット」することができます。

それが 1 回限りの操作である場合 (データを考慮していない可能性が高い)、トリガー イベントが発生するまで、メモリ消費量の増加傾向は見られません。このような場合、ソース コードにアクセスして、アプリケーションが通常の動作パラメータから大きく外れて大きくなるデータを処理しないように保護する必要があります。たとえば、ネットワークからのメッセージの読み取りには、通常、数 KB しかかかりませんが、例外的な状況では、クライアントが永久に送信する場合があります。このような場合、メッセージの最大サイズ制限である 10 MB を超えると、メッセージ処理を強制終了し、メッセージをエラーで破棄します。

後者のシナリオでソース コードにアクセスできない場合、唯一の望みは、入ってくるアップセットを特定し、誤った送信のソースを突き止め、それを操作して出力の過負荷を防ぐことです。

これらの手法へのアプローチ方法にはさまざまなバリエーションがありますが、いくつかのアイデアが得られました。

于 2013-03-14T16:53:34.693 に答える