1 /* 2 * Copyright (C) 2011 Google Inc. 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 package libcore.java.lang.ref; 18 19 import java.util.concurrent.CountDownLatch; 20 import java.util.concurrent.atomic.AtomicBoolean; 21 import java.util.concurrent.atomic.AtomicInteger; 22 import junit.framework.TestCase; 23 24 public final class FinalizeTest extends TestCase { 25 testFinalizeIsCalled()26 public void testFinalizeIsCalled() throws Exception { 27 AtomicBoolean finalized = new AtomicBoolean(); 28 createFinalizableObject(finalized); 29 30 FinalizationTester.induceFinalization(); 31 if (!finalized.get()) { 32 fail("object not yet finalized"); 33 } 34 } 35 36 /** 37 * Test verifies that runFinalization() does not mess up objects 38 * that should be finalized later on. http://b/6907299 39 */ testInducedFinalization()40 public void testInducedFinalization() throws Exception { 41 AtomicBoolean finalized1 = new AtomicBoolean(); 42 AtomicBoolean finalized2 = new AtomicBoolean(); 43 createFinalizableObject(finalized1); 44 createFinalizableObject(finalized2); 45 FinalizationTester.induceFinalization(); 46 if (!finalized1.get() || !finalized2.get()) { 47 fail("not yet finalized: " + finalized1.get() + " " + finalized2.get()); 48 } 49 } 50 51 /** Do not inline this method; that could break non-precise GCs. See FinalizationTester. */ createFinalizableObject(final AtomicBoolean finalized)52 private X createFinalizableObject(final AtomicBoolean finalized) { 53 X result = new X() { 54 @Override protected void finalize() throws Throwable { 55 super.finalize(); 56 finalized.set(true); 57 } 58 }; 59 FinalizationTester.induceFinalization(); 60 // Dance around a bit to discourage dx from realizing that 'result' is no longer live. 61 boolean wasFinalized = finalized.get(); 62 if (wasFinalized) { 63 fail("finalizer called early"); // ...because 'result' is still live until we return. 64 } 65 // But we don't actually want to return 'result' because then we'd have to worry about 66 // the caller accidentally keeping it live. 67 return wasFinalized ? result : null; 68 } 69 70 static class X {} 71 72 // Helper function since we do not want a vreg to keep the allocated object live. 73 // For b/25851249 exceptionInConstructor()74 private void exceptionInConstructor() { 75 boolean thrown = false; 76 try { 77 new ConstructionFails(); 78 // can't fail() here since AssertionFailedError extends AssertionError, which 79 // we expect 80 } catch (AssertionError expected) { 81 thrown = true; 82 } 83 if (!thrown) { 84 fail(); 85 } 86 } 87 88 // http://b/issue?id=2136462 testBackFromTheDead()89 public void testBackFromTheDead() throws Exception { 90 exceptionInConstructor(); 91 FinalizationTester.induceFinalization(); 92 assertTrue("object whose constructor threw was not finalized", ConstructionFails.finalized); 93 } 94 95 static class ConstructionFails { 96 private static boolean finalized; 97 ConstructionFails()98 ConstructionFails() { 99 throw new AssertionError(); 100 } 101 finalize()102 @Override protected void finalize() throws Throwable { 103 finalized = true; 104 } 105 } 106 107 /** 108 * The finalizer watch dog exits the VM if any object takes more than 10 s 109 * to finalize. Check that objects near that limit are okay. 110 */ testWatchdogDoesNotFailForObjectsThatAreNearTheDeadline()111 public void testWatchdogDoesNotFailForObjectsThatAreNearTheDeadline() throws Exception { 112 CountDownLatch latch = new CountDownLatch(3); 113 createSlowFinalizer( 1, latch); 114 createSlowFinalizer(1000, latch); 115 createSlowFinalizer(8000, latch); 116 FinalizationTester.induceFinalization(); 117 latch.await(); 118 } 119 createSlowFinalizer(final long millis, final CountDownLatch latch)120 public void createSlowFinalizer(final long millis, final CountDownLatch latch) { 121 new Object() { 122 @Override protected void finalize() throws Throwable { 123 System.out.println("finalize sleeping " + millis + " ms"); 124 Thread.sleep(millis); 125 latch.countDown(); 126 } 127 }; 128 } 129 130 /** 131 * Make sure that System.runFinalization() returns even if the finalization 132 * queue is never completely empty. http://b/4193517 133 */ testSystemRunFinalizationReturnsEvenIfQueueIsNonEmpty()134 public void testSystemRunFinalizationReturnsEvenIfQueueIsNonEmpty() throws Exception { 135 AtomicInteger count = new AtomicInteger(); 136 AtomicBoolean keepGoing = new AtomicBoolean(true); 137 createChainedFinalizer(count, keepGoing); 138 FinalizationTester.induceFinalization(); 139 keepGoing.set(false); 140 assertTrue(count.get() > 0); 141 } 142 createChainedFinalizer(final AtomicInteger counter, final AtomicBoolean keepGoing)143 public void createChainedFinalizer(final AtomicInteger counter, final AtomicBoolean keepGoing) { 144 new Object() { 145 @Override protected void finalize() throws Throwable { 146 int count = counter.incrementAndGet(); 147 System.out.println(count); 148 if (keepGoing.get()) { 149 createChainedFinalizer(counter, keepGoing); // recursive! 150 } 151 System.gc(); 152 FinalizationTester.enqueueReferences(); 153 } 154 }; 155 } 156 } 157