[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 10315] GC の対象になるのは?



以下の問題がどうしてもわかりません。どなたか解説していただけますか? (_ _)


出展:SUN 教科書 Java 2 (試験番号:310-025)
      ビル・ブローデン著、有限会社トップスタジオ 訳編、翔泳社 発行

問題:(210ページ)
  問題8-7
  次のメソッドでは、カウントダウンの数値を出力するために複数のStringオブジェ
  クトが作成されます。
  
  1. public void countDown()
  2.   for( int i = 10 ; i >= 0 ; i-- ){
  3.     String tmp = Integer.toString( i );
  4.     System.out.println( tmp );
  5.   }
  6.   System.out.println("BOOM!");
  7. }

※1行目に"{"がないのは本の通り。脱字と思いますが。

  6行目に処理が進んだ時点で、3行目で作成されたStringオブジェクトのいくつがガ
  ベージコレクションの対象となりますか(System.outオブジェクトに参照がないと
  仮定します)。

  A. なし
  B. 1個
  C. 10個
  D. 11個



解説には、以下の通り書かれています。

  解説
  正解は選択肢Cです。11個のStringオブジェクトのうち最後の1つだけにまだ参照が
  あります。したがって選択肢A、B、Dは不正解です。6行目ではtmp変数はスコープ
  の外になりますが、それでもtmpには最後のStringオブジェクトへの参照が格納さ
  れています。この点でも選択肢Dは不正解です。


私は、Dかと思いましたが間違いのようです。ん? と思って2つほど実験してみまし
た。

■実験1 javap -c
  上記メソッドのみを記述したGcTestクラスをGcTest.javaというファイルに保存し、
  コンパイルしてから javap -c してみました。(J2SE SDK v1.3.1_04 on WinNT)
-------------------------------------------------------------
Compiled from GcTest.java
public class GcTest extends java.lang.Object {
    public GcTest();
    public void countDown();
}

Method GcTest()
   0 aload_0
   1 invokespecial #1 <Method java.lang.Object()>
   4 return

Method void countDown()
   0 bipush 10
   2 istore_1
   3 goto 21
   6 iload_1
   7 invokestatic #2 <Method java.lang.String toString(int)>
  10 astore_2
  11 getstatic #3 <Field java.io.PrintStream out>
  14 aload_2
  15 invokevirtual #4 <Method void println(java.lang.String)>
  18 iinc 1 -1
  21 iload_1
  22 ifge 6
  25 getstatic #3 <Field java.io.PrintStream out>
  28 ldc #5 <String "BOOM">
  30 invokevirtual #4 <Method void println(java.lang.String)>
  33 return
-------------------------------------------------------------

これを見ると、変数2番にtmpが格納されているようです。行番号10で毎回上書きされ
ていることと、2番にtmpになるもの以外代入されていなさそうなので、「最後の1個
の参照のみが残っている」のか、と理解(?)できなくもないですが…。

■実験2 WeakReferenceを使って参照の確認。

下記プログラムを実行すると、weak1では11個すべて値が保持されており、gc()後の
weak2では11個すべてnullになっていました。ってことは、スコープが外れても参照
が残っている(?)ことはわかりましたが、11個すべてがGCの対象になっているという
ことではないんですかね?

-------------------------------------------------------------
import java.lang.ref.WeakReference;

public class GcTest {
  public static void main(String[] args) {
    new GcTest().countDown();
  }
  
  public void countDown() {
    WeakReference[] weak = new WeakReference[11];
    
    for (int i = 10; i >= 0; i--) {
      String tmp = Integer.toString(i);
      weak[i] = new WeakReference(tmp);
      System.out.println(tmp);
    }
    System.out.println("weak1:");
    for (int i = 10; i >= 0; i--) {
      System.out.println("weak[" + i + "]=" + weak[i].get());
    }
    
    System.gc();
    
    System.out.println("weak2:");
    for (int i = 10; i >= 0; i--) {
      System.out.println("weak[" + i + "]=" + weak[i].get());
    }
    System.out.println("BOOM");
  }
}
-------------------------------------------------------------
実行結果:
10
9
8
7
6
5
4
3
2
1
0
weak1:
weak[10]=10
weak[9]=9
weak[8]=8
weak[7]=7
weak[6]=6
weak[5]=5
weak[4]=4
weak[3]=3
weak[2]=2
weak[1]=1
weak[0]=0
weak2:
weak[10]=null
weak[9]=null
weak[8]=null
weak[7]=null
weak[6]=null
weak[5]=null
weak[4]=null
weak[3]=null
weak[2]=null
weak[1]=null
weak[0]=null
BOOM
-------------------------------------------------------------

---------------------------------------------------
(株)PFU システム事業部ソフトウェア統括部第二開発部
      福嶋 航  w.fukushima@xxxxxxxxxxxxxxx