Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import java.lang.ref.WeakReference;
     18 import java.util.ArrayList;
     19 import java.util.List;
     20 
     21 /**
     22  * Some finalizer tests.
     23  *
     24  * This only works if System.runFinalization() causes finalizers to run
     25  * immediately or very soon.
     26  */
     27 public class Main {
     28     private static void snooze(int ms) {
     29         try {
     30             Thread.sleep(ms);
     31         } catch (InterruptedException ie) {
     32             System.out.println("Snooze: " + ie.getMessage());
     33         }
     34     }
     35 
     36     public static WeakReference<FinalizerTest> makeRef() {
     37         FinalizerTest ft = new FinalizerTest("wahoo");
     38         WeakReference<FinalizerTest> ref = new WeakReference<FinalizerTest>(ft);
     39         ft = null;
     40         return ref;
     41     }
     42 
     43     public static String wimpString(final WeakReference<FinalizerTest> wimp) {
     44         /*
     45          * Do the work in another thread, so there is no danger of a
     46          * conservative reference to ft leaking onto the main thread's
     47          * stack.
     48          */
     49 
     50         final String[] s = new String[1];
     51         Thread t = new Thread() {
     52                 public void run() {
     53                     FinalizerTest ref = wimp.get();
     54                     if (ref != null) {
     55                         s[0] = ref.toString();
     56                     }
     57                 }
     58             };
     59 
     60         t.start();
     61 
     62         try {
     63             t.join();
     64         } catch (InterruptedException ie) {
     65             throw new RuntimeException(ie);
     66         }
     67 
     68         return s[0];
     69     }
     70 
     71     private static void printWeakReference(WeakReference<FinalizerTest> wimp) {
     72         // Reference ft so we are sure the WeakReference cannot be cleared.
     73         FinalizerTest keepLive = wimp.get();
     74         System.out.println("wimp: " + wimpString(wimp));
     75     }
     76 
     77     public static void main(String[] args) {
     78         WeakReference<FinalizerTest> wimp = makeRef();
     79         printWeakReference(wimp);
     80 
     81         /* this will try to collect and finalize ft */
     82         System.out.println("gc");
     83         Runtime.getRuntime().gc();
     84 
     85         System.out.println("wimp: " + wimpString(wimp));
     86         System.out.println("finalize");
     87         System.runFinalization();
     88         System.out.println("wimp: " + wimpString(wimp));
     89 
     90         System.out.println("sleep");
     91         snooze(1000);
     92 
     93         System.out.println("reborn: " + FinalizerTest.mReborn);
     94         System.out.println("wimp: " + wimpString(wimp));
     95         System.out.println("reset reborn");
     96         Runtime.getRuntime().gc();
     97         FinalizerTest.mReborn = FinalizerTest.mNothing;
     98         System.out.println("gc + finalize");
     99         System.gc();
    100         System.runFinalization();
    101 
    102         System.out.println("sleep");
    103         snooze(1000);
    104 
    105         System.out.println("reborn: " + FinalizerTest.mReborn);
    106         System.out.println("wimp: " + wimpString(wimp));
    107         // Test runFinalization with multiple objects.
    108         runFinalizationTest();
    109     }
    110 
    111     static class FinalizeCounter {
    112       public static final int maxCount = 1024;
    113       public static boolean finalized[] = new boolean[maxCount];
    114       private static Object finalizeLock = new Object();
    115       private static volatile int finalizeCount = 0;
    116       private int index;
    117       static int getCount() {
    118         return finalizeCount;
    119       }
    120       static void printNonFinalized() {
    121         for (int i = 0; i < maxCount; ++i) {
    122           if (!FinalizeCounter.finalized[i]) {
    123             System.err.println("Element " + i + " was not finalized");
    124           }
    125         }
    126       }
    127       FinalizeCounter(int index) {
    128         this.index = index;
    129       }
    130       protected void finalize() {
    131         synchronized(finalizeLock) {
    132           ++finalizeCount;
    133           finalized[index] = true;
    134         }
    135       }
    136     }
    137 
    138     private static void allocFinalizableObjects(int count) {
    139       Object[] objs = new Object[count];
    140       for (int i = 0; i < count; ++i) {
    141         objs[i] = new FinalizeCounter(i);
    142       }
    143     }
    144 
    145     private static void runFinalizationTest() {
    146       allocFinalizableObjects(FinalizeCounter.maxCount);
    147       Runtime.getRuntime().gc();
    148       System.runFinalization();
    149       System.out.println("Finalized " + FinalizeCounter.getCount() + " / "  + FinalizeCounter.maxCount);
    150       if (FinalizeCounter.getCount() != FinalizeCounter.maxCount) {
    151         // Print out all the finalized elements.
    152         FinalizeCounter.printNonFinalized();
    153         // Try to sleep for a couple seconds to see if the objects became finalized after.
    154         try {
    155           java.lang.Thread.sleep(2000);
    156         } catch (InterruptedException e) {
    157         }
    158         System.out.println("After sleep finalized " + FinalizeCounter.getCount() + " / "  + FinalizeCounter.maxCount);
    159         FinalizeCounter.printNonFinalized();
    160       }
    161     }
    162 
    163     public static class FinalizerTest {
    164         public static FinalizerTest mNothing = new FinalizerTest("nothing");
    165         public static FinalizerTest mReborn = mNothing;
    166 
    167         private final String message;
    168         private boolean finalized = false;
    169 
    170         public FinalizerTest(String message) {
    171             this.message = message;
    172         }
    173 
    174         public String toString() {
    175             return "[FinalizerTest message=" + message +
    176                     ", finalized=" + finalized + "]";
    177         }
    178 
    179         protected void finalize() {
    180             finalized = true;
    181             mReborn = this;
    182         }
    183     }
    184 }
    185