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