01: /*
02: * @(#)Cleaner.java 1.2 04/12/06
03: *
04: * Copyright (c) 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
05: *
06: * See the file "LICENSE.txt" for information on usage and redistribution
07: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
08: */
09: package org.pnuts.lib;
10:
11: import java.lang.ref.Reference;
12: import java.lang.ref.PhantomReference;
13: import java.lang.ref.ReferenceQueue;
14: import java.util.HashSet;
15: import java.util.Set;
16:
17: /**
18: * This class provides an alternative to Object.finalize() method.
19: */
20: public class Cleaner extends PhantomReference {
21:
22: private static final ReferenceQueue rq = new ReferenceQueue();
23: private static Set set = new HashSet();
24:
25: static {
26: startHandler();
27: }
28:
29: private final Runnable command;
30:
31: private Cleaner(Object referent, Runnable command) {
32: super (referent, rq);
33: this .command = command;
34: }
35:
36: /**
37: * Registers a command as the finalizer of the target object.
38: * When the target is ready to be reclaimed, the registered command is executed.
39: *
40: * @param target the target object
41: * @param command the command to be registered
42: * @return A Cleaner object that should be assigned to a member variable of the target object.
43: */
44: public static Cleaner create(Object target, Runnable command) {
45: if (command != null) {
46: Cleaner cleaner = new Cleaner(target, command);
47: set.add(cleaner);
48: return cleaner;
49: }
50: return null;
51: }
52:
53: protected void error(Throwable t) {
54: // ignore
55: }
56:
57: void clean() {
58: if (!set.remove(this )) {
59: return;
60: }
61: try {
62: command.run();
63: } catch (Throwable t) {
64: error(t);
65: }
66: }
67:
68: private static synchronized boolean remove(Cleaner cleaner) {
69: if (set.isEmpty()) {
70: return false;
71: } else {
72: set.remove(cleaner);
73: return true;
74: }
75: }
76:
77: private static void startHandler() {
78: Handler handler = new Handler();
79: handler.setDaemon(true);
80: handler.setPriority(Thread.MAX_PRIORITY - 1);
81: handler.start();
82: }
83:
84: private static class Handler extends Thread {
85: public void run() {
86: for (;;) {
87: try {
88: Reference r = rq.remove();
89: if (r instanceof Cleaner) {
90: ((Cleaner) r).clean();
91: continue;
92: }
93: } catch (InterruptedException e) {
94: }
95: }
96: }
97: }
98: }
|