142 |
// Using defaultProperties directly avoids a security check, as well |
// Using defaultProperties directly avoids a security check, as well |
143 |
// as bootstrap issues (since System is not initialized yet). |
// as bootstrap issues (since System is not initialized yet). |
144 |
String path = defaultProperties.getProperty("java.library.path", "."); |
String path = defaultProperties.getProperty("java.library.path", "."); |
145 |
String separator = defaultProperties.getProperty("path.separator", "/"); |
String pathSep = defaultProperties.getProperty("path.separator", ":"); |
146 |
StringTokenizer t = new StringTokenizer(path, separator); |
String fileSep = defaultProperties.getProperty("file.separator", "/"); |
147 |
|
StringTokenizer t = new StringTokenizer(path, pathSep); |
148 |
libpath = new String[t.countTokens()]; |
libpath = new String[t.countTokens()]; |
149 |
for (int i = 0; i < libpath.length; i++) |
for (int i = 0; i < libpath.length; i++) |
150 |
libpath[i] = t.nextToken(); |
{ |
151 |
|
String prefix = t.nextToken(); |
152 |
|
if (! prefix.endsWith(fileSep)) |
153 |
|
prefix += fileSep; |
154 |
|
libpath[i] = prefix; |
155 |
|
} |
156 |
} |
} |
157 |
|
|
158 |
/** |
/** |
201 |
{ |
{ |
202 |
first = true; |
first = true; |
203 |
exitSequence = Thread.currentThread(); |
exitSequence = Thread.currentThread(); |
204 |
Iterator i = shutdownHooks.iterator(); |
if (shutdownHooks != null) |
205 |
while (i.hasNext()) // Start all shutdown hooks. |
{ |
206 |
try |
Iterator i = shutdownHooks.iterator(); |
207 |
{ |
while (i.hasNext()) // Start all shutdown hooks. |
208 |
((Thread) i.next()).start(); |
try |
209 |
} |
{ |
210 |
catch (IllegalThreadStateException e) |
((Thread) i.next()).start(); |
211 |
{ |
} |
212 |
i.remove(); |
catch (IllegalThreadStateException e) |
213 |
} |
{ |
214 |
|
i.remove(); |
215 |
|
} |
216 |
|
} |
217 |
} |
} |
218 |
} |
} |
219 |
if (first) |
if (first) |
220 |
{ |
{ |
221 |
// Check progress of all shutdown hooks. As a hook completes, remove |
if (shutdownHooks != null) |
|
// it from the set. If a hook calls exit, it removes itself from the |
|
|
// set, then waits indefinitely on the exitSequence thread. Once |
|
|
// the set is empty, set it to null to signal all finalizer threads |
|
|
// that halt may be called. |
|
|
while (! shutdownHooks.isEmpty()) |
|
222 |
{ |
{ |
223 |
Thread[] hooks; |
// Check progress of all shutdown hooks. As a hook completes, |
224 |
synchronized (libpath) |
// remove it from the set. If a hook calls exit, it removes |
225 |
|
// itself from the set, then waits indefinitely on the |
226 |
|
// exitSequence thread. Once the set is empty, set it to null to |
227 |
|
// signal all finalizer threads that halt may be called. |
228 |
|
while (! shutdownHooks.isEmpty()) |
229 |
{ |
{ |
230 |
hooks = new Thread[shutdownHooks.size()]; |
Thread[] hooks; |
|
shutdownHooks.toArray(hooks); |
|
|
} |
|
|
for (int i = hooks.length; --i >= 0; ) |
|
|
if (! hooks[i].isAlive()) |
|
231 |
synchronized (libpath) |
synchronized (libpath) |
232 |
{ |
{ |
233 |
shutdownHooks.remove(hooks[i]); |
hooks = new Thread[shutdownHooks.size()]; |
234 |
|
shutdownHooks.toArray(hooks); |
235 |
|
} |
236 |
|
for (int i = hooks.length; --i >= 0; ) |
237 |
|
if (! hooks[i].isAlive()) |
238 |
|
synchronized (libpath) |
239 |
|
{ |
240 |
|
shutdownHooks.remove(hooks[i]); |
241 |
|
} |
242 |
|
try |
243 |
|
{ |
244 |
|
exitSequence.sleep(1); // Give other threads a chance. |
245 |
|
} |
246 |
|
catch (InterruptedException e) |
247 |
|
{ |
248 |
|
// Ignore, the next loop just starts sooner. |
249 |
} |
} |
|
try |
|
|
{ |
|
|
exitSequence.sleep(1); // Give other threads a chance. |
|
250 |
} |
} |
251 |
catch (InterruptedException e) |
synchronized (libpath) |
252 |
{ |
{ |
253 |
// Ignore, the next loop just starts sooner. |
shutdownHooks = null; |
254 |
} |
} |
255 |
} |
} |
|
synchronized (libpath) |
|
|
{ |
|
|
shutdownHooks = null; |
|
|
} |
|
256 |
// XXX Right now, it is the VM that knows whether runFinalizersOnExit |
// XXX Right now, it is the VM that knows whether runFinalizersOnExit |
257 |
// is true; so the VM must look at exitSequence to decide whether |
// is true; so the VM must look at exitSequence to decide whether |
258 |
// this should be run on every object. |
// this should be run on every object. |