gcがjava.lang.refパッケージのクラスでどのように動作するかテスト中です:Javaガベージリファレンスクラスの収集
以下は私のコードです。
public static void main(String [] args) {
int mb = 1024*1024;
//Getting the runtime reference from system
Runtime runtime = Runtime.getRuntime();
System.out.println("##### Heap utilization statistics [MB] #####");
ArrayList<Object> sb = new ArrayList<Object>();
for(int i =0; i < 5000000; i++){
sb.add(new Object());
if(i % 1000 == 0) {
System.out.println(i);
}
}
SoftReference<ArrayList> wr = new SoftReference<ArrayList>(sb);
// System.gc()
//Print used memory
System.out.println("Used Memory:"
+ (runtime.totalMemory() - runtime.freeMemory())/mb);
//Print free memory
System.out.println("Free Memory:"
+ runtime.freeMemory()/mb);
//Print total available memory
System.out.println("Total Memory:" + runtime.totalMemory()/mb);
//Print Maximum available memory
System.out.println("Max Memory:" + runtime.maxMemory()/mb);
}
それは結果:
Used Memory:95,
Free Memory:28,
Total Memory:123,
Max Memory:247
そして、私は、コードを "にSystem.gc()" にコメントを元に戻した、とreran、結果は
Used Memory:1,
Free Memory:122,
Total Memory:123,
Max Memory:247
だったうん、まず、 ArrayListのインスタンスが収集されました。私が知っているように、SoftReferenceだけで参照されるインスタンスは柔らかく、左ヒープスペースがないためにGCが本当に必要なときに収集されます。コードの最初の結果の左スペースは約150(フリーmem 28 +左max mem 124)でした。私はArrayListのインスタンスが収集された理由を理解していません。
そして第二に、私は変更すると、コード実行:
sb.add(new Object()); -> sb.add(new StringBuffer(i));
をし、それが結果:
Used Memory:245,
Free Memory:2,
Total Memory:247,
Max Memory:247
なぜこれが違います?
そして最後に、私は修正して再度、コードを実行した:それは結果 を
SoftReference<ArrayList> wr = new SoftReference<ArrayList>(sb);
から
WeakReference<ArrayList> wr = new WeakReference<ArrayList>(sb);
へ:
Used Memory:245,
Free Memory:2,
Total Memory:247,
Max Memory:247
を私がしたのArrayListのインスタンスを推測していましたインスタンスがWeakReferenceによってのみ参照されたため収集されたので、これらのw弱い到達可能。しかし、彼らは集められなかった。
ここで、リファレンスの作業方法についての私の理解が間違っていると仮定します。
私は誰に教えてください。
Thxを^^
これは実際に実行したコードと同じであってはなりません。 'sb'参照自体を決して削除しないので、' ArrayList'は確かに収集されません。 2回目と3回目のテストの間に 'sb = null;'行を削除していませんか? – Dolda2000
オブジェクトがまだrefrenceを持っている場合、最初のgcはオブジェクトを削除しません。 System.gc()が実行されるかどうかは、jvmに依存するかどうかは決して確認できません。 – Jois
Doldaが指摘したように、あなたは 'ArrayList'への強い参照を保持しています。もしあなたが見ている相違はおそらく 'ArrayList'自体が繰り返しサイズ変更されているためです。これは、あなたのループ中に徐々に大きな配列を割り当てます。 (そして、それらの配列はガベージコレクションされているものです。)また、 'StringBuffer'についてのあなたの質問が分かりません。 'StringBuffer'は、内部に配列を持っているので、普通の' Object'よりはるかに大きくなります。それゆえ、それははるかに多くのメモリを使用することが期待されるべきではありませんか? – Radiodef