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 jdk.internal.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) {
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 }
88
89 /* Invoked by VM */
90 static void register(Object finalizee) {
91 new Finalizer(finalizee);
92 }
93
94 private void runFinalizer(JavaLangAccess jla) {
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.
138 Thread.currentThread().interrupt();
139 }
140 return null;
141 }});
142 }
143
144 /* Called by Runtime.runFinalization() */
145 static void runFinalization() {
146 if (VM.initLevel() == 0) {
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 }
212 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
213 running = true;
214 for (;;) {
215 try {
216 Finalizer f = (Finalizer)queue.remove();
217 f.runFinalizer(jla);
218 } catch (InterruptedException x) {
219 // ignore and continue
220 }
221 }
222 }
223 }
224
225 static {
226 ThreadGroup tg = Thread.currentThread().getThreadGroup();
227 for (ThreadGroup tgn = tg;
228 tgn != null;
229 tg = tgn, tgn = tg.getParent());
230 Thread finalizer = new FinalizerThread(tg);
231 finalizer.setPriority(Thread.MAX_PRIORITY - 2);
232 finalizer.setDaemon(true);
233 finalizer.start();
234 }
235
236 }
|
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 jdk.internal.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
40 /** Head of doubly linked list of Finalizers awaiting finalization. */
41 private static Finalizer unfinalized = null;
42
43 /** Lock guarding access to unfinalized list. */
44 private static final Object lock = new Object();
45
46 private Finalizer next, prev;
47
48 private Finalizer(Object finalizee) {
49 super(finalizee, queue);
50 // push onto unfinalized
51 synchronized (lock) {
52 if (unfinalized != null) {
53 this.next = unfinalized;
54 unfinalized.prev = this;
55 }
56 unfinalized = this;
57 }
58 }
59
60 static ReferenceQueue<Object> getQueue() {
61 return queue;
62 }
63
64 /* Invoked by VM */
65 static void register(Object finalizee) {
66 new Finalizer(finalizee);
67 }
68
69 private void deregisterAndRunFinalizer(JavaLangAccess jla) {
70 synchronized (lock) {
71 if (this.next == this) // already finalized
72 return;
73 // unlink from unfinalized
74 if (unfinalized == this)
75 unfinalized = this.next;
76 else
77 this.prev.next = this.next;
78 if (this.next != null)
79 this.next.prev = this.prev;
80 this.prev = null;
81 this.next = this; // mark as finalized
82 }
83 runFinalizer(jla);
84 }
85
86 private void runFinalizer(JavaLangAccess jla) {
87 try {
88 Object finalizee = this.get();
89 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
90 jla.invokeFinalize(finalizee);
91
92 /* Clear stack slot containing this variable, to decrease
93 the chances of false retention with a conservative GC */
94 finalizee = null;
95 }
96 } catch (Throwable x) { }
97 super.clear();
98 }
99
100 /* Create a privileged secondary finalizer thread in the system thread
101 group for the given Runnable, and wait for it to complete.
102
103 This method is used by both runFinalization and runFinalizersOnExit.
104 The former method invokes all pending finalizers, while the latter
105 invokes all uninvoked finalizers if on-exit finalization has been
106 enabled.
126 Thread.currentThread().interrupt();
127 }
128 return null;
129 }});
130 }
131
132 /* Called by Runtime.runFinalization() */
133 static void runFinalization() {
134 if (VM.initLevel() == 0) {
135 return;
136 }
137
138 forkSecondaryFinalizer(new Runnable() {
139 private volatile boolean running;
140 public void run() {
141 // in case of recursive call to run()
142 if (running)
143 return;
144 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
145 running = true;
146 for (Finalizer f; (f = (Finalizer)queue.poll()) != null; )
147 f.deregisterAndRunFinalizer(jla);
148 }
149 });
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 }
180
181 private static class FinalizerThread extends Thread {
182 private volatile boolean running;
183 FinalizerThread(ThreadGroup g) {
184 super(g, null, "Finalizer", 0, false);
185 }
186 public void run() {
187 // in case of recursive call to run()
188 if (running)
189 return;
190
191 // Finalizer thread starts before System.initializeSystemClass
192 // is called. Wait until JavaLangAccess is available
193 while (VM.initLevel() == 0) {
194 // delay until VM completes initialization
195 try {
196 VM.awaitInitLevel(1);
197 } catch (InterruptedException x) {
198 // ignore and continue
199 }
200 }
201 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
202 running = true;
203 for (;;) {
204 try {
205 Finalizer f = (Finalizer)queue.remove();
206 f.deregisterAndRunFinalizer(jla);
207 } catch (InterruptedException x) {
208 // ignore and continue
209 }
210 }
211 }
212 }
213
214 static {
215 ThreadGroup tg = Thread.currentThread().getThreadGroup();
216 for (ThreadGroup tgn = tg;
217 tgn != null;
218 tg = tgn, tgn = tg.getParent());
219 Thread finalizer = new FinalizerThread(tg);
220 finalizer.setPriority(Thread.MAX_PRIORITY - 2);
221 finalizer.setDaemon(true);
222 finalizer.start();
223 }
224
225 }
|