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