1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
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
43 next = null,
44 prev = null;
45
46 private boolean hasBeenFinalized() {
47 return (next == this);
48 }
49
50 private void add() {
51 synchronized (lock) {
52 if (unfinalized != null) {
53 this.next = unfinalized;
54 unfinalized.prev = this;
55 }
56 unfinalized = this;
57 }
58 }
59
60 private void remove() {
61 synchronized (lock) {
62 if (unfinalized == this) {
63 if (this.next != null) {
64 unfinalized = this.next;
65 } else {
66 unfinalized = this.prev;
67 }
68 }
69 if (this.next != null) {
70 this.next.prev = this.prev;
71 }
72 if (this.prev != null) {
73 this.prev.next = this.next;
74 }
75 this.next = this; /* Indicates that this has been finalized */
76 this.prev = this;
77 }
78 }
79
80 private Finalizer(Object finalizee) {
81 super(finalizee, queue);
82 add();
83 }
84
85 static ReferenceQueue<Object> getQueue() {
86 return queue;
87 }
95 synchronized (this) {
96 if (hasBeenFinalized()) return;
97 remove();
98 }
99 try {
100 Object finalizee = this.get();
101 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
102 jla.invokeFinalize(finalizee);
103
104 /* Clear stack slot containing this variable, to decrease
105 the chances of false retention with a conservative GC */
106 finalizee = null;
107 }
108 } catch (Throwable x) { }
109 super.clear();
110 }
111
112 /* Create a privileged secondary finalizer thread in the system thread
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 {
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()
154 if (running)
155 return;
156 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
157 running = true;
158 for (;;) {
159 Finalizer f = (Finalizer)queue.poll();
160 if (f == null) break;
161 f.runFinalizer(jla);
162 }
163 }
164 });
165 }
166
167 /* Invoked by java.lang.Shutdown */
168 static void runAllFinalizers() {
169 if (VM.initLevel() == 0) {
170 return;
171 }
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.initLevel() == 0) {
205 // delay until VM completes initialization
206 try {
207 VM.awaitInitLevel(1);
208 } catch (InterruptedException x) {
209 // ignore and continue
210 }
211 }
|
1 /*
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.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
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
43 next = null,
44 prev = null;
45
46 private boolean hasBeenFinalized() {
47 return (next == this);
48 }
49
50 private void add() {
51 synchronized (lock) {
52 if (unfinalized != null) {
53 this.next = unfinalized;
54 unfinalized.prev = this;
55 }
56 unfinalized = this;
57 }
58 }
59
60 private void remove() {
61 synchronized (lock) {
62 if (unfinalized == this) {
63 unfinalized = this.next;
64 }
65 if (this.next != null) {
66 this.next.prev = this.prev;
67 }
68 if (this.prev != null) {
69 this.prev.next = this.next;
70 }
71 this.next = this; /* Indicates that this has been finalized */
72 this.prev = this;
73 }
74 }
75
76 private Finalizer(Object finalizee) {
77 super(finalizee, queue);
78 add();
79 }
80
81 static ReferenceQueue<Object> getQueue() {
82 return queue;
83 }
91 synchronized (this) {
92 if (hasBeenFinalized()) return;
93 remove();
94 }
95 try {
96 Object finalizee = this.get();
97 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
98 jla.invokeFinalize(finalizee);
99
100 /* Clear stack slot containing this variable, to decrease
101 the chances of false retention with a conservative GC */
102 finalizee = null;
103 }
104 } catch (Throwable x) { }
105 super.clear();
106 }
107
108 /* Create a privileged secondary finalizer thread in the system thread
109 group for the given Runnable, and wait for it to complete.
110
111 This method is used by both runFinalization.
112 The former method invokes all pending finalizers, while the latter
113 invokes all uninvoked finalizers if on-exit finalization has been
114 enabled.
115
116 These two methods could have been implemented by offloading their work
117 to the regular finalizer thread and waiting for that thread to finish.
118 The advantage of creating a fresh thread, however, is that it insulates
119 invokers of these methods from a stalled or deadlocked finalizer thread.
120 */
121 private static void forkSecondaryFinalizer(final Runnable proc) {
122 AccessController.doPrivileged(
123 new PrivilegedAction<>() {
124 public Void run() {
125 ThreadGroup tg = Thread.currentThread().getThreadGroup();
126 for (ThreadGroup tgn = tg;
127 tgn != null;
128 tg = tgn, tgn = tg.getParent());
129 Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
130 sft.start();
131 try {
143 return;
144 }
145
146 forkSecondaryFinalizer(new Runnable() {
147 private volatile boolean running;
148 public void run() {
149 // in case of recursive call to run()
150 if (running)
151 return;
152 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
153 running = true;
154 for (;;) {
155 Finalizer f = (Finalizer)queue.poll();
156 if (f == null) break;
157 f.runFinalizer(jla);
158 }
159 }
160 });
161 }
162
163 private static class FinalizerThread extends Thread {
164 private volatile boolean running;
165 FinalizerThread(ThreadGroup g) {
166 super(g, null, "Finalizer", 0, false);
167 }
168 public void run() {
169 // in case of recursive call to run()
170 if (running)
171 return;
172
173 // Finalizer thread starts before System.initializeSystemClass
174 // is called. Wait until JavaLangAccess is available
175 while (VM.initLevel() == 0) {
176 // delay until VM completes initialization
177 try {
178 VM.awaitInitLevel(1);
179 } catch (InterruptedException x) {
180 // ignore and continue
181 }
182 }
|