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.PhantomReference; 18*795d594fSAndroid Build Coastguard Worker import java.lang.ref.Reference; 19*795d594fSAndroid Build Coastguard Worker import java.lang.ref.ReferenceQueue; 20*795d594fSAndroid Build Coastguard Worker import java.lang.ref.WeakReference; 21*795d594fSAndroid Build Coastguard Worker import java.math.BigInteger; 22*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.ArrayBlockingQueue; 23*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.atomic.AtomicInteger; 24*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.ConcurrentHashMap; 25*795d594fSAndroid Build Coastguard Worker import java.util.TreeMap; 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker /** 28*795d594fSAndroid Build Coastguard Worker * Test that objects get finalized and their references cleared in the right order. 29*795d594fSAndroid Build Coastguard Worker * 30*795d594fSAndroid Build Coastguard Worker * We maintain a list of nominally MAX_LIVE_OBJS numbered finalizable objects. 31*795d594fSAndroid Build Coastguard Worker * We then alternately drop the last 50, and add 50 more. When we see an object finalized 32*795d594fSAndroid Build Coastguard Worker * or its reference cleared, we make sure that the preceding objects in its group of 50 33*795d594fSAndroid Build Coastguard Worker * have also had their references cleared. We also perform a number of other more 34*795d594fSAndroid Build Coastguard Worker * straightforward checks, such as ensuring that all references are eventually cleared, 35*795d594fSAndroid Build Coastguard Worker * and all objects are finalized. 36*795d594fSAndroid Build Coastguard Worker */ 37*795d594fSAndroid Build Coastguard Worker public class Main { 38*795d594fSAndroid Build Coastguard Worker // TODO(b/216481630) Enable CHECK_PHANTOM_REFS. This currently occasionally reports a few 39*795d594fSAndroid Build Coastguard Worker // PhantomReferences as not enqueued. If this report is correct, this needs to be tracked 40*795d594fSAndroid Build Coastguard Worker // down and fixed. 41*795d594fSAndroid Build Coastguard Worker static final boolean CHECK_PHANTOM_REFS = false; 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker static final int MAX_LIVE_OBJS = 150; 44*795d594fSAndroid Build Coastguard Worker static final int DROP_OBJS = 50; // Number of linked objects dropped in each batch. 45*795d594fSAndroid Build Coastguard Worker static final int MIN_LIVE_OBJS = MAX_LIVE_OBJS - DROP_OBJS; 46*795d594fSAndroid Build Coastguard Worker static final int TOTAL_OBJS = 200_000; // Allocate this many finalizable objects in total. 47*795d594fSAndroid Build Coastguard Worker static final boolean REPORT_DROPS = false; 48*795d594fSAndroid Build Coastguard Worker static volatile boolean pleaseStop; 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker AtomicInteger totalFinalized = new AtomicInteger(0); 51*795d594fSAndroid Build Coastguard Worker int maxDropped = 0; 52*795d594fSAndroid Build Coastguard Worker int liveObjects = 0; 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // Number of next finalizable object to be allocated. 55*795d594fSAndroid Build Coastguard Worker int nextAllocated = 0; 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker // List of finalizable objects in descending order. We add to the front and drop 58*795d594fSAndroid Build Coastguard Worker // from the rear. 59*795d594fSAndroid Build Coastguard Worker FinalizableObject listHead; 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // A possibly incomplete list of FinalizableObject indices that were finalized, but 62*795d594fSAndroid Build Coastguard Worker // have yet to be checked for consistency with reference processing. 63*795d594fSAndroid Build Coastguard Worker ArrayBlockingQueue<Integer> finalized = new ArrayBlockingQueue<>(20_000); 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker // Maps from object number to Reference; Cleared references are deleted when queues are 66*795d594fSAndroid Build Coastguard Worker // processed. 67*795d594fSAndroid Build Coastguard Worker TreeMap<Integer, MyWeakReference> weakRefs = new TreeMap<>(); 68*795d594fSAndroid Build Coastguard Worker ConcurrentHashMap<Integer, MyPhantomReference> phantomRefs = new ConcurrentHashMap<>(); 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker class FinalizableObject { 71*795d594fSAndroid Build Coastguard Worker int n; 72*795d594fSAndroid Build Coastguard Worker FinalizableObject next; FinalizableObject(int num, FinalizableObject nextObj)73*795d594fSAndroid Build Coastguard Worker FinalizableObject(int num, FinalizableObject nextObj) { 74*795d594fSAndroid Build Coastguard Worker n = num; 75*795d594fSAndroid Build Coastguard Worker next = nextObj; 76*795d594fSAndroid Build Coastguard Worker } finalize()77*795d594fSAndroid Build Coastguard Worker protected void finalize() { 78*795d594fSAndroid Build Coastguard Worker if (!inPhantomRefs(n)) { 79*795d594fSAndroid Build Coastguard Worker System.out.println("PhantomRef enqueued before finalizer ran"); 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker totalFinalized.incrementAndGet(); 82*795d594fSAndroid Build Coastguard Worker if (!finalized.offer(n) && REPORT_DROPS) { 83*795d594fSAndroid Build Coastguard Worker System.out.println("Dropped finalization of " + n); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker } 86*795d594fSAndroid Build Coastguard Worker } 87*795d594fSAndroid Build Coastguard Worker ReferenceQueue<FinalizableObject> refQueue = new ReferenceQueue<>(); 88*795d594fSAndroid Build Coastguard Worker class MyWeakReference extends WeakReference<FinalizableObject> { 89*795d594fSAndroid Build Coastguard Worker int n; MyWeakReference(FinalizableObject obj)90*795d594fSAndroid Build Coastguard Worker MyWeakReference(FinalizableObject obj) { 91*795d594fSAndroid Build Coastguard Worker super(obj, refQueue); 92*795d594fSAndroid Build Coastguard Worker n = obj.n; 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker }; 95*795d594fSAndroid Build Coastguard Worker class MyPhantomReference extends PhantomReference<FinalizableObject> { 96*795d594fSAndroid Build Coastguard Worker int n; MyPhantomReference(FinalizableObject obj)97*795d594fSAndroid Build Coastguard Worker MyPhantomReference(FinalizableObject obj) { 98*795d594fSAndroid Build Coastguard Worker super(obj, refQueue); 99*795d594fSAndroid Build Coastguard Worker n = obj.n; 100*795d594fSAndroid Build Coastguard Worker } 101*795d594fSAndroid Build Coastguard Worker } inPhantomRefs(int n)102*795d594fSAndroid Build Coastguard Worker boolean inPhantomRefs(int n) { 103*795d594fSAndroid Build Coastguard Worker MyPhantomReference ref = phantomRefs.get(n); 104*795d594fSAndroid Build Coastguard Worker if (ref == null) { 105*795d594fSAndroid Build Coastguard Worker return false; 106*795d594fSAndroid Build Coastguard Worker } 107*795d594fSAndroid Build Coastguard Worker if (ref.n != n) { 108*795d594fSAndroid Build Coastguard Worker System.out.println("phantomRef retrieval failed"); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker return true; 111*795d594fSAndroid Build Coastguard Worker } 112*795d594fSAndroid Build Coastguard Worker CheckOKToClearWeak(int num)113*795d594fSAndroid Build Coastguard Worker void CheckOKToClearWeak(int num) { 114*795d594fSAndroid Build Coastguard Worker if (num > maxDropped) { 115*795d594fSAndroid Build Coastguard Worker System.out.println("WeakRef to live object " + num + " was cleared/enqueued."); 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker int batchEnd = (num / DROP_OBJS + 1) * DROP_OBJS; 118*795d594fSAndroid Build Coastguard Worker for (MyWeakReference wr : weakRefs.subMap(num + 1, batchEnd).values()) { 119*795d594fSAndroid Build Coastguard Worker if (wr.n <= num || wr.n / DROP_OBJS != num / DROP_OBJS) { 120*795d594fSAndroid Build Coastguard Worker throw new AssertionError("MyWeakReference logic error!"); 121*795d594fSAndroid Build Coastguard Worker } 122*795d594fSAndroid Build Coastguard Worker // wr referent was dropped in same batch and precedes it in list. 123*795d594fSAndroid Build Coastguard Worker if (wr.get() != null) { 124*795d594fSAndroid Build Coastguard Worker // This violates the WeakReference spec, and can result in strong references 125*795d594fSAndroid Build Coastguard Worker // to objects that have been cleaned. 126*795d594fSAndroid Build Coastguard Worker System.out.println("WeakReference to " + wr.n 127*795d594fSAndroid Build Coastguard Worker + " was erroneously cleared after " + num); 128*795d594fSAndroid Build Coastguard Worker } 129*795d594fSAndroid Build Coastguard Worker } 130*795d594fSAndroid Build Coastguard Worker } 131*795d594fSAndroid Build Coastguard Worker CheckOKToClearPhantom(int num)132*795d594fSAndroid Build Coastguard Worker void CheckOKToClearPhantom(int num) { 133*795d594fSAndroid Build Coastguard Worker if (num > maxDropped) { 134*795d594fSAndroid Build Coastguard Worker System.out.println("PhantomRef to live object " + num + " was enqueued."); 135*795d594fSAndroid Build Coastguard Worker } 136*795d594fSAndroid Build Coastguard Worker MyWeakReference wr = weakRefs.get(num); 137*795d594fSAndroid Build Coastguard Worker if (wr != null && wr.get() != null) { 138*795d594fSAndroid Build Coastguard Worker System.out.println("PhantomRef cleared before WeakRef for " + num); 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker } 141*795d594fSAndroid Build Coastguard Worker emptyAndCheckQueues()142*795d594fSAndroid Build Coastguard Worker void emptyAndCheckQueues() { 143*795d594fSAndroid Build Coastguard Worker // Check recently finalized objects for consistency with cleared references. 144*795d594fSAndroid Build Coastguard Worker while (true) { 145*795d594fSAndroid Build Coastguard Worker Integer num = finalized.poll(); 146*795d594fSAndroid Build Coastguard Worker if (num == null) { 147*795d594fSAndroid Build Coastguard Worker break; 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker MyWeakReference wr = weakRefs.get(num); 150*795d594fSAndroid Build Coastguard Worker if (wr != null) { 151*795d594fSAndroid Build Coastguard Worker if (wr.n != num) { 152*795d594fSAndroid Build Coastguard Worker System.out.println("Finalization logic error!"); 153*795d594fSAndroid Build Coastguard Worker } 154*795d594fSAndroid Build Coastguard Worker if (wr.get() != null) { 155*795d594fSAndroid Build Coastguard Worker System.out.println("Finalizing object with uncleared reference"); 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker } 158*795d594fSAndroid Build Coastguard Worker CheckOKToClearWeak(num); 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker // Check recently enqueued references for consistency. 161*795d594fSAndroid Build Coastguard Worker while (true) { 162*795d594fSAndroid Build Coastguard Worker Reference<FinalizableObject> ref = (Reference<FinalizableObject>) refQueue.poll(); 163*795d594fSAndroid Build Coastguard Worker if (ref == null) { 164*795d594fSAndroid Build Coastguard Worker break; 165*795d594fSAndroid Build Coastguard Worker } 166*795d594fSAndroid Build Coastguard Worker if (ref instanceof MyWeakReference) { 167*795d594fSAndroid Build Coastguard Worker MyWeakReference wr = (MyWeakReference) ref; 168*795d594fSAndroid Build Coastguard Worker if (wr.get() != null) { 169*795d594fSAndroid Build Coastguard Worker System.out.println("WeakRef " + wr.n + " enqueued but not cleared"); 170*795d594fSAndroid Build Coastguard Worker } 171*795d594fSAndroid Build Coastguard Worker CheckOKToClearWeak(wr.n); 172*795d594fSAndroid Build Coastguard Worker if (weakRefs.remove(Integer.valueOf(wr.n)) != ref) { 173*795d594fSAndroid Build Coastguard Worker System.out.println("Missing WeakReference: " + wr.n); 174*795d594fSAndroid Build Coastguard Worker } 175*795d594fSAndroid Build Coastguard Worker } else if (ref instanceof MyPhantomReference) { 176*795d594fSAndroid Build Coastguard Worker MyPhantomReference pr = (MyPhantomReference) ref; 177*795d594fSAndroid Build Coastguard Worker CheckOKToClearPhantom(pr.n); 178*795d594fSAndroid Build Coastguard Worker if (phantomRefs.remove(Integer.valueOf(pr.n)) != ref) { 179*795d594fSAndroid Build Coastguard Worker System.out.println("Missing PhantomReference: " + pr.n); 180*795d594fSAndroid Build Coastguard Worker } 181*795d594fSAndroid Build Coastguard Worker } else { 182*795d594fSAndroid Build Coastguard Worker System.out.println("Found unrecognized reference in queue"); 183*795d594fSAndroid Build Coastguard Worker } 184*795d594fSAndroid Build Coastguard Worker } 185*795d594fSAndroid Build Coastguard Worker } 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker 188*795d594fSAndroid Build Coastguard Worker /** 189*795d594fSAndroid Build Coastguard Worker * Add n objects to the head of the list. These will be assigned the next n consecutive 190*795d594fSAndroid Build Coastguard Worker * numbers after the current head of the list. 191*795d594fSAndroid Build Coastguard Worker */ addObjects(int n)192*795d594fSAndroid Build Coastguard Worker void addObjects(int n) { 193*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < n; ++i) { 194*795d594fSAndroid Build Coastguard Worker int me = nextAllocated++; 195*795d594fSAndroid Build Coastguard Worker listHead = new FinalizableObject(me, listHead); 196*795d594fSAndroid Build Coastguard Worker weakRefs.put(me, new MyWeakReference(listHead)); 197*795d594fSAndroid Build Coastguard Worker phantomRefs.put(me, new MyPhantomReference(listHead)); 198*795d594fSAndroid Build Coastguard Worker } 199*795d594fSAndroid Build Coastguard Worker liveObjects += n; 200*795d594fSAndroid Build Coastguard Worker } 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker /** 203*795d594fSAndroid Build Coastguard Worker * Drop n finalizable objects from the tail of the list. These are the lowest-numbered objects 204*795d594fSAndroid Build Coastguard Worker * in the list. 205*795d594fSAndroid Build Coastguard Worker */ dropObjects(int n)206*795d594fSAndroid Build Coastguard Worker void dropObjects(int n) { 207*795d594fSAndroid Build Coastguard Worker FinalizableObject list = listHead; 208*795d594fSAndroid Build Coastguard Worker FinalizableObject last = null; 209*795d594fSAndroid Build Coastguard Worker if (n > liveObjects) { 210*795d594fSAndroid Build Coastguard Worker System.out.println("Removing too many elements"); 211*795d594fSAndroid Build Coastguard Worker } 212*795d594fSAndroid Build Coastguard Worker if (liveObjects == n) { 213*795d594fSAndroid Build Coastguard Worker maxDropped = list.n; 214*795d594fSAndroid Build Coastguard Worker listHead = null; 215*795d594fSAndroid Build Coastguard Worker } else { 216*795d594fSAndroid Build Coastguard Worker final int skip = liveObjects - n; 217*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < skip; ++i) { 218*795d594fSAndroid Build Coastguard Worker last = list; 219*795d594fSAndroid Build Coastguard Worker list = list.next; 220*795d594fSAndroid Build Coastguard Worker } 221*795d594fSAndroid Build Coastguard Worker int expected = nextAllocated - skip - 1; 222*795d594fSAndroid Build Coastguard Worker if (list.n != expected) { 223*795d594fSAndroid Build Coastguard Worker System.out.println("dropObjects found " + list.n + " but expected " + expected); 224*795d594fSAndroid Build Coastguard Worker } 225*795d594fSAndroid Build Coastguard Worker maxDropped = expected; 226*795d594fSAndroid Build Coastguard Worker last.next = null; 227*795d594fSAndroid Build Coastguard Worker } 228*795d594fSAndroid Build Coastguard Worker liveObjects -= n; 229*795d594fSAndroid Build Coastguard Worker } 230*795d594fSAndroid Build Coastguard Worker testLoop()231*795d594fSAndroid Build Coastguard Worker void testLoop() { 232*795d594fSAndroid Build Coastguard Worker System.out.println("Starting"); 233*795d594fSAndroid Build Coastguard Worker addObjects(MIN_LIVE_OBJS); 234*795d594fSAndroid Build Coastguard Worker final int ITERS = (TOTAL_OBJS - MIN_LIVE_OBJS) / DROP_OBJS; 235*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < ITERS; ++i) { 236*795d594fSAndroid Build Coastguard Worker addObjects(DROP_OBJS); 237*795d594fSAndroid Build Coastguard Worker if (liveObjects != MAX_LIVE_OBJS) { 238*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected live object count"); 239*795d594fSAndroid Build Coastguard Worker } 240*795d594fSAndroid Build Coastguard Worker dropObjects(DROP_OBJS); 241*795d594fSAndroid Build Coastguard Worker if (i % 100 == 0) { 242*795d594fSAndroid Build Coastguard Worker // Make sure we don't fall too far behind, otherwise we may run out of memory. 243*795d594fSAndroid Build Coastguard Worker System.runFinalization(); 244*795d594fSAndroid Build Coastguard Worker } 245*795d594fSAndroid Build Coastguard Worker emptyAndCheckQueues(); 246*795d594fSAndroid Build Coastguard Worker } 247*795d594fSAndroid Build Coastguard Worker dropObjects(MIN_LIVE_OBJS); 248*795d594fSAndroid Build Coastguard Worker if (liveObjects != 0 || listHead != null) { 249*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected live objecs at end"); 250*795d594fSAndroid Build Coastguard Worker } 251*795d594fSAndroid Build Coastguard Worker if (maxDropped != TOTAL_OBJS - 1) { 252*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected dropped object count: " + maxDropped); 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; ++i) { 255*795d594fSAndroid Build Coastguard Worker Runtime.getRuntime().gc(); 256*795d594fSAndroid Build Coastguard Worker System.runFinalization(); 257*795d594fSAndroid Build Coastguard Worker emptyAndCheckQueues(); 258*795d594fSAndroid Build Coastguard Worker } 259*795d594fSAndroid Build Coastguard Worker if (!weakRefs.isEmpty()) { 260*795d594fSAndroid Build Coastguard Worker System.out.println("Weak Reference map nonempty size = " + weakRefs.size()); 261*795d594fSAndroid Build Coastguard Worker } 262*795d594fSAndroid Build Coastguard Worker if (CHECK_PHANTOM_REFS && !phantomRefs.isEmpty()) { 263*795d594fSAndroid Build Coastguard Worker try { 264*795d594fSAndroid Build Coastguard Worker Thread.sleep(500); 265*795d594fSAndroid Build Coastguard Worker } catch (InterruptedException e) { 266*795d594fSAndroid Build Coastguard Worker System.out.println("Unexpected interrupt"); 267*795d594fSAndroid Build Coastguard Worker } 268*795d594fSAndroid Build Coastguard Worker if (!phantomRefs.isEmpty()) { 269*795d594fSAndroid Build Coastguard Worker System.out.println("Phantom Reference map nonempty size = " + phantomRefs.size()); 270*795d594fSAndroid Build Coastguard Worker System.out.print("First elements:"); 271*795d594fSAndroid Build Coastguard Worker int i = 0; 272*795d594fSAndroid Build Coastguard Worker for (MyPhantomReference pr : phantomRefs.values()) { 273*795d594fSAndroid Build Coastguard Worker System.out.print(" " + pr.n); 274*795d594fSAndroid Build Coastguard Worker if (++i > 10) { 275*795d594fSAndroid Build Coastguard Worker break; 276*795d594fSAndroid Build Coastguard Worker } 277*795d594fSAndroid Build Coastguard Worker } 278*795d594fSAndroid Build Coastguard Worker System.out.println(""); 279*795d594fSAndroid Build Coastguard Worker } 280*795d594fSAndroid Build Coastguard Worker } 281*795d594fSAndroid Build Coastguard Worker if (totalFinalized.get() != TOTAL_OBJS) { 282*795d594fSAndroid Build Coastguard Worker System.out.println("Finalized only " + totalFinalized + " objects"); 283*795d594fSAndroid Build Coastguard Worker } 284*795d594fSAndroid Build Coastguard Worker } 285*795d594fSAndroid Build Coastguard Worker 286*795d594fSAndroid Build Coastguard Worker static Runnable causeGCs = new Runnable() { 287*795d594fSAndroid Build Coastguard Worker public void run() { 288*795d594fSAndroid Build Coastguard Worker // Allocate a lot. 289*795d594fSAndroid Build Coastguard Worker BigInteger counter = BigInteger.ZERO; 290*795d594fSAndroid Build Coastguard Worker while (!pleaseStop) { 291*795d594fSAndroid Build Coastguard Worker counter = counter.add(BigInteger.TEN); 292*795d594fSAndroid Build Coastguard Worker } 293*795d594fSAndroid Build Coastguard Worker // Look at counter to reduce chance of optimizing out the allocation. 294*795d594fSAndroid Build Coastguard Worker if (counter.longValue() % 10 != 0) { 295*795d594fSAndroid Build Coastguard Worker System.out.println("Bad causeGCs counter value: " + counter); 296*795d594fSAndroid Build Coastguard Worker } 297*795d594fSAndroid Build Coastguard Worker } 298*795d594fSAndroid Build Coastguard Worker }; 299*795d594fSAndroid Build Coastguard Worker main(String[] args)300*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 301*795d594fSAndroid Build Coastguard Worker Main theTest = new Main(); 302*795d594fSAndroid Build Coastguard Worker Thread gcThread = new Thread(causeGCs); 303*795d594fSAndroid Build Coastguard Worker gcThread.setDaemon(true); // Terminate if main thread dies. 304*795d594fSAndroid Build Coastguard Worker gcThread.start(); 305*795d594fSAndroid Build Coastguard Worker theTest.testLoop(); 306*795d594fSAndroid Build Coastguard Worker pleaseStop = true; 307*795d594fSAndroid Build Coastguard Worker gcThread.join(); 308*795d594fSAndroid Build Coastguard Worker System.out.println("Finished"); 309*795d594fSAndroid Build Coastguard Worker } 310*795d594fSAndroid Build Coastguard Worker } 311