16a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson/* 26a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * Copyright (C) 2011 Google Inc. 36a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * 46a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 56a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * you may not use this file except in compliance with the License. 66a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * You may obtain a copy of the License at 76a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * 86a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 96a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * 106a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * Unless required by applicable law or agreed to in writing, software 116a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 126a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * See the License for the specific language governing permissions and 146a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson * limitations under the License. 156a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson */ 166a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 176a22fa91a64739523c1344023f6dfde57e53110eJesse Wilsonpackage libcore.java.lang.ref; 186a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 1964c6c367497c7fcf88e7527022234043e4460758Jesse Wilsonimport java.util.concurrent.CountDownLatch; 206a22fa91a64739523c1344023f6dfde57e53110eJesse Wilsonimport java.util.concurrent.atomic.AtomicBoolean; 219429d06c5427a6cac499ba90f138afac006135a2Jesse Wilsonimport java.util.concurrent.atomic.AtomicInteger; 226a22fa91a64739523c1344023f6dfde57e53110eJesse Wilsonimport junit.framework.TestCase; 236a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 246a22fa91a64739523c1344023f6dfde57e53110eJesse Wilsonpublic final class FinalizeTest extends TestCase { 256a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 266a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson public void testFinalizeIsCalled() throws Exception { 276a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson AtomicBoolean finalized = new AtomicBoolean(); 286a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson createFinalizableObject(finalized); 296a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 301a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson FinalizationTester.induceFinalization(); 316a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson if (!finalized.get()) { 323edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson fail("object not yet finalized"); 333edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson } 343edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson } 353edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson 363edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson /** 373edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson * Test verifies that runFinalization() does not mess up objects 383edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson * that should be finalized later on. http://b/6907299 393edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson */ 403edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson public void testInducedFinalization() throws Exception { 413edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson AtomicBoolean finalized1 = new AtomicBoolean(); 423edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson AtomicBoolean finalized2 = new AtomicBoolean(); 433edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson createFinalizableObject(finalized1); 443edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson createFinalizableObject(finalized2); 453edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson FinalizationTester.induceFinalization(); 463edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson if (!finalized1.get() || !finalized2.get()) { 473edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson fail("not yet finalized: " + finalized1.get() + " " + finalized2.get()); 486a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 496a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 506a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 511a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson /** Do not inline this method; that could break non-precise GCs. See FinalizationTester. */ 523edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson private X createFinalizableObject(final AtomicBoolean finalized) { 533edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson X result = new X() { 546a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson @Override protected void finalize() throws Throwable { 556a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson super.finalize(); 566a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson finalized.set(true); 576a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 586a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson }; 593edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson FinalizationTester.induceFinalization(); 603edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson // Dance around a bit to discourage dx from realizing that 'result' is no longer live. 613edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson boolean wasFinalized = finalized.get(); 623edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson if (wasFinalized) { 633edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson fail("finalizer called early"); // ...because 'result' is still live until we return. 643edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson } 653edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson // But we don't actually want to return 'result' because then we'd have to worry about 663edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson // the caller accidentally keeping it live. 673edd28a92fc86a1260347d0995e65a815d73bbbeMattias Petersson return wasFinalized ? result : null; 686a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 696a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 706a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson static class X {} 716a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 72cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier // Helper function since we do not want a vreg to keep the allocated object live. 73cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier // For b/25851249 74cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier private void exceptionInConstructor() { 75d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer boolean thrown = false; 766a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson try { 776a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson new ConstructionFails(); 78d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer // can't fail() here since AssertionFailedError extends AssertionError, which 79d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer // we expect 806a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } catch (AssertionError expected) { 81d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer thrown = true; 82d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer } 83d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer if (!thrown) { 84d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer fail(); 856a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 86cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier } 876a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 88cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier // http://b/issue?id=2136462 89cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier public void testBackFromTheDead() throws Exception { 90cf3d432790a78b7d81da656f9a666f3d1ce4962cMathieu Chartier exceptionInConstructor(); 911a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson FinalizationTester.induceFinalization(); 9229e0638aca737dd1093dac55216982b5af7d59a7Jesse Wilson assertTrue("object whose constructor threw was not finalized", ConstructionFails.finalized); 936a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 946a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 956a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson static class ConstructionFails { 9629e0638aca737dd1093dac55216982b5af7d59a7Jesse Wilson private static boolean finalized; 976a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 986a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson ConstructionFails() { 996a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson throw new AssertionError(); 1006a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 1016a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson 1026a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson @Override protected void finalize() throws Throwable { 10329e0638aca737dd1093dac55216982b5af7d59a7Jesse Wilson finalized = true; 1046a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 1056a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson } 10664c6c367497c7fcf88e7527022234043e4460758Jesse Wilson 10764c6c367497c7fcf88e7527022234043e4460758Jesse Wilson /** 10864c6c367497c7fcf88e7527022234043e4460758Jesse Wilson * The finalizer watch dog exits the VM if any object takes more than 10 s 10964c6c367497c7fcf88e7527022234043e4460758Jesse Wilson * to finalize. Check that objects near that limit are okay. 11064c6c367497c7fcf88e7527022234043e4460758Jesse Wilson */ 11164c6c367497c7fcf88e7527022234043e4460758Jesse Wilson public void testWatchdogDoesNotFailForObjectsThatAreNearTheDeadline() throws Exception { 1125e5169a394fd431609c3419bb4052e71dc73fed3Tobias Thierer CountDownLatch latch = new CountDownLatch(3); 11364c6c367497c7fcf88e7527022234043e4460758Jesse Wilson createSlowFinalizer( 1, latch); 11464c6c367497c7fcf88e7527022234043e4460758Jesse Wilson createSlowFinalizer(1000, latch); 11564c6c367497c7fcf88e7527022234043e4460758Jesse Wilson createSlowFinalizer(8000, latch); 1161a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson FinalizationTester.induceFinalization(); 11764c6c367497c7fcf88e7527022234043e4460758Jesse Wilson latch.await(); 11864c6c367497c7fcf88e7527022234043e4460758Jesse Wilson } 11964c6c367497c7fcf88e7527022234043e4460758Jesse Wilson 12064c6c367497c7fcf88e7527022234043e4460758Jesse Wilson public void createSlowFinalizer(final long millis, final CountDownLatch latch) { 12164c6c367497c7fcf88e7527022234043e4460758Jesse Wilson new Object() { 12264c6c367497c7fcf88e7527022234043e4460758Jesse Wilson @Override protected void finalize() throws Throwable { 12364c6c367497c7fcf88e7527022234043e4460758Jesse Wilson System.out.println("finalize sleeping " + millis + " ms"); 12464c6c367497c7fcf88e7527022234043e4460758Jesse Wilson Thread.sleep(millis); 12564c6c367497c7fcf88e7527022234043e4460758Jesse Wilson latch.countDown(); 12664c6c367497c7fcf88e7527022234043e4460758Jesse Wilson } 12764c6c367497c7fcf88e7527022234043e4460758Jesse Wilson }; 12864c6c367497c7fcf88e7527022234043e4460758Jesse Wilson } 1299429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson 1309429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson /** 1319429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson * Make sure that System.runFinalization() returns even if the finalization 1329429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson * queue is never completely empty. http://b/4193517 1339429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson */ 1349429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson public void testSystemRunFinalizationReturnsEvenIfQueueIsNonEmpty() throws Exception { 1359429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson AtomicInteger count = new AtomicInteger(); 1369429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson AtomicBoolean keepGoing = new AtomicBoolean(true); 1379429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson createChainedFinalizer(count, keepGoing); 1381a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson FinalizationTester.induceFinalization(); 1399429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson keepGoing.set(false); 1409429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson assertTrue(count.get() > 0); 1419429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson } 1429429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson 1439429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson public void createChainedFinalizer(final AtomicInteger counter, final AtomicBoolean keepGoing) { 1449429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson new Object() { 1459429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson @Override protected void finalize() throws Throwable { 1469429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson int count = counter.incrementAndGet(); 1479429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson System.out.println(count); 1489429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson if (keepGoing.get()) { 1499429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson createChainedFinalizer(counter, keepGoing); // recursive! 1509429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson } 1519429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson System.gc(); 1521a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson FinalizationTester.enqueueReferences(); 1539429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson } 1549429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson }; 1559429d06c5427a6cac499ba90f138afac006135a2Jesse Wilson } 1566a22fa91a64739523c1344023f6dfde57e53110eJesse Wilson} 157