記憶から外:素人の用語では、それは十分なメモリがないことを意味します。たとえば、無限のループで大きなオブジェクトを絶えず作成すると、すぐにメモリオーバーフローが発生します。
メモリの漏れ:オブジェクトが使用されなくなったときにオブジェクトにメモリを割り当てた後のメモリのタイムリーなリリースを指し、メモリユニットが占有され、実際の使用可能なメモリがメモリリークのように縮小されます。
サブストリング方法によって引き起こされるメモリリーク
Substring(int beginindex、int endndex)は文字列クラスのメソッドですが、この方法はJDK6とJDK7で完全に異なって実装されています(どちらも同じ効果を達成します)。 JDK1.6でのサブストリングの不適切な使用は、深刻なメモリリークの問題につながる可能性があるため、実装の詳細を理解することで、それらをよりよく使用するのに役立ちます。
1。サブストリングの役割
Substring(int beginindex、int endindex)メソッドは、親文字列のbeginindexから始まり、endindex-1で終了するサブストリングを返します。親文字列の添え字は0から始まり、サブストリングにはbeginindexが含まれ、endindexではありません
string x = "abcdef"; x = str.substring(1,3); system.out.println(x);
上記のプログラムの出力は「BC」です
2。実装原則
文字列クラスは不変です。上記の2番目の文でxが再割り当てされると、新しい文字列オブジェクトが指されます。ただし、正確な説明はなく、ヒープで発生する実際の状況を表します。サブストリングが呼ばれるときに実際に起こることは、2つの違いです。
JDK6のサブストリング実装
文字列オブジェクトは、チャーアレイとして保存されます。文字列クラスには、実際の文字配列、配列の開始位置、文字列の文字の数を保存するためにそれぞれ使用されるchar [] value、int offset、およびintカウントの3つのフィールドがあります。これらの3つの変数は、文字列を決定できます。サブストリングメソッドが呼び出されると、新しい文字列が作成されますが、上記のchar配列値は元の親アレイの値を使用します。親と子の配列の唯一の違いは、カウントとオフセットの値が異なることです。
JDK6のサブストリング実装のソースコードをご覧ください。
public string substring(int vertingindex、int endindex){if(beginIndex <0){throw new StringIndexOfBoundSexception(beginIndex); } if(endindex> count){new StringIndexOutofBoundSexception(EndIndex); } if(beginIndex> endIndex){new StringIndexOutOfBoundSexception(EndIndex -beginIndex); } return((beginindex == 0)&&(endindex == count))?これ:new String(offset + beginindex、endindex -beginindex、value); //親文字列と同じchar配列値を使用するために使用されます} string(int offset、int count、char value []){this.value = value; this.offset = offset; this.count = count; }string str = "abcdefghijklmnopqrst"; string sub = str.substring(1、3); str = null;
このシンプルなプログラムには、2つの文字列変数strとsubがあります。サブ文字列は、親文字列strによって取得されます。上記のプログラムがJDK1.6で実行されている場合、アレイのメモリスペース割り当てがヒープで実行されることがわかっています。サブとSTRの内部char配列値は同じです。つまり、文字a〜文字tで構成される上記のcharアレイです。 STRとSUBの唯一の違いは、ArrayのBeginIndexと文字長の違いです。 3番目の文では、STR参照を空にします。これは、STRで占有されているスペースを解放することを目的としていますが、現時点では、GCはサブストリング内でまだ参照されているため、この大きなチャーアレイをリサイクルできませんが、サブはこの大きなアレイのごく一部のみをインターセプトします。 STRが非常に大きな弦である場合、この廃棄物は非常に明白であり、パフォーマンスの問題を引き起こす可能性さえあります。この問題を解決できます。
ストリングスプライシングテクノロジーを使用して、新しい文字列を作成します。この新しい文字列は、新しい内部チャーアレイを使用して実際に必要な文字を保存するため、親配列のchar配列は他のソースによって参照されません。 STR = NULLとし、STRが占有するスペース全体が次にGCがリサイクルされるときにリサイクルされます。しかし、このように書くことは明らかに見栄えが良いので、JDK7では、サブストリングが再実装されています。
JDK7のサブストリング実装
JDK7でのサブストリングの実装の改善。これにより、実際には、サブストリングの文字を保持するための傍受されたサブストリングのために、ヒープに新しいチャーアレイが作成されます。
JDK7の文字列クラスのサブストリング方法の実装ソースコードを確認します。
public string substring(int vertingindex、int endindex){if(beginIndex <0){throw new StringIndexOfBoundSexception(beginIndex); } if(endindex> value.length){new stringindexOutofboundsexception(endindex); } int sublen = endIndex -beginIndex; if(sublen <0){新しいstringindexOutofboundsexception(sublen); } return((beginindex == 0)&&(endindex == value.length))?これ:new String(Value、beginIndex、Sublen); } public string(char value []、int offset、int count){if(offset <0){show new StringIndexOutOfBoundSexception(offset); } if(count <0){新しいstringindexOutofboundsexception(count); } //注:オフセットまたはカウントが-1 >>> 1に近い場合があります。 if(offset> value.length -count){new StringIndexOutOfBoundSexception(offset + count); } this.value = arrays.copyofrange(value、offset、offset+count); }アレイクラスのコピーフレージメソッド:
public static char [] copyofrange(char [] original、int、int to){int newlength = to -from; if(newLength <0)を新しいIllegalargumentException(from + ">" + to); char [] copy = new char [newlength]; //新しいchar array system.arraycopy(original、from、copy、0、math.min(original.length- from、newlength))を作成することです。コピーを返します。 }サブストリング用に新しいチャーアレイが作成され、文字がサブストリングに保存されることがわかります。このようにして、子の文字列と親文字列の間に必要な接続はありません。親文字列の参照が無効な場合、GCは親文字列によって占有されているメモリスペースをタイムリーにリサイクルします。
要約します
上記は、Javaのサブストリング法によって引き起こされるメモリリークの完全な説明です。私はそれが誰にでも役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!