25 |
25 |
26 package java.lang.ref; |
26 package java.lang.ref; |
27 |
27 |
28 import java.security.PrivilegedAction; |
28 import java.security.PrivilegedAction; |
29 import java.security.AccessController; |
29 import java.security.AccessController; |
30 |
30 import sun.misc.JavaLangAccess; |
|
31 import sun.misc.SharedSecrets; |
|
32 import sun.misc.VM; |
31 |
33 |
32 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in |
34 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in |
33 same package as the Reference |
35 same package as the Reference |
34 class */ |
36 class */ |
35 |
|
36 /* A native method that invokes an arbitrary object's finalize method is |
|
37 required since the finalize method is protected |
|
38 */ |
|
39 static native void invokeFinalizeMethod(Object o) throws Throwable; |
|
40 |
37 |
41 private static ReferenceQueue<Object> queue = new ReferenceQueue<>(); |
38 private static ReferenceQueue<Object> queue = new ReferenceQueue<>(); |
42 private static Finalizer unfinalized = null; |
39 private static Finalizer unfinalized = null; |
43 private static final Object lock = new Object(); |
40 private static final Object lock = new Object(); |
44 |
41 |
88 /* Invoked by VM */ |
85 /* Invoked by VM */ |
89 static void register(Object finalizee) { |
86 static void register(Object finalizee) { |
90 new Finalizer(finalizee); |
87 new Finalizer(finalizee); |
91 } |
88 } |
92 |
89 |
93 private void runFinalizer() { |
90 private void runFinalizer(JavaLangAccess jla) { |
94 synchronized (this) { |
91 synchronized (this) { |
95 if (hasBeenFinalized()) return; |
92 if (hasBeenFinalized()) return; |
96 remove(); |
93 remove(); |
97 } |
94 } |
98 try { |
95 try { |
99 Object finalizee = this.get(); |
96 Object finalizee = this.get(); |
100 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { |
97 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { |
101 invokeFinalizeMethod(finalizee); |
98 jla.invokeFinalize(finalizee); |
|
99 |
102 /* Clear stack slot containing this variable, to decrease |
100 /* Clear stack slot containing this variable, to decrease |
103 the chances of false retention with a conservative GC */ |
101 the chances of false retention with a conservative GC */ |
104 finalizee = null; |
102 finalizee = null; |
105 } |
103 } |
106 } catch (Throwable x) { } |
104 } catch (Throwable x) { } |
139 }}); |
137 }}); |
140 } |
138 } |
141 |
139 |
142 /* Called by Runtime.runFinalization() */ |
140 /* Called by Runtime.runFinalization() */ |
143 static void runFinalization() { |
141 static void runFinalization() { |
|
142 if (!VM.isBooted()) { |
|
143 return; |
|
144 } |
|
145 |
144 forkSecondaryFinalizer(new Runnable() { |
146 forkSecondaryFinalizer(new Runnable() { |
145 private volatile boolean running; |
147 private volatile boolean running; |
146 public void run() { |
148 public void run() { |
147 if (running) |
149 if (running) |
148 return; |
150 return; |
|
151 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
149 running = true; |
152 running = true; |
150 for (;;) { |
153 for (;;) { |
151 Finalizer f = (Finalizer)queue.poll(); |
154 Finalizer f = (Finalizer)queue.poll(); |
152 if (f == null) break; |
155 if (f == null) break; |
153 f.runFinalizer(); |
156 f.runFinalizer(jla); |
154 } |
157 } |
155 } |
158 } |
156 }); |
159 }); |
157 } |
160 } |
158 |
161 |
159 /* Invoked by java.lang.Shutdown */ |
162 /* Invoked by java.lang.Shutdown */ |
160 static void runAllFinalizers() { |
163 static void runAllFinalizers() { |
|
164 if (!VM.isBooted()) { |
|
165 return; |
|
166 } |
|
167 |
161 forkSecondaryFinalizer(new Runnable() { |
168 forkSecondaryFinalizer(new Runnable() { |
162 private volatile boolean running; |
169 private volatile boolean running; |
163 public void run() { |
170 public void run() { |
164 if (running) |
171 if (running) |
165 return; |
172 return; |
|
173 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
166 running = true; |
174 running = true; |
167 for (;;) { |
175 for (;;) { |
168 Finalizer f; |
176 Finalizer f; |
169 synchronized (lock) { |
177 synchronized (lock) { |
170 f = unfinalized; |
178 f = unfinalized; |
171 if (f == null) break; |
179 if (f == null) break; |
172 unfinalized = f.next; |
180 unfinalized = f.next; |
173 } |
181 } |
174 f.runFinalizer(); |
182 f.runFinalizer(jla); |
175 }}}); |
183 }}}); |
176 } |
184 } |
177 |
185 |
178 private static class FinalizerThread extends Thread { |
186 private static class FinalizerThread extends Thread { |
179 private volatile boolean running; |
187 private volatile boolean running; |
181 super(g, "Finalizer"); |
189 super(g, "Finalizer"); |
182 } |
190 } |
183 public void run() { |
191 public void run() { |
184 if (running) |
192 if (running) |
185 return; |
193 return; |
|
194 |
|
195 // Finalizer thread starts before System.initializeSystemClass |
|
196 // is called. Wait until JavaLangAccess is available |
|
197 while (!VM.isBooted()) { |
|
198 // delay until VM completes initialization |
|
199 try { |
|
200 VM.awaitBooted(); |
|
201 } catch (InterruptedException x) { |
|
202 // ignore and continue |
|
203 } |
|
204 } |
|
205 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
186 running = true; |
206 running = true; |
187 for (;;) { |
207 for (;;) { |
188 try { |
208 try { |
189 Finalizer f = (Finalizer)queue.remove(); |
209 Finalizer f = (Finalizer)queue.remove(); |
190 f.runFinalizer(); |
210 f.runFinalizer(jla); |
191 } catch (InterruptedException x) { |
211 } catch (InterruptedException x) { |
192 continue; |
212 // ignore and continue |
193 } |
213 } |
194 } |
214 } |
195 } |
215 } |
196 } |
216 } |
197 |
217 |