• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
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 import java.util.concurrent.CountDownLatch;
18 import static java.util.concurrent.TimeUnit.MINUTES;
19 
20 /**
21  * Test a class with a bad finalizer.
22  *
23  * This test is inherently flaky. It assumes that the system will schedule the finalizer daemon
24  * and finalizer watchdog daemon enough to reach the timeout and throwing the fatal exception.
25  */
26 public class Main {
main(String[] args)27     public static void main(String[] args) throws Exception {
28         CountDownLatch finalizerWait = new CountDownLatch(1);
29 
30         // A separate method to ensure no dex register keeps the object alive.
31         createBadFinalizer(finalizerWait);
32 
33         // Should have at least two iterations to trigger finalization, but just to make sure run
34         // some more.
35         for (int i = 0; i < 5; i++) {
36             Runtime.getRuntime().gc();
37         }
38 
39         // Now wait for the finalizer to start running. Give it a minute.
40         finalizerWait.await(1, MINUTES);
41 
42         // Now fall asleep with a timeout. The timeout is large enough that we expect the
43         // finalizer daemon to have killed the process before the deadline elapses.
44         // Note: the timeout is here (instead of an infinite sleep) to protect the test
45         //       environment (e.g., in case this is run without a timeout wrapper).
46         final long timeout = 60 * 1000;  // 1 minute.
47         long remainingWait = timeout;
48         final long waitStart = System.currentTimeMillis();
49         while (remainingWait > 0) {
50             synchronized (args) {  // Just use an already existing object for simplicity...
51                 try {
52                     args.wait(remainingWait);
53                 } catch (Exception e) {
54                 }
55             }
56             remainingWait = timeout - (System.currentTimeMillis() - waitStart);
57         }
58 
59         // We should not get here.
60         System.out.println("UNREACHABLE");
61         System.exit(0);
62     }
63 
createBadFinalizer(CountDownLatch finalizerWait)64     private static void createBadFinalizer(CountDownLatch finalizerWait) {
65         BadFinalizer bf = new BadFinalizer(finalizerWait);
66 
67         System.out.println("About to null reference.");
68         bf = null;  // Not that this would make a difference, could be eliminated earlier.
69     }
70 
snooze(int ms)71     public static void snooze(int ms) {
72         try {
73             Thread.sleep(ms);
74         } catch (InterruptedException ie) {
75         }
76     }
77 
78     /**
79      * Class with a bad finalizer.
80      */
81     public static class BadFinalizer {
82         private CountDownLatch finalizerWait;
83         private volatile int j = 0;  // Volatile in an effort to curb loop optimization.
84 
BadFinalizer(CountDownLatch finalizerWait)85         public BadFinalizer(CountDownLatch finalizerWait) {
86             this.finalizerWait = finalizerWait;
87         }
88 
finalize()89         protected void finalize() {
90             finalizerWait.countDown();
91 
92             System.out.println("Finalizer started and spinning...");
93 
94             /* spin for a bit */
95             long start, end;
96             start = System.nanoTime();
97             for (int i = 0; i < 1000000; i++) {
98                 j++;
99             }
100             end = System.nanoTime();
101             System.out.println("Finalizer done spinning.");
102 
103             System.out.println("Finalizer sleeping forever now.");
104             while (true) {
105                 snooze(10000);
106             }
107         }
108     }
109 }
110