16

substring Stringクラスのメソッドはメモリリークを引き起こすと言われています。それは本当ですか?どのように?その代替手段は何ですか?
特に答えを探してい
ます。Javaでメモリリークを引き起こす可能性のある他のすべてのものは何ですか?これは、コーディング中に注意を払うのに役立ちます。

4

4 に答える 4

31

JDKの過去のバージョンでは、メソッドの実装により、char配列全体への参照を保持するsubstring新しいオブジェクトが作成され、コピーが回避されていました。Stringしたがって、1つの文字列だけで非常に大きな文字配列への参照を誤って保持する可能性があります。これが引き起こす可能性のあるバグの例を次に示します。

この方法は現在変更されており、この「リーク」はもう存在しません。

古いJDK(OpenJDK 7、Update 6より古い)を使用し、後substringに最小限の文字列を使用する場合は、別の文字列を使用するコンストラクターを使用します。

String s2 = new String(s1.substring(0,1));

2番目の質問については、「Javaでメモリリークを引き起こす可能性のある他のこと」に関して、建設的な方法で答えることは不可能です。Java標準ライブラリには、オブジェクトへの非表示の参照を簡単に保持できるケースの多くのインスタンスはありません。一般的なケースでは、作成するすべての参照に注意してください。最も頻繁に発生する問題は、クリーンアップされていないコレクションまたは外部リソース(ファイル、データベーストランザクション、ネイティブウィジェットなど)で発生する可能性があります。

于 2013-03-25T10:04:31.280 に答える
12

このsubstring()メソッドは、に新しい文字配列を割り当てるのではなく、既存のchar配列にウィンドウ付きのをString生成するだけです。これはフライウェイトパターンの実装であり、最適化と見なされていました。String

したがって、巨大なString(char配列)を作成してからサブ文字列を作成すると、元の文字列をガベージコレクションしても、元のchar配列は残ります(たとえば、2文字のサブ文字列があると思われるにもかかわらず)。この問題は、(たとえば)大量の入力データ(おそらくXMLファイル)を解析し、を介して少量のテキストを抽出するときによく発生します。substring()

一見冗長なString(String str)コンストラクター( !StringをとるコンストラクターString)を使用すると、新しい(場合によっては小さい)char配列が割り当てられ、元のコンストラクターをガベージコレクションできるため、これが解決されます。

この動作はJava7u6から変更されていることに注意してください。

于 2013-03-25T10:05:07.533 に答える
8

文字列の部分文字列は、予想よりも多くのメモリを保持する可能性があります。このメモリは正常に回復できるため、メモリリークではありません。

最も簡単な解決策は、これを行わない最新バージョンのJava7を使用することです。これはOracleから無料でサポートされている唯一のバージョンであるため、とにかくこれを行うことを検討する必要があります。

そのため、Java 7アップデート5で「修正」されました。私見では、実装を単純化するほどの修正ではありません。すべての部分文字列のコピーを取得すると、はるかに多くの作業が必要になり、より多くのメモリを消費する可能性がありますが、心配することが1つ少なくなることを意味します。

Javaでメモリリークを引き起こす可能性のある他のすべてのものは何ですか?

任意のオブジェクトをクリーンアップできるため、C /C++という用語の意味でメモリリークを作成することはできません。あなたができることは、オブジェクトを誤って保持することです。この一般的な例は、JDBCリソースなどのリソースを閉じるのを忘れていることです。これにより、予期しない方法でメモリを保持する可能性があります。

于 2013-03-25T10:04:57.553 に答える
5

Stringオブジェクトでは、を呼び出すsubstringと、valueプロパティは2つの文字列間で共有されます。

したがって、大きな文字列からサブ文字列を取得して長期間保持すると、大きな文字列はガベージコレクションされません。実際には、メモリリークが発生する可能性があります。

于 2013-03-25T10:05:55.977 に答える