115 private static Lock lock = new Lock(); 116 117 118 /* List of References waiting to be enqueued. The collector adds 119 * References to this list, while the Reference-handler thread removes 120 * them. This list is protected by the above lock object. The 121 * list uses the discovered field to link its elements. 122 */ 123 private static Reference<Object> pending = null; 124 125 /* High-priority thread to enqueue pending References 126 */ 127 private static class ReferenceHandler extends Thread { 128 129 ReferenceHandler(ThreadGroup g, String name) { 130 super(g, name); 131 } 132 133 public void run() { 134 for (;;) { 135 Reference<Object> r; 136 synchronized (lock) { 137 if (pending != null) { 138 r = pending; 139 pending = r.discovered; 140 r.discovered = null; 141 } else { 142 // The waiting on the lock may cause an OOME because it may try to allocate 143 // exception objects, so also catch OOME here to avoid silent exit of the 144 // reference handler thread. 145 // 146 // Explicitly define the order of the two exceptions we catch here 147 // when waiting for the lock. 148 // 149 // We do not want to try to potentially load the InterruptedException class 150 // (which would be done if this was its first use, and InterruptedException 151 // were checked first) in this situation. 152 // 153 // This may lead to the VM not ever trying to load the InterruptedException 154 // class again. 155 try { 156 try { 157 lock.wait(); 158 } catch (OutOfMemoryError x) { } 159 } catch (InterruptedException x) { } 160 continue; 161 } 162 } 163 164 // Fast path for cleaners 165 if (r instanceof Cleaner) { 166 ((Cleaner)r).clean(); 167 continue; 168 } 169 170 ReferenceQueue<Object> q = r.queue; 171 if (q != ReferenceQueue.NULL) q.enqueue(r); 172 } 173 } 174 } 175 176 static { 177 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 178 for (ThreadGroup tgn = tg; 179 tgn != null; 180 tg = tgn, tgn = tg.getParent()); 181 Thread handler = new ReferenceHandler(tg, "Reference Handler"); 182 /* If there were a special system-only priority greater than 183 * MAX_PRIORITY, it would be used here 184 */ 185 handler.setPriority(Thread.MAX_PRIORITY); 186 handler.setDaemon(true); 187 handler.start(); 188 } 189 190 191 /* -- Referent accessor and setters -- */ | 115 private static Lock lock = new Lock(); 116 117 118 /* List of References waiting to be enqueued. The collector adds 119 * References to this list, while the Reference-handler thread removes 120 * them. This list is protected by the above lock object. The 121 * list uses the discovered field to link its elements. 122 */ 123 private static Reference<Object> pending = null; 124 125 /* High-priority thread to enqueue pending References 126 */ 127 private static class ReferenceHandler extends Thread { 128 129 ReferenceHandler(ThreadGroup g, String name) { 130 super(g, name); 131 } 132 133 public void run() { 134 for (;;) { 135 try { 136 Reference<Object> r; 137 synchronized (lock) { 138 if (pending != null) { 139 r = pending; 140 pending = r.discovered; 141 r.discovered = null; 142 } else { 143 // The waiting on the lock may cause an OOME because it may try to allocate 144 // exception objects, so also catch OOME here to avoid silent exit of the 145 // reference handler thread. 146 // 147 // Explicitly define the order of the two exceptions we catch here 148 // when waiting for the lock. 149 // 150 // We do not want to try to potentially load the InterruptedException class 151 // (which would be done if this was its first use, and InterruptedException 152 // were checked first) in this situation. 153 // 154 // This may lead to the VM not ever trying to load the InterruptedException 155 // class again. 156 try { 157 try { 158 lock.wait(); 159 } catch (OutOfMemoryError x) { } 160 } catch (InterruptedException x) { } 161 continue; 162 } 163 } 164 165 // Fast path for cleaners 166 if (r instanceof Cleaner) { 167 ((Cleaner)r).clean(); 168 continue; 169 } 170 171 ReferenceQueue<Object> q = r.queue; 172 if (q != ReferenceQueue.NULL) q.enqueue(r); 173 174 } catch (OutOfMemoryError x) { } 175 } 176 } 177 } 178 179 static { 180 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 181 for (ThreadGroup tgn = tg; 182 tgn != null; 183 tg = tgn, tgn = tg.getParent()); 184 Thread handler = new ReferenceHandler(tg, "Reference Handler"); 185 /* If there were a special system-only priority greater than 186 * MAX_PRIORITY, it would be used here 187 */ 188 handler.setPriority(Thread.MAX_PRIORITY); 189 handler.setDaemon(true); 190 handler.start(); 191 } 192 193 194 /* -- Referent accessor and setters -- */ |