私が次のことをするとき:
public double[] someFn()
{
double[][] b = new double[5][5];
return b[2];
}
バッファ b の残りはごみ箱の準備ができていますか、それとも 2 行目への使用中の参照が配列 b 全体の収集を停止しますか?
ジェネリック配列について話しているので、ファイナライズをテストできません…</p>
私が次のことをするとき:
public double[] someFn()
{
double[][] b = new double[5][5];
return b[2];
}
バッファ b の残りはごみ箱の準備ができていますか、それとも 2 行目への使用中の参照が配列 b 全体の収集を停止しますか?
ジェネリック配列について話しているので、ファイナライズをテストできません…</p>
はい、 の各要素b
はへの単なる参照double[]
です。それぞれが独立したオブジェクトへの参照である可能性があります。または、複数の要素が同じ配列を参照するか、null 値を持つ可能性があります。
要素からそれを含む配列への「バックリンク」はありません。
基本的に、「多次元」配列は、要素の型がたまたま別の配列である通常の配列と考える必要があります。たとえば、次のようになります。
String foo() {
String[] array = getStrings();
return array[0];
}
メソッドによって返される文字列参照は、配列について何も認識せず、それが参照する文字列オブジェクトも認識しません。配列の配列とまったく同じ方法です。
b の他の要素は、 someFn() が返された後に gc される準備ができています。これは、それらの参照を取得できないためです。私はそれを証明するために小さなプログラムを書きました:
public class GCDemo {
static class OneMB {
byte[] data = new byte[1024 * 1024];
String name;
public OneMB(String name) {
this.name = name;
}
protected void finalize() throws Throwable {
System.out.println(name + " gc-ed");
}
}
public static OneMB[] someFn() {
OneMB[][] b = new OneMB[3][3];
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b[i].length; j++) {
b[i][j] = new OneMB(i + "-" + j);
}
}
return b[2];
}
public static void main(String[] args) throws InterruptedException {
OneMB[] b2 = someFn();
System.gc();
System.gc();
Thread.sleep(6000);
System.out.println("after b2 is released");
b2 = null;
System.gc();
Thread.sleep(2000);
}
}
出力は
0-2 gc-ed
1-2 GC 教育
1-1 gc-ed
0-1 gc-ed
0-0 GC-ED
1-0 GC-ED
b2 リリース後
2-2 gc-ed
2-1 gc-ed
2-0 GC-ED