1 /* |
1 /* |
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
64 /* Invoked by VM */ |
64 /* Invoked by VM */ |
65 static void register(Object finalizee) { |
65 static void register(Object finalizee) { |
66 new Finalizer(finalizee); |
66 new Finalizer(finalizee); |
67 } |
67 } |
68 |
68 |
69 private void deregisterAndRunFinalizer(JavaLangAccess jla) { |
69 private void runFinalizer(JavaLangAccess jla) { |
70 synchronized (lock) { |
70 synchronized (lock) { |
71 if (this.next == this) // already finalized |
71 if (this.next == this) // already finalized |
72 return; |
72 return; |
73 // unlink from unfinalized |
73 // unlink from unfinalized |
74 if (unfinalized == this) |
74 if (unfinalized == this) |
78 if (this.next != null) |
78 if (this.next != null) |
79 this.next.prev = this.prev; |
79 this.next.prev = this.prev; |
80 this.prev = null; |
80 this.prev = null; |
81 this.next = this; // mark as finalized |
81 this.next = this; // mark as finalized |
82 } |
82 } |
83 runFinalizer(jla); |
|
84 } |
|
85 |
83 |
86 private void runFinalizer(JavaLangAccess jla) { |
|
87 try { |
84 try { |
88 Object finalizee = this.get(); |
85 Object finalizee = this.get(); |
89 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { |
86 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { |
90 jla.invokeFinalize(finalizee); |
87 jla.invokeFinalize(finalizee); |
91 |
88 |
92 /* Clear stack slot containing this variable, to decrease |
89 // Clear stack slot containing this variable, to decrease |
93 the chances of false retention with a conservative GC */ |
90 // the chances of false retention with a conservative GC |
94 finalizee = null; |
91 finalizee = null; |
95 } |
92 } |
96 } catch (Throwable x) { } |
93 } catch (Throwable x) { } |
97 super.clear(); |
94 super.clear(); |
98 } |
95 } |
99 |
96 |
100 /* Create a privileged secondary finalizer thread in the system thread |
97 /* Create a privileged secondary finalizer thread in the system thread |
101 group for the given Runnable, and wait for it to complete. |
98 * group for the given Runnable, and wait for it to complete. |
102 |
99 * |
103 This method is used by both runFinalization and runFinalizersOnExit. |
100 * This method is used by runFinalization. |
104 The former method invokes all pending finalizers, while the latter |
101 * |
105 invokes all uninvoked finalizers if on-exit finalization has been |
102 * It could have been implemented by offloading the work to the |
106 enabled. |
103 * regular finalizer thread and waiting for that thread to finish. |
107 |
104 * The advantage of creating a fresh thread, however, is that it insulates |
108 These two methods could have been implemented by offloading their work |
105 * invokers of that method from a stalled or deadlocked finalizer thread. |
109 to the regular finalizer thread and waiting for that thread to finish. |
|
110 The advantage of creating a fresh thread, however, is that it insulates |
|
111 invokers of these methods from a stalled or deadlocked finalizer thread. |
|
112 */ |
106 */ |
113 private static void forkSecondaryFinalizer(final Runnable proc) { |
107 private static void forkSecondaryFinalizer(final Runnable proc) { |
114 AccessController.doPrivileged( |
108 AccessController.doPrivileged( |
115 new PrivilegedAction<>() { |
109 new PrivilegedAction<>() { |
116 public Void run() { |
110 public Void run() { |
142 if (running) |
136 if (running) |
143 return; |
137 return; |
144 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
138 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
145 running = true; |
139 running = true; |
146 for (Finalizer f; (f = (Finalizer)queue.poll()) != null; ) |
140 for (Finalizer f; (f = (Finalizer)queue.poll()) != null; ) |
147 f.deregisterAndRunFinalizer(jla); |
141 f.runFinalizer(jla); |
148 } |
142 } |
149 }); |
143 }); |
150 } |
|
151 |
|
152 /* Invoked by java.lang.Shutdown */ |
|
153 static void runAllFinalizers() { |
|
154 if (VM.initLevel() == 0) { |
|
155 return; |
|
156 } |
|
157 |
|
158 forkSecondaryFinalizer(new Runnable() { |
|
159 private volatile boolean running; |
|
160 public void run() { |
|
161 // in case of recursive call to run() |
|
162 if (running) |
|
163 return; |
|
164 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
|
165 running = true; |
|
166 for (;;) { |
|
167 // "pollFirst" from unfinalized |
|
168 Finalizer f; |
|
169 synchronized (lock) { |
|
170 f = unfinalized; |
|
171 if (f == null) break; |
|
172 unfinalized = f.next; |
|
173 if (unfinalized != null) |
|
174 unfinalized.prev = null; |
|
175 f.next = f; // mark as finalized |
|
176 } |
|
177 f.runFinalizer(jla); |
|
178 }}}); |
|
179 } |
144 } |
180 |
145 |
181 private static class FinalizerThread extends Thread { |
146 private static class FinalizerThread extends Thread { |
182 private volatile boolean running; |
147 private volatile boolean running; |
183 FinalizerThread(ThreadGroup g) { |
148 FinalizerThread(ThreadGroup g) { |