45 private static int state = RUNNING; |
43 private static int state = RUNNING; |
46 |
44 |
47 /* Should we run all finalizers upon exit? */ |
45 /* Should we run all finalizers upon exit? */ |
48 private static boolean runFinalizersOnExit = false; |
46 private static boolean runFinalizersOnExit = false; |
49 |
47 |
50 /* The set of registered, wrapped hooks, or null if there aren't any */ |
48 // The system shutdown hooks are registered with a predefined slot. |
51 private static ArrayList<Runnable> hooks = new ArrayList<Runnable>(); |
49 // The list of shutdown hooks is as follows: |
|
50 // (0) Console restore hook |
|
51 // (1) Application hooks |
|
52 // (2) DeleteOnExit hook |
|
53 private static final int MAX_SYSTEM_HOOKS = 10; |
|
54 private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS]; |
52 |
55 |
53 /* The preceding static fields are protected by this lock */ |
56 /* The preceding static fields are protected by this lock */ |
54 private static class Lock { }; |
57 private static class Lock { }; |
55 private static Object lock = new Lock(); |
58 private static Object lock = new Lock(); |
56 |
59 |
66 |
69 |
67 |
70 |
68 /* Add a new shutdown hook. Checks the shutdown state and the hook itself, |
71 /* Add a new shutdown hook. Checks the shutdown state and the hook itself, |
69 * but does not do any security checks. |
72 * but does not do any security checks. |
70 */ |
73 */ |
71 static void add(Runnable hook) { |
74 static void add(int slot, Runnable hook) { |
72 synchronized (lock) { |
75 synchronized (lock) { |
73 if (state > RUNNING) |
76 if (state > RUNNING) |
74 throw new IllegalStateException("Shutdown in progress"); |
77 throw new IllegalStateException("Shutdown in progress"); |
75 |
78 |
76 hooks.add(hook); |
79 if (hooks[slot] != null) |
77 } |
80 throw new InternalError("Shutdown hook at slot " + slot + " already registered"); |
78 } |
81 |
79 |
82 hooks[slot] = hook; |
80 |
83 } |
81 /* Remove a previously-registered hook. Like the add method, this method |
84 } |
82 * does not do any security checks. |
|
83 */ |
|
84 static boolean remove(Runnable hook) { |
|
85 synchronized (lock) { |
|
86 if (state > RUNNING) |
|
87 throw new IllegalStateException("Shutdown in progress"); |
|
88 if (hook == null) throw new NullPointerException(); |
|
89 if (hooks == null) { |
|
90 return false; |
|
91 } else { |
|
92 return hooks.remove(hook); |
|
93 } |
|
94 } |
|
95 } |
|
96 |
|
97 |
85 |
98 /* Run all registered shutdown hooks |
86 /* Run all registered shutdown hooks |
99 */ |
87 */ |
100 private static void runHooks() { |
88 private static void runHooks() { |
101 /* We needn't bother acquiring the lock just to read the hooks field, |
89 /* We needn't bother acquiring the lock just to read the hooks field, |
102 * since the hooks can't be modified once shutdown is in progress |
90 * since the hooks can't be modified once shutdown is in progress |
103 */ |
91 */ |
104 for (Runnable hook : hooks) { |
92 for (Runnable hook : hooks) { |
105 try { |
93 try { |
106 hook.run(); |
94 if (hook != null) hook.run(); |
107 } catch(Throwable t) { |
95 } catch(Throwable t) { |
108 if (t instanceof ThreadDeath) { |
96 if (t instanceof ThreadDeath) { |
109 ThreadDeath td = (ThreadDeath)t; |
97 ThreadDeath td = (ThreadDeath)t; |
110 throw td; |
98 throw td; |
111 } |
99 } |