12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.ref;
27
28 import java.security.PrivilegedAction;
29 import java.security.AccessController;
30 import jdk.internal.misc.JavaLangAccess;
31 import jdk.internal.misc.SharedSecrets;
32 import sun.misc.ManagedLocalsThread;
33 import sun.misc.VM;
34
35 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
36 same package as the Reference
37 class */
38
39 private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
40 private static Finalizer unfinalized = null;
41 private static final Object lock = new Object();
42
43 private Finalizer
44 next = null,
45 prev = null;
46
47 private boolean hasBeenFinalized() {
48 return (next == this);
49 }
50
51 private void add() {
52 synchronized (lock) {
114 group for the given Runnable, and wait for it to complete.
115
116 This method is used by both runFinalization and runFinalizersOnExit.
117 The former method invokes all pending finalizers, while the latter
118 invokes all uninvoked finalizers if on-exit finalization has been
119 enabled.
120
121 These two methods could have been implemented by offloading their work
122 to the regular finalizer thread and waiting for that thread to finish.
123 The advantage of creating a fresh thread, however, is that it insulates
124 invokers of these methods from a stalled or deadlocked finalizer thread.
125 */
126 private static void forkSecondaryFinalizer(final Runnable proc) {
127 AccessController.doPrivileged(
128 new PrivilegedAction<>() {
129 public Void run() {
130 ThreadGroup tg = Thread.currentThread().getThreadGroup();
131 for (ThreadGroup tgn = tg;
132 tgn != null;
133 tg = tgn, tgn = tg.getParent());
134 Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer");
135 sft.start();
136 try {
137 sft.join();
138 } catch (InterruptedException x) {
139 Thread.currentThread().interrupt();
140 }
141 return null;
142 }});
143 }
144
145 /* Called by Runtime.runFinalization() */
146 static void runFinalization() {
147 if (!VM.isBooted()) {
148 return;
149 }
150
151 forkSecondaryFinalizer(new Runnable() {
152 private volatile boolean running;
153 public void run() {
154 // in case of recursive call to run()
173
174 forkSecondaryFinalizer(new Runnable() {
175 private volatile boolean running;
176 public void run() {
177 // in case of recursive call to run()
178 if (running)
179 return;
180 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
181 running = true;
182 for (;;) {
183 Finalizer f;
184 synchronized (lock) {
185 f = unfinalized;
186 if (f == null) break;
187 unfinalized = f.next;
188 }
189 f.runFinalizer(jla);
190 }}});
191 }
192
193 private static class FinalizerThread extends ManagedLocalsThread {
194 private volatile boolean running;
195 FinalizerThread(ThreadGroup g) {
196 super(g, "Finalizer");
197 }
198 public void run() {
199 // in case of recursive call to run()
200 if (running)
201 return;
202
203 // Finalizer thread starts before System.initializeSystemClass
204 // is called. Wait until JavaLangAccess is available
205 while (!VM.isBooted()) {
206 // delay until VM completes initialization
207 try {
208 VM.awaitBooted();
209 } catch (InterruptedException x) {
210 // ignore and continue
211 }
212 }
213 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
214 running = true;
215 for (;;) {
216 try {
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.ref;
27
28 import java.security.PrivilegedAction;
29 import java.security.AccessController;
30 import jdk.internal.misc.JavaLangAccess;
31 import jdk.internal.misc.SharedSecrets;
32 import sun.misc.VM;
33
34 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
35 same package as the Reference
36 class */
37
38 private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
39 private static Finalizer unfinalized = null;
40 private static final Object lock = new Object();
41
42 private Finalizer
43 next = null,
44 prev = null;
45
46 private boolean hasBeenFinalized() {
47 return (next == this);
48 }
49
50 private void add() {
51 synchronized (lock) {
113 group for the given Runnable, and wait for it to complete.
114
115 This method is used by both runFinalization and runFinalizersOnExit.
116 The former method invokes all pending finalizers, while the latter
117 invokes all uninvoked finalizers if on-exit finalization has been
118 enabled.
119
120 These two methods could have been implemented by offloading their work
121 to the regular finalizer thread and waiting for that thread to finish.
122 The advantage of creating a fresh thread, however, is that it insulates
123 invokers of these methods from a stalled or deadlocked finalizer thread.
124 */
125 private static void forkSecondaryFinalizer(final Runnable proc) {
126 AccessController.doPrivileged(
127 new PrivilegedAction<>() {
128 public Void run() {
129 ThreadGroup tg = Thread.currentThread().getThreadGroup();
130 for (ThreadGroup tgn = tg;
131 tgn != null;
132 tg = tgn, tgn = tg.getParent());
133 Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
134 sft.start();
135 try {
136 sft.join();
137 } catch (InterruptedException x) {
138 Thread.currentThread().interrupt();
139 }
140 return null;
141 }});
142 }
143
144 /* Called by Runtime.runFinalization() */
145 static void runFinalization() {
146 if (!VM.isBooted()) {
147 return;
148 }
149
150 forkSecondaryFinalizer(new Runnable() {
151 private volatile boolean running;
152 public void run() {
153 // in case of recursive call to run()
172
173 forkSecondaryFinalizer(new Runnable() {
174 private volatile boolean running;
175 public void run() {
176 // in case of recursive call to run()
177 if (running)
178 return;
179 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
180 running = true;
181 for (;;) {
182 Finalizer f;
183 synchronized (lock) {
184 f = unfinalized;
185 if (f == null) break;
186 unfinalized = f.next;
187 }
188 f.runFinalizer(jla);
189 }}});
190 }
191
192 private static class FinalizerThread extends Thread {
193 private volatile boolean running;
194 FinalizerThread(ThreadGroup g) {
195 super(g, null, "Finalizer", 0, false);
196 }
197 public void run() {
198 // in case of recursive call to run()
199 if (running)
200 return;
201
202 // Finalizer thread starts before System.initializeSystemClass
203 // is called. Wait until JavaLangAccess is available
204 while (!VM.isBooted()) {
205 // delay until VM completes initialization
206 try {
207 VM.awaitBooted();
208 } catch (InterruptedException x) {
209 // ignore and continue
210 }
211 }
212 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
213 running = true;
214 for (;;) {
215 try {
|