1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2022 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.lang.ref.SoftReference; 20*795d594fSAndroid Build Coastguard Worker import java.math.BigInteger; 21*795d594fSAndroid Build Coastguard Worker import java.util.ArrayList; 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker /** 24*795d594fSAndroid Build Coastguard Worker * Basic test of WeakReferences with large amounts of memory that's only reachable through 25*795d594fSAndroid Build Coastguard Worker * finalizers. Also makes sure that finalizer-reachable data is not collected. 26*795d594fSAndroid Build Coastguard Worker * Can easily be modified to time Reference.get() blocking. 27*795d594fSAndroid Build Coastguard Worker */ 28*795d594fSAndroid Build Coastguard Worker public class Main { 29*795d594fSAndroid Build Coastguard Worker static final boolean PRINT_TIMES = false; // true will cause benchmark failure. 30*795d594fSAndroid Build Coastguard Worker // Data structures repeatedly allocated in background to trigger GC. 31*795d594fSAndroid Build Coastguard Worker // Size of finalizer reachable trees. 32*795d594fSAndroid Build Coastguard Worker static final int TREE_HEIGHT = 15; // Trees contain 2^TREE_HEIGHT -1 allocated objects. 33*795d594fSAndroid Build Coastguard Worker // Number of finalizable tree-owning objects that exist at one point. 34*795d594fSAndroid Build Coastguard Worker static final int N_RESURRECTING_OBJECTS = 10; 35*795d594fSAndroid Build Coastguard Worker // Number of short-lived, not finalizer-reachable, objects allocated between trees. 36*795d594fSAndroid Build Coastguard Worker static final int N_PLAIN_OBJECTS = 20_000; 37*795d594fSAndroid Build Coastguard Worker // Number of SoftReferences to CBTs we allocate. 38*795d594fSAndroid Build Coastguard Worker static final int N_SOFTREFS = 10; 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker static final boolean BACKGROUND_GC_THREAD = true; 41*795d594fSAndroid Build Coastguard Worker static final int NBATCHES = 10; 42*795d594fSAndroid Build Coastguard Worker static final int NREFS = PRINT_TIMES ? 1_000_000 : 300_000; // Multiple of NBATCHES. 43*795d594fSAndroid Build Coastguard Worker static final int REFS_PER_BATCH = NREFS / NBATCHES; 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker static volatile boolean pleaseStop = false; 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker // Large array of WeakReferences filled and accessed by tests below. 48*795d594fSAndroid Build Coastguard Worker ArrayList<WeakReference<Integer>> weakRefs = new ArrayList<>(NREFS); 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker /** 51*795d594fSAndroid Build Coastguard Worker * Complete binary tree data structure. make(n) takes O(2^n) space. 52*795d594fSAndroid Build Coastguard Worker */ 53*795d594fSAndroid Build Coastguard Worker static class CBT { 54*795d594fSAndroid Build Coastguard Worker CBT left; 55*795d594fSAndroid Build Coastguard Worker CBT right; CBT(CBT l, CBT r)56*795d594fSAndroid Build Coastguard Worker CBT(CBT l, CBT r) { 57*795d594fSAndroid Build Coastguard Worker left = l; 58*795d594fSAndroid Build Coastguard Worker right = r; 59*795d594fSAndroid Build Coastguard Worker } make(int n)60*795d594fSAndroid Build Coastguard Worker static CBT make(int n) { 61*795d594fSAndroid Build Coastguard Worker if (n == 0) { 62*795d594fSAndroid Build Coastguard Worker return null; 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker return new CBT(make(n - 1), make(n - 1)); 65*795d594fSAndroid Build Coastguard Worker } 66*795d594fSAndroid Build Coastguard Worker /** 67*795d594fSAndroid Build Coastguard Worker * Check that path described by bit-vector path has the correct length. 68*795d594fSAndroid Build Coastguard Worker */ check(int n, int path)69*795d594fSAndroid Build Coastguard Worker void check(int n, int path) { 70*795d594fSAndroid Build Coastguard Worker CBT current = this; 71*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < n; i++, path = path >>> 1) { 72*795d594fSAndroid Build Coastguard Worker // Unexpectedly short paths result in NPE. 73*795d594fSAndroid Build Coastguard Worker if ((path & 1) == 0) { 74*795d594fSAndroid Build Coastguard Worker current = current.left; 75*795d594fSAndroid Build Coastguard Worker } else { 76*795d594fSAndroid Build Coastguard Worker current = current.right; 77*795d594fSAndroid Build Coastguard Worker } 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker if (current != null) { 80*795d594fSAndroid Build Coastguard Worker System.out.println("Complete binary tree path too long"); 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker } 83*795d594fSAndroid Build Coastguard Worker } 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker /** 87*795d594fSAndroid Build Coastguard Worker * A finalizable object that refers to O(2^TREE_HEIGHT) otherwise unreachable memory. 88*795d594fSAndroid Build Coastguard Worker * When finalized, it creates a new identical object, making sure that one always stays 89*795d594fSAndroid Build Coastguard Worker * around. 90*795d594fSAndroid Build Coastguard Worker */ 91*795d594fSAndroid Build Coastguard Worker static class ResurrectingObject { 92*795d594fSAndroid Build Coastguard Worker CBT stuff; ResurrectingObject()93*795d594fSAndroid Build Coastguard Worker ResurrectingObject() { 94*795d594fSAndroid Build Coastguard Worker stuff = CBT.make(TREE_HEIGHT); 95*795d594fSAndroid Build Coastguard Worker } 96*795d594fSAndroid Build Coastguard Worker static ResurrectingObject a[] = new ResurrectingObject[2]; 97*795d594fSAndroid Build Coastguard Worker static int i = 0; allocOne()98*795d594fSAndroid Build Coastguard Worker static synchronized void allocOne() { 99*795d594fSAndroid Build Coastguard Worker a[(++i) % 2] = new ResurrectingObject(); 100*795d594fSAndroid Build Coastguard Worker // Check the previous one to make it hard to optimize anything out. 101*795d594fSAndroid Build Coastguard Worker if (i > 1) { 102*795d594fSAndroid Build Coastguard Worker a[(i + 1) % 2].stuff.check(TREE_HEIGHT, i /* weirdly interpreted as path */); 103*795d594fSAndroid Build Coastguard Worker } 104*795d594fSAndroid Build Coastguard Worker } finalize()105*795d594fSAndroid Build Coastguard Worker protected void finalize() { 106*795d594fSAndroid Build Coastguard Worker stuff.check(TREE_HEIGHT, 42 /* Some path descriptor */); 107*795d594fSAndroid Build Coastguard Worker // Allocate a new one to replace this one. 108*795d594fSAndroid Build Coastguard Worker allocOne(); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker } 111*795d594fSAndroid Build Coastguard Worker fillWeakRefs()112*795d594fSAndroid Build Coastguard Worker void fillWeakRefs() { 113*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NREFS; ++i) { 114*795d594fSAndroid Build Coastguard Worker weakRefs.add(null); 115*795d594fSAndroid Build Coastguard Worker } 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker /* 119*795d594fSAndroid Build Coastguard Worker * Return maximum observed time in nanos to dereference a WeakReference to an unreachable 120*795d594fSAndroid Build Coastguard Worker * object. weakRefs is presumed to be pre-filled to have the correct size. 121*795d594fSAndroid Build Coastguard Worker */ timeUnreachableInner()122*795d594fSAndroid Build Coastguard Worker long timeUnreachableInner() { 123*795d594fSAndroid Build Coastguard Worker long maxNanos = 0; 124*795d594fSAndroid Build Coastguard Worker // Fill weakRefs with WeakReferences to unreachable integers, a batch at a time. 125*795d594fSAndroid Build Coastguard Worker // Then time and test .get() calls on carefully sampled array entries, some of which 126*795d594fSAndroid Build Coastguard Worker // will have been cleared. 127*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NBATCHES; ++i) { 128*795d594fSAndroid Build Coastguard Worker for (int j = 0; j < REFS_PER_BATCH; ++j) { 129*795d594fSAndroid Build Coastguard Worker weakRefs.set(i * REFS_PER_BATCH + j, 130*795d594fSAndroid Build Coastguard Worker new WeakReference(new Integer(i * REFS_PER_BATCH + j))); 131*795d594fSAndroid Build Coastguard Worker } 132*795d594fSAndroid Build Coastguard Worker try { 133*795d594fSAndroid Build Coastguard Worker Thread.sleep(50); 134*795d594fSAndroid Build Coastguard Worker } catch (InterruptedException e) { 135*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected exception"); 136*795d594fSAndroid Build Coastguard Worker } 137*795d594fSAndroid Build Coastguard Worker // Iterate over the filled-in section of weakRefs, but look only at a subset of the 138*795d594fSAndroid Build Coastguard Worker // elements, making sure the subsets for different top-level iterations are disjoint. 139*795d594fSAndroid Build Coastguard Worker // Otherwise the get() calls here will extend the lifetimes of the referents, and we 140*795d594fSAndroid Build Coastguard Worker // may never see any cleared WeakReferences. 141*795d594fSAndroid Build Coastguard Worker for (int j = (i + 1) * REFS_PER_BATCH - i - 1; j >= 0; j -= NBATCHES) { 142*795d594fSAndroid Build Coastguard Worker WeakReference<Integer> wr = weakRefs.get(j); 143*795d594fSAndroid Build Coastguard Worker if (wr != null) { 144*795d594fSAndroid Build Coastguard Worker long startNanos = System.nanoTime(); 145*795d594fSAndroid Build Coastguard Worker Integer referent = wr.get(); 146*795d594fSAndroid Build Coastguard Worker long totalNanos = System.nanoTime() - startNanos; 147*795d594fSAndroid Build Coastguard Worker if (referent == null) { 148*795d594fSAndroid Build Coastguard Worker // Optimization to reduce max space use and scanning time. 149*795d594fSAndroid Build Coastguard Worker weakRefs.set(j, null); 150*795d594fSAndroid Build Coastguard Worker } 151*795d594fSAndroid Build Coastguard Worker maxNanos = Math.max(maxNanos, totalNanos); 152*795d594fSAndroid Build Coastguard Worker if (referent != null && referent.intValue() != j) { 153*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected referent; expected " + j + " got " 154*795d594fSAndroid Build Coastguard Worker + referent.intValue()); 155*795d594fSAndroid Build Coastguard Worker } 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker } 158*795d594fSAndroid Build Coastguard Worker } 159*795d594fSAndroid Build Coastguard Worker return maxNanos; 160*795d594fSAndroid Build Coastguard Worker } 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker /* 163*795d594fSAndroid Build Coastguard Worker * Wrapper for the above that also checks that references were reclaimed. 164*795d594fSAndroid Build Coastguard Worker * We do this separately to make sure any stack references from the core of the 165*795d594fSAndroid Build Coastguard Worker * test are gone. Empirically, we otherwise sometimes see the zeroth WeakReference 166*795d594fSAndroid Build Coastguard Worker * not reclaimed. 167*795d594fSAndroid Build Coastguard Worker */ timeUnreachable()168*795d594fSAndroid Build Coastguard Worker long timeUnreachable() { 169*795d594fSAndroid Build Coastguard Worker long maxNanos = timeUnreachableInner(); 170*795d594fSAndroid Build Coastguard Worker Runtime.getRuntime().gc(); 171*795d594fSAndroid Build Coastguard Worker System.runFinalization(); // Presumed to wait for reference clearing. 172*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NREFS; ++i) { 173*795d594fSAndroid Build Coastguard Worker if (weakRefs.get(i) != null && weakRefs.get(i).get() != null) { 174*795d594fSAndroid Build Coastguard Worker System.out.println("WeakReference to " + i + " wasn't cleared"); 175*795d594fSAndroid Build Coastguard Worker } 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker return maxNanos; 178*795d594fSAndroid Build Coastguard Worker } 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker /** 181*795d594fSAndroid Build Coastguard Worker * Return maximum observed time in nanos to dereference a WeakReference to a reachable 182*795d594fSAndroid Build Coastguard Worker * object. Overwrites weakRefs, which is presumed to have NREFS entries already. 183*795d594fSAndroid Build Coastguard Worker */ timeReachable()184*795d594fSAndroid Build Coastguard Worker long timeReachable() { 185*795d594fSAndroid Build Coastguard Worker long maxNanos = 0; 186*795d594fSAndroid Build Coastguard Worker // Similar to the above, but we use WeakReferences to otherwise reachable objects, 187*795d594fSAndroid Build Coastguard Worker // which should thus not get cleared. 188*795d594fSAndroid Build Coastguard Worker Integer[] strongRefs = new Integer[NREFS]; 189*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NBATCHES; ++i) { 190*795d594fSAndroid Build Coastguard Worker for (int j = i * REFS_PER_BATCH; j < (i + 1) * REFS_PER_BATCH; ++j) { 191*795d594fSAndroid Build Coastguard Worker Integer newObj = new Integer(j); 192*795d594fSAndroid Build Coastguard Worker strongRefs[j] = newObj; 193*795d594fSAndroid Build Coastguard Worker weakRefs.set(j, new WeakReference(newObj)); 194*795d594fSAndroid Build Coastguard Worker } 195*795d594fSAndroid Build Coastguard Worker for (int j = (i + 1) * REFS_PER_BATCH - 1; j >= 0; --j) { 196*795d594fSAndroid Build Coastguard Worker WeakReference<Integer> wr = weakRefs.get(j); 197*795d594fSAndroid Build Coastguard Worker long startNanos = System.nanoTime(); 198*795d594fSAndroid Build Coastguard Worker Integer referent = wr.get(); 199*795d594fSAndroid Build Coastguard Worker long totalNanos = System.nanoTime() - startNanos; 200*795d594fSAndroid Build Coastguard Worker maxNanos = Math.max(maxNanos, totalNanos); 201*795d594fSAndroid Build Coastguard Worker if (referent == null) { 202*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpectedly cleared referent at " + j); 203*795d594fSAndroid Build Coastguard Worker } else if (referent.intValue() != j) { 204*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected reachable referent; expected " + j + " got " 205*795d594fSAndroid Build Coastguard Worker + referent.intValue()); 206*795d594fSAndroid Build Coastguard Worker } 207*795d594fSAndroid Build Coastguard Worker } 208*795d594fSAndroid Build Coastguard Worker } 209*795d594fSAndroid Build Coastguard Worker Reference.reachabilityFence(strongRefs); 210*795d594fSAndroid Build Coastguard Worker return maxNanos; 211*795d594fSAndroid Build Coastguard Worker } 212*795d594fSAndroid Build Coastguard Worker runTest()213*795d594fSAndroid Build Coastguard Worker void runTest() { 214*795d594fSAndroid Build Coastguard Worker System.out.println("Starting"); 215*795d594fSAndroid Build Coastguard Worker fillWeakRefs(); 216*795d594fSAndroid Build Coastguard Worker long unreachableNanos = timeUnreachable(); 217*795d594fSAndroid Build Coastguard Worker if (PRINT_TIMES) { 218*795d594fSAndroid Build Coastguard Worker System.out.println("Finished timeUnrechable()"); 219*795d594fSAndroid Build Coastguard Worker } 220*795d594fSAndroid Build Coastguard Worker long reachableNanos = timeReachable(); 221*795d594fSAndroid Build Coastguard Worker String unreachableMillis = 222*795d594fSAndroid Build Coastguard Worker String. format("%,.3f", ((double) unreachableNanos) / 1_000_000); 223*795d594fSAndroid Build Coastguard Worker String reachableMillis = 224*795d594fSAndroid Build Coastguard Worker String. format("%,.3f", ((double) reachableNanos) / 1_000_000); 225*795d594fSAndroid Build Coastguard Worker if (PRINT_TIMES) { 226*795d594fSAndroid Build Coastguard Worker System.out.println( 227*795d594fSAndroid Build Coastguard Worker "Max time for WeakReference.get (unreachable): " + unreachableMillis); 228*795d594fSAndroid Build Coastguard Worker System.out.println( 229*795d594fSAndroid Build Coastguard Worker "Max time for WeakReference.get (reachable): " + reachableMillis); 230*795d594fSAndroid Build Coastguard Worker } 231*795d594fSAndroid Build Coastguard Worker // Only report extremely egregious pauses to avoid spurious failures. 232*795d594fSAndroid Build Coastguard Worker if (unreachableNanos > 10_000_000_000L) { 233*795d594fSAndroid Build Coastguard Worker System.out.println("WeakReference.get (unreachable) time unreasonably long"); 234*795d594fSAndroid Build Coastguard Worker } 235*795d594fSAndroid Build Coastguard Worker if (reachableNanos > 10_000_000_000L) { 236*795d594fSAndroid Build Coastguard Worker System.out.println("WeakReference.get (reachable) time unreasonably long"); 237*795d594fSAndroid Build Coastguard Worker } 238*795d594fSAndroid Build Coastguard Worker } 239*795d594fSAndroid Build Coastguard Worker 240*795d594fSAndroid Build Coastguard Worker /** 241*795d594fSAndroid Build Coastguard Worker * Allocate and GC a lot, while keeping significant amounts of finalizer and 242*795d594fSAndroid Build Coastguard Worker * SoftReference-reachable memory around. 243*795d594fSAndroid Build Coastguard Worker */ 244*795d594fSAndroid Build Coastguard Worker static Runnable allocFinalizable = new Runnable() { 245*795d594fSAndroid Build Coastguard Worker public void run() { 246*795d594fSAndroid Build Coastguard Worker // Allocate and drop some finalizable objects that take a long time 247*795d594fSAndroid Build Coastguard Worker // to mark. Designed to be hard to optimize away. Each of these objects will 248*795d594fSAndroid Build Coastguard Worker // build a new one in its finalizer before really going away. 249*795d594fSAndroid Build Coastguard Worker ArrayList<SoftReference<CBT>> softRefs = new ArrayList<>(N_SOFTREFS); 250*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < N_SOFTREFS; ++i) { 251*795d594fSAndroid Build Coastguard Worker // These should not normally get reclaimed, since we shouldn't run out of 252*795d594fSAndroid Build Coastguard Worker // memory. They do increase tracing time. 253*795d594fSAndroid Build Coastguard Worker softRefs.add(new SoftReference(CBT.make(TREE_HEIGHT))); 254*795d594fSAndroid Build Coastguard Worker } 255*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < N_RESURRECTING_OBJECTS; ++i) { 256*795d594fSAndroid Build Coastguard Worker ResurrectingObject.allocOne(); 257*795d594fSAndroid Build Coastguard Worker } 258*795d594fSAndroid Build Coastguard Worker BigInteger counter = BigInteger.ZERO; 259*795d594fSAndroid Build Coastguard Worker for (int i = 1; !pleaseStop; ++i) { 260*795d594fSAndroid Build Coastguard Worker // Allocate a lot of short-lived objects, using BigIntegers to minimize the chance 261*795d594fSAndroid Build Coastguard Worker // of the allocation getting optimized out. This makes things slightly more 262*795d594fSAndroid Build Coastguard Worker // realistic, since not all objects will be finalizer reachable. 263*795d594fSAndroid Build Coastguard Worker for (int j = 0; j < N_PLAIN_OBJECTS / 2; ++j) { 264*795d594fSAndroid Build Coastguard Worker counter = counter.add(BigInteger.TEN); 265*795d594fSAndroid Build Coastguard Worker } 266*795d594fSAndroid Build Coastguard Worker // Look at counter to reduce chance of optimizing out the allocation. 267*795d594fSAndroid Build Coastguard Worker if (counter.longValue() % 10 != 0) { 268*795d594fSAndroid Build Coastguard Worker System.out.println("Bad allocFinalizable counter value: " + counter); 269*795d594fSAndroid Build Coastguard Worker } 270*795d594fSAndroid Build Coastguard Worker // Explicitly collect here, mostly to prevent heap growth. Otherwise we get 271*795d594fSAndroid Build Coastguard Worker // ahead of the GC and eventually block on it. 272*795d594fSAndroid Build Coastguard Worker Runtime.getRuntime().gc(); 273*795d594fSAndroid Build Coastguard Worker if (PRINT_TIMES && i % 100 == 0) { 274*795d594fSAndroid Build Coastguard Worker System.out.println("Collected " + i + " times"); 275*795d594fSAndroid Build Coastguard Worker } 276*795d594fSAndroid Build Coastguard Worker } 277*795d594fSAndroid Build Coastguard Worker // To be safe, access softRefs. 278*795d594fSAndroid Build Coastguard Worker final CBT sample = softRefs.get(N_SOFTREFS / 2).get(); 279*795d594fSAndroid Build Coastguard Worker if (sample != null) { 280*795d594fSAndroid Build Coastguard Worker sample.check(TREE_HEIGHT, 47 /* some path descriptor */); 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker } 283*795d594fSAndroid Build Coastguard Worker }; 284*795d594fSAndroid Build Coastguard Worker main(String[] args)285*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 286*795d594fSAndroid Build Coastguard Worker Main theTest = new Main(); 287*795d594fSAndroid Build Coastguard Worker Thread allocThread = null; 288*795d594fSAndroid Build Coastguard Worker if (BACKGROUND_GC_THREAD) { 289*795d594fSAndroid Build Coastguard Worker allocThread = new Thread(allocFinalizable); 290*795d594fSAndroid Build Coastguard Worker allocThread.setDaemon(true); // Terminate if main thread dies. 291*795d594fSAndroid Build Coastguard Worker allocThread.start(); 292*795d594fSAndroid Build Coastguard Worker } 293*795d594fSAndroid Build Coastguard Worker theTest.runTest(); 294*795d594fSAndroid Build Coastguard Worker if (BACKGROUND_GC_THREAD) { 295*795d594fSAndroid Build Coastguard Worker pleaseStop = true; 296*795d594fSAndroid Build Coastguard Worker allocThread.join(); 297*795d594fSAndroid Build Coastguard Worker } 298*795d594fSAndroid Build Coastguard Worker System.out.println("Finished"); 299*795d594fSAndroid Build Coastguard Worker } 300*795d594fSAndroid Build Coastguard Worker } 301