blob: e3cf4eedbc62073fed9f42e7a6bd8375c3beebe5 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2008 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 */
jeffhao5d1ac922011-09-29 17:41:15 -070016
17import java.lang.ref.WeakReference;
Brian Carlstromc8494452014-02-20 13:50:05 -080018import java.util.ArrayList;
19import java.util.List;
jeffhao5d1ac922011-09-29 17:41:15 -070020
21/**
22 * Some finalizer tests.
23 *
24 * This only works if System.runFinalization() causes finalizers to run
25 * immediately or very soon.
26 */
27public class Main {
28 private static void snooze(int ms) {
29 try {
30 Thread.sleep(ms);
31 } catch (InterruptedException ie) {
32 System.out.println("Snooze: " + ie.getMessage());
33 }
34 }
35
Brian Carlstromc8494452014-02-20 13:50:05 -080036 public static WeakReference<FinalizerTest> makeRef() {
jeffhao5d1ac922011-09-29 17:41:15 -070037 /*
38 * Make ft in another thread, so there is no danger of
39 * a conservative reference leaking onto the main thread's
40 * stack.
41 */
42
Brian Carlstromc8494452014-02-20 13:50:05 -080043 final List<WeakReference<FinalizerTest>> wimp =
44 new ArrayList<WeakReference<FinalizerTest>>();
jeffhao5d1ac922011-09-29 17:41:15 -070045 Thread t = new Thread() {
46 public void run() {
47 FinalizerTest ft = new FinalizerTest("wahoo");
Brian Carlstromc8494452014-02-20 13:50:05 -080048 wimp.add(new WeakReference<FinalizerTest>(ft));
jeffhao5d1ac922011-09-29 17:41:15 -070049 ft = null;
50 }
51 };
52
53 t.start();
54
55 try {
56 t.join();
57 } catch (InterruptedException ie) {
58 throw new RuntimeException(ie);
59 }
60
Brian Carlstromc8494452014-02-20 13:50:05 -080061 return wimp.get(0);
jeffhao5d1ac922011-09-29 17:41:15 -070062 }
63
Brian Carlstromc8494452014-02-20 13:50:05 -080064 public static String wimpString(final WeakReference<FinalizerTest> wimp) {
jeffhao5d1ac922011-09-29 17:41:15 -070065 /*
66 * Do the work in another thread, so there is no danger of a
67 * conservative reference to ft leaking onto the main thread's
68 * stack.
69 */
70
71 final String[] s = new String[1];
72 Thread t = new Thread() {
73 public void run() {
Brian Carlstromc8494452014-02-20 13:50:05 -080074 FinalizerTest ref = wimp.get();
jeffhao5d1ac922011-09-29 17:41:15 -070075 if (ref != null) {
76 s[0] = ref.toString();
77 }
78 }
79 };
80
81 t.start();
82
83 try {
84 t.join();
85 } catch (InterruptedException ie) {
86 throw new RuntimeException(ie);
87 }
88
89 return s[0];
90 }
91
92 public static void main(String[] args) {
Brian Carlstromc8494452014-02-20 13:50:05 -080093 WeakReference<FinalizerTest> wimp = makeRef();
jeffhao5d1ac922011-09-29 17:41:15 -070094
95 System.out.println("wimp: " + wimpString(wimp));
96
97 /* this will try to collect and finalize ft */
98 System.out.println("gc");
Mathieu Chartier7befd0e2014-02-03 17:48:41 -080099 Runtime.getRuntime().gc();
jeffhao5d1ac922011-09-29 17:41:15 -0700100
101 System.out.println("wimp: " + wimpString(wimp));
102 System.out.println("finalize");
103 System.runFinalization();
104 System.out.println("wimp: " + wimpString(wimp));
105
106 System.out.println("sleep");
107 snooze(1000);
108
109 System.out.println("reborn: " + FinalizerTest.mReborn);
110 System.out.println("wimp: " + wimpString(wimp));
111 System.out.println("reset reborn");
Mathieu Chartier7befd0e2014-02-03 17:48:41 -0800112 Runtime.getRuntime().gc();
jeffhao5d1ac922011-09-29 17:41:15 -0700113 FinalizerTest.mReborn = FinalizerTest.mNothing;
114 System.out.println("gc + finalize");
115 System.gc();
116 System.runFinalization();
117
118 System.out.println("sleep");
119 snooze(1000);
120
121 System.out.println("reborn: " + FinalizerTest.mReborn);
122 System.out.println("wimp: " + wimpString(wimp));
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700123 // Test runFinalization with multiple objects.
124 runFinalizationTest();
125 }
126
127 static class FinalizeCounter {
Mathieu Chartierbbb54792014-10-15 09:59:03 -0700128 public static final int maxCount = 1024;
129 public static boolean finalized[] = new boolean[maxCount];
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700130 private static Object finalizeLock = new Object();
131 private static volatile int finalizeCount = 0;
132 private int index;
133 static int getCount() {
134 return finalizeCount;
135 }
Mathieu Chartierbbb54792014-10-15 09:59:03 -0700136 static void printNonFinalized() {
137 for (int i = 0; i < maxCount; ++i) {
138 if (!FinalizeCounter.finalized[i]) {
139 System.err.println("Element " + i + " was not finalized");
140 }
141 }
142 }
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700143 FinalizeCounter(int index) {
144 this.index = index;
145 }
146 protected void finalize() {
147 synchronized(finalizeLock) {
148 ++finalizeCount;
Mathieu Chartierbbb54792014-10-15 09:59:03 -0700149 finalized[index] = true;
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700150 }
151 }
152 }
153
Mathieu Chartier8cb03062014-10-13 10:58:01 -0700154 private static void allocFinalizableObjects(int count) {
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700155 Object[] objs = new Object[count];
156 for (int i = 0; i < count; ++i) {
157 objs[i] = new FinalizeCounter(i);
158 }
Mathieu Chartier8cb03062014-10-13 10:58:01 -0700159 }
160
161 private static void runFinalizationTest() {
Mathieu Chartierbbb54792014-10-15 09:59:03 -0700162 allocFinalizableObjects(FinalizeCounter.maxCount);
Mathieu Chartier8cb03062014-10-13 10:58:01 -0700163 Runtime.getRuntime().gc();
Mathieu Chartier3a5fa5e2014-09-04 14:15:35 -0700164 System.runFinalization();
Mathieu Chartierbbb54792014-10-15 09:59:03 -0700165 System.out.println("Finalized " + FinalizeCounter.getCount() + " / " + FinalizeCounter.maxCount);
166 if (FinalizeCounter.getCount() != FinalizeCounter.maxCount) {
167 // Print out all the finalized elements.
168 FinalizeCounter.printNonFinalized();
169 // Try to sleep for a couple seconds to see if the objects became finalized after.
170 try {
171 java.lang.Thread.sleep(2000);
172 } catch (InterruptedException e) {
173 }
174 System.out.println("After sleep finalized " + FinalizeCounter.getCount() + " / " + FinalizeCounter.maxCount);
175 FinalizeCounter.printNonFinalized();
176 }
jeffhao5d1ac922011-09-29 17:41:15 -0700177 }
Brian Carlstromc8494452014-02-20 13:50:05 -0800178
179 public static class FinalizerTest {
180 public static FinalizerTest mNothing = new FinalizerTest("nothing");
181 public static FinalizerTest mReborn = mNothing;
182
183 private final String message;
184 private boolean finalized = false;
185
186 public FinalizerTest(String message) {
187 this.message = message;
188 }
189
190 public String toString() {
191 return "[FinalizerTest message=" + message +
192 ", finalized=" + finalized + "]";
193 }
194
195 protected void finalize() {
196 finalized = true;
197 mReborn = this;
198 }
199 }
jeffhao5d1ac922011-09-29 17:41:15 -0700200}