/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; /** * Some finalizer tests. * * This only works if System.runFinalization() causes finalizers to run * immediately or very soon. */ public class Main { private static void snooze(int ms) { try { Thread.sleep(ms); } catch (InterruptedException ie) { System.out.println("Snooze: " + ie.getMessage()); } } public static WeakReference makeRef() { FinalizerTest ft = new FinalizerTest("wahoo"); WeakReference ref = new WeakReference(ft); ft = null; return ref; } public static String wimpString(final WeakReference wimp) { /* * Do the work in another thread, so there is no danger of a * conservative reference to ft leaking onto the main thread's * stack. */ final String[] s = new String[1]; Thread t = new Thread() { public void run() { FinalizerTest ref = wimp.get(); if (ref != null) { s[0] = ref.toString(); } } }; t.start(); try { t.join(); } catch (InterruptedException ie) { throw new RuntimeException(ie); } return s[0]; } private static void printWeakReference(WeakReference wimp) { // Reference ft so we are sure the WeakReference cannot be cleared. FinalizerTest keepLive = wimp.get(); System.out.println("wimp: " + wimpString(wimp)); } public static void main(String[] args) { WeakReference wimp = makeRef(); printWeakReference(wimp); /* this will try to collect and finalize ft */ System.out.println("gc"); Runtime.getRuntime().gc(); System.out.println("wimp: " + wimpString(wimp)); System.out.println("finalize"); System.runFinalization(); System.out.println("wimp: " + wimpString(wimp)); System.out.println("sleep"); snooze(1000); System.out.println("reborn: " + FinalizerTest.mReborn); System.out.println("wimp: " + wimpString(wimp)); System.out.println("reset reborn"); Runtime.getRuntime().gc(); FinalizerTest.mReborn = FinalizerTest.mNothing; System.out.println("gc + finalize"); System.gc(); System.runFinalization(); System.out.println("sleep"); snooze(1000); System.out.println("reborn: " + FinalizerTest.mReborn); System.out.println("wimp: " + wimpString(wimp)); // Test runFinalization with multiple objects. runFinalizationTest(); } static class FinalizeCounter { public static final int maxCount = 1024; public static boolean finalized[] = new boolean[maxCount]; private static Object finalizeLock = new Object(); private static volatile int finalizeCount = 0; private int index; static int getCount() { return finalizeCount; } static void printNonFinalized() { for (int i = 0; i < maxCount; ++i) { if (!FinalizeCounter.finalized[i]) { System.err.println("Element " + i + " was not finalized"); } } } FinalizeCounter(int index) { this.index = index; } protected void finalize() { synchronized(finalizeLock) { ++finalizeCount; finalized[index] = true; } } } private static void allocFinalizableObjects(int count) { Object[] objs = new Object[count]; for (int i = 0; i < count; ++i) { objs[i] = new FinalizeCounter(i); } } private static void runFinalizationTest() { allocFinalizableObjects(FinalizeCounter.maxCount); Runtime.getRuntime().gc(); System.runFinalization(); System.out.println("Finalized " + FinalizeCounter.getCount() + " / " + FinalizeCounter.maxCount); if (FinalizeCounter.getCount() != FinalizeCounter.maxCount) { // Print out all the finalized elements. FinalizeCounter.printNonFinalized(); // Try to sleep for a couple seconds to see if the objects became finalized after. try { java.lang.Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println("After sleep finalized " + FinalizeCounter.getCount() + " / " + FinalizeCounter.maxCount); FinalizeCounter.printNonFinalized(); } } public static class FinalizerTest { public static FinalizerTest mNothing = new FinalizerTest("nothing"); public static FinalizerTest mReborn = mNothing; private final String message; private boolean finalized = false; public FinalizerTest(String message) { this.message = message; } public String toString() { return "[FinalizerTest message=" + message + ", finalized=" + finalized + "]"; } protected void finalize() { finalized = true; mReborn = this; } } }