この質問は最初は些細なことのように思えるかもしれませんが、これを実装し始めてから、奇妙な OutOfMemory 問題が発生しています。Java ヒープ ダンプを調べたところ、メモリ リークが ObjectOutputStream 変数に関連していることがわかりました。コードは次のとおりです。
コンストラクターで、入力/出力ストリーム変数を保持するフィールド変数を設定しています。それに加えて、特にカスタム オブジェクトと純粋なプリミティブで IO を実行する場合に備えて、他に 2 つの変数セットを作成しています。
public SingleServer(Socket s, int maxThreads) {
client = s;
serversCreated.incrementAndGet();
try {
is = client.getInputStream();
os = client.getOutputStream();
ois = new ObjectInputStream(is);
oos = new ObjectOutputStream(os);
dis = new DataInputStream(is);
dos = new DataOutputStream(os);
} catch (Exception e) {
// ...
}
print("Client Connected");
}
以前は、オブジェクト出力ストリームである OOS のストレージしかありませんでした。では、なぜ私がこれらのフィールドを作成するのに苦労しているのかと疑問に思われるかもしれません。答えは、プリミティブの送信を、カスタム オブジェクトの送信と純粋なバイトの送信から分離したかったということです。こういう切り分けはJavaでいいと思っていました。
私が気付いているのは、突然、予測が困難なオブジェクトが OutOfMemory エラーを引き起こし、プログラムがクラッシュすることです。IO クラスにこれらのさまざまなデコレータをすべて使用することを忘れることができることはわかっていますが、これらのメモリ不足エラーが発生する理由を理解したいですか?
- IO ストリームを複数回装飾することに根本的な問題がありますか?
- ストリームを実際に使用する前にオンデマンドで装飾し、不要になったときにガベージ コレクターに処理させる方がよいでしょうか?
- 上記の質問の延長として、すべてがメモリエラーなしで機能していた前に、私が実際に保存したオブジェクトは OOS だけでした。しかし、現在、メモリ エラーは OOS に関連しています。DOS や OS を作成すると、ガベージ コレクタが正しく動作しなくなりますか?