1.1 --- a/src/share/classes/java/io/Console.java Mon May 04 18:28:26 2009 -0700
1.2 +++ b/src/share/classes/java/io/Console.java Mon May 04 22:16:02 2009 -0700
1.3 @@ -503,20 +503,25 @@
1.4
1.5 // Set up JavaIOAccess in SharedSecrets
1.6 static {
1.7 -
1.8 - // Add a shutdown hook to restore console's echo state should
1.9 - // it be necessary.
1.10 - sun.misc.SharedSecrets.getJavaLangAccess()
1.11 - .registerShutdownHook(0 /* shutdown hook invocation order */,
1.12 - new Runnable() {
1.13 - public void run() {
1.14 - try {
1.15 - if (echoOff) {
1.16 - echo(true);
1.17 - }
1.18 - } catch (IOException x) { }
1.19 - }
1.20 - });
1.21 + try {
1.22 + // Add a shutdown hook to restore console's echo state should
1.23 + // it be necessary.
1.24 + sun.misc.SharedSecrets.getJavaLangAccess()
1.25 + .registerShutdownHook(0 /* shutdown hook invocation order */,
1.26 + false /* only register if shutdown is not in progress */,
1.27 + new Runnable() {
1.28 + public void run() {
1.29 + try {
1.30 + if (echoOff) {
1.31 + echo(true);
1.32 + }
1.33 + } catch (IOException x) { }
1.34 + }
1.35 + });
1.36 + } catch (IllegalStateException e) {
1.37 + // shutdown is already in progress and console is first used
1.38 + // by a shutdown hook
1.39 + }
1.40
1.41 sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {
1.42 public Console console() {
2.1 --- a/src/share/classes/java/io/DeleteOnExitHook.java Mon May 04 18:28:26 2009 -0700
2.2 +++ b/src/share/classes/java/io/DeleteOnExitHook.java Mon May 04 22:16:02 2009 -0700
2.3 @@ -34,23 +34,31 @@
2.4 */
2.5
2.6 class DeleteOnExitHook {
2.7 + private static LinkedHashSet<String> files = new LinkedHashSet<String>();
2.8 static {
2.9 - sun.misc.SharedSecrets.getJavaLangAccess()
2.10 - .registerShutdownHook(2 /* Shutdown hook invocation order */,
2.11 - new Runnable() {
2.12 - public void run() {
2.13 - runHooks();
2.14 - }
2.15 - });
2.16 + // DeleteOnExitHook must be the last shutdown hook to be invoked.
2.17 + // Application shutdown hooks may add the first file to the
2.18 + // delete on exit list and cause the DeleteOnExitHook to be
2.19 + // registered during shutdown in progress. So set the
2.20 + // registerShutdownInProgress parameter to true.
2.21 + sun.misc.SharedSecrets.getJavaLangAccess()
2.22 + .registerShutdownHook(2 /* Shutdown hook invocation order */,
2.23 + true /* register even if shutdown in progress */,
2.24 + new Runnable() {
2.25 + public void run() {
2.26 + runHooks();
2.27 + }
2.28 + }
2.29 + );
2.30 }
2.31
2.32 - private static LinkedHashSet<String> files = new LinkedHashSet<String>();
2.33 -
2.34 private DeleteOnExitHook() {}
2.35
2.36 static synchronized void add(String file) {
2.37 - if(files == null)
2.38 + if(files == null) {
2.39 + // DeleteOnExitHook is running. Too late to add a file
2.40 throw new IllegalStateException("Shutdown in progress");
2.41 + }
2.42
2.43 files.add(file);
2.44 }
3.1 --- a/src/share/classes/java/lang/ApplicationShutdownHooks.java Mon May 04 18:28:26 2009 -0700
3.2 +++ b/src/share/classes/java/lang/ApplicationShutdownHooks.java Mon May 04 22:16:02 2009 -0700
3.3 @@ -35,17 +35,26 @@
3.4 */
3.5
3.6 class ApplicationShutdownHooks {
3.7 + /* The set of registered hooks */
3.8 + private static IdentityHashMap<Thread, Thread> hooks;
3.9 static {
3.10 - Shutdown.add(1 /* shutdown hook invocation order */,
3.11 - new Runnable() {
3.12 - public void run() {
3.13 - runHooks();
3.14 + try {
3.15 + Shutdown.add(1 /* shutdown hook invocation order */,
3.16 + false /* not registered if shutdown in progress */,
3.17 + new Runnable() {
3.18 + public void run() {
3.19 + runHooks();
3.20 + }
3.21 }
3.22 - });
3.23 + );
3.24 + hooks = new IdentityHashMap<Thread, Thread>();
3.25 + } catch (IllegalStateException e) {
3.26 + // application shutdown hooks cannot be added if
3.27 + // shutdown is in progress.
3.28 + hooks = null;
3.29 + }
3.30 }
3.31
3.32 - /* The set of registered hooks */
3.33 - private static IdentityHashMap<Thread, Thread> hooks = new IdentityHashMap<Thread, Thread>();
3.34
3.35 private ApplicationShutdownHooks() {}
3.36
4.1 --- a/src/share/classes/java/lang/Shutdown.java Mon May 04 18:28:26 2009 -0700
4.2 +++ b/src/share/classes/java/lang/Shutdown.java Mon May 04 22:16:02 2009 -0700
4.3 @@ -53,6 +53,9 @@
4.4 private static final int MAX_SYSTEM_HOOKS = 10;
4.5 private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];
4.6
4.7 + // the index of the currently running shutdown hook to the hooks array
4.8 + private static int currentRunningHook = 0;
4.9 +
4.10 /* The preceding static fields are protected by this lock */
4.11 private static class Lock { };
4.12 private static Object lock = new Lock();
4.13 @@ -68,17 +71,39 @@
4.14 }
4.15
4.16
4.17 - /* Add a new shutdown hook. Checks the shutdown state and the hook itself,
4.18 + /**
4.19 + * Add a new shutdown hook. Checks the shutdown state and the hook itself,
4.20 * but does not do any security checks.
4.21 + *
4.22 + * The registerShutdownInProgress parameter should be false except
4.23 + * registering the DeleteOnExitHook since the first file may
4.24 + * be added to the delete on exit list by the application shutdown
4.25 + * hooks.
4.26 + *
4.27 + * @params slot the slot in the shutdown hook array, whose element
4.28 + * will be invoked in order during shutdown
4.29 + * @params registerShutdownInProgress true to allow the hook
4.30 + * to be registered even if the shutdown is in progress.
4.31 + * @params hook the hook to be registered
4.32 + *
4.33 + * @throw IllegalStateException
4.34 + * if registerShutdownInProgress is false and shutdown is in progress; or
4.35 + * if registerShutdownInProgress is true and the shutdown process
4.36 + * already passes the given slot
4.37 */
4.38 - static void add(int slot, Runnable hook) {
4.39 + static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
4.40 synchronized (lock) {
4.41 - if (state > RUNNING)
4.42 - throw new IllegalStateException("Shutdown in progress");
4.43 -
4.44 if (hooks[slot] != null)
4.45 throw new InternalError("Shutdown hook at slot " + slot + " already registered");
4.46
4.47 + if (!registerShutdownInProgress) {
4.48 + if (state > RUNNING)
4.49 + throw new IllegalStateException("Shutdown in progress");
4.50 + } else {
4.51 + if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))
4.52 + throw new IllegalStateException("Shutdown in progress");
4.53 + }
4.54 +
4.55 hooks[slot] = hook;
4.56 }
4.57 }
4.58 @@ -86,11 +111,15 @@
4.59 /* Run all registered shutdown hooks
4.60 */
4.61 private static void runHooks() {
4.62 - /* We needn't bother acquiring the lock just to read the hooks field,
4.63 - * since the hooks can't be modified once shutdown is in progress
4.64 - */
4.65 - for (Runnable hook : hooks) {
4.66 + for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
4.67 try {
4.68 + Runnable hook;
4.69 + synchronized (lock) {
4.70 + // acquire the lock to make sure the hook registered during
4.71 + // shutdown is visible here.
4.72 + currentRunningHook = i;
4.73 + hook = hooks[i];
4.74 + }
4.75 if (hook != null) hook.run();
4.76 } catch(Throwable t) {
4.77 if (t instanceof ThreadDeath) {
5.1 --- a/src/share/classes/java/lang/System.java Mon May 04 18:28:26 2009 -0700
5.2 +++ b/src/share/classes/java/lang/System.java Mon May 04 22:16:02 2009 -0700
5.3 @@ -1171,8 +1171,8 @@
5.4 public void blockedOn(Thread t, Interruptible b) {
5.5 t.blockedOn(b);
5.6 }
5.7 - public void registerShutdownHook(int slot, Runnable r) {
5.8 - Shutdown.add(slot, r);
5.9 + public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
5.10 + Shutdown.add(slot, registerShutdownInProgress, hook);
5.11 }
5.12 });
5.13 }
6.1 --- a/src/share/classes/java/util/zip/ZipFile.java Mon May 04 18:28:26 2009 -0700
6.2 +++ b/src/share/classes/java/util/zip/ZipFile.java Mon May 04 22:16:02 2009 -0700
6.3 @@ -154,7 +154,7 @@
6.4 * @param file the ZIP file to be opened for reading
6.5 * @param mode the mode in which the file is to be opened
6.6 * @param charset
6.7 - * the {@link java.nio.charset.Charset {@code charset}} to
6.8 + * the {@linkplain java.nio.charset.Charset charset} to
6.9 * be used to decode the ZIP entry name and comment that are not
6.10 * encoded by using UTF-8 encoding (indicated by entry's general
6.11 * purpose flag).
6.12 @@ -206,7 +206,7 @@
6.13 *
6.14 * @param name the name of the zip file
6.15 * @param charset
6.16 - * the {@link java.nio.charset.Charset {@code charset}} to
6.17 + * the {@linkplain java.nio.charset.Charset charset} to
6.18 * be used to decode the ZIP entry name and comment that are not
6.19 * encoded by using UTF-8 encoding (indicated by entry's general
6.20 * purpose flag).
6.21 @@ -230,7 +230,7 @@
6.22 * Opens a ZIP file for reading given the specified File object.
6.23 * @param file the ZIP file to be opened for reading
6.24 * @param charset
6.25 - * The {@link java.nio.charset.Charset {@code charset}} to be
6.26 + * The {@linkplain java.nio.charset.Charset charset} to be
6.27 * used to decode the ZIP entry name and comment (ignored if
6.28 * the <a href="package-summary.html#lang_encoding"> language
6.29 * encoding bit</a> of the ZIP entry's general purpose bit
7.1 --- a/src/share/classes/java/util/zip/ZipInputStream.java Mon May 04 18:28:26 2009 -0700
7.2 +++ b/src/share/classes/java/util/zip/ZipInputStream.java Mon May 04 22:16:02 2009 -0700
7.3 @@ -84,7 +84,7 @@
7.4 * @param in the actual input stream
7.5 *
7.6 * @param charset
7.7 - * The {@link java.nio.charset.Charset {@code charset}} to be
7.8 + * The {@linkplain java.nio.charset.Charset charset} to be
7.9 * used to decode the ZIP entry name (ignored if the
7.10 * <a href="package-summary.html#lang_encoding"> language
7.11 * encoding bit</a> of the ZIP entry's general purpose bit
8.1 --- a/src/share/classes/java/util/zip/ZipOutputStream.java Mon May 04 18:28:26 2009 -0700
8.2 +++ b/src/share/classes/java/util/zip/ZipOutputStream.java Mon May 04 22:16:02 2009 -0700
8.3 @@ -108,7 +108,7 @@
8.4 *
8.5 * @param out the actual output stream
8.6 *
8.7 - * @param charset the {@link java.nio.charset.Charset </code>charset<code>}
8.8 + * @param charset the {@linkplain java.nio.charset.Charset charset}
8.9 * to be used to encode the entry names and comments
8.10 *
8.11 * @since 1.7
9.1 --- a/src/share/classes/sun/misc/JavaLangAccess.java Mon May 04 18:28:26 2009 -0700
9.2 +++ b/src/share/classes/sun/misc/JavaLangAccess.java Mon May 04 22:16:02 2009 -0700
9.3 @@ -55,6 +55,22 @@
9.4 /** Set thread's blocker field. */
9.5 void blockedOn(Thread t, Interruptible b);
9.6
9.7 - /** register shutdown hook */
9.8 - void registerShutdownHook(int slot, Runnable r);
9.9 + /**
9.10 + * Registers a shutdown hook.
9.11 + *
9.12 + * It is expected that this method with registerShutdownInProgress=true
9.13 + * is only used to register DeleteOnExitHook since the first file
9.14 + * may be added to the delete on exit list by the application shutdown
9.15 + * hooks.
9.16 + *
9.17 + * @params slot the slot in the shutdown hook array, whose element
9.18 + * will be invoked in order during shutdown
9.19 + * @params registerShutdownInProgress true to allow the hook
9.20 + * to be registered even if the shutdown is in progress.
9.21 + * @params hook the hook to be registered
9.22 + *
9.23 + * @throw IllegalStateException if shutdown is in progress and
9.24 + * the slot is not valid to register.
9.25 + */
9.26 + void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook);
9.27 }
10.1 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Mon May 04 18:28:26 2009 -0700
10.2 +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Mon May 04 22:16:02 2009 -0700
10.3 @@ -475,49 +475,40 @@
10.4 // get an OVERLAPPED structure (from the cache or allocate)
10.5 overlapped = ioCache.add(result);
10.6
10.7 - // synchronize on result to allow this thread handle the case
10.8 - // where the read completes immediately.
10.9 - synchronized (result) {
10.10 - int n = read0(handle, numBufs, readBufferArray, overlapped);
10.11 - if (n == IOStatus.UNAVAILABLE) {
10.12 - // I/O is pending
10.13 - pending = true;
10.14 - return;
10.15 + // initiate read
10.16 + int n = read0(handle, numBufs, readBufferArray, overlapped);
10.17 + if (n == IOStatus.UNAVAILABLE) {
10.18 + // I/O is pending
10.19 + pending = true;
10.20 + return;
10.21 + }
10.22 + if (n == IOStatus.EOF) {
10.23 + // input shutdown
10.24 + enableReading();
10.25 + if (scatteringRead) {
10.26 + result.setResult((V)Long.valueOf(-1L));
10.27 + } else {
10.28 + result.setResult((V)Integer.valueOf(-1));
10.29 }
10.30 - // read completed immediately:
10.31 - // 1. update buffer position
10.32 - // 2. reset read flag
10.33 - // 3. release waiters
10.34 - if (n == 0) {
10.35 - n = -1;
10.36 - } else {
10.37 - updateBuffers(n);
10.38 - }
10.39 - enableReading();
10.40 -
10.41 - if (scatteringRead) {
10.42 - result.setResult((V)Long.valueOf(n));
10.43 - } else {
10.44 - result.setResult((V)Integer.valueOf(n));
10.45 - }
10.46 + } else {
10.47 + throw new InternalError("Read completed immediately");
10.48 }
10.49 } catch (Throwable x) {
10.50 - // failed to initiate read:
10.51 - // 1. reset read flag
10.52 - // 2. free resources
10.53 - // 3. release waiters
10.54 + // failed to initiate read
10.55 + // reset read flag before releasing waiters
10.56 enableReading();
10.57 - if (overlapped != 0L)
10.58 - ioCache.remove(overlapped);
10.59 if (x instanceof ClosedChannelException)
10.60 x = new AsynchronousCloseException();
10.61 if (!(x instanceof IOException))
10.62 x = new IOException(x);
10.63 result.setFailure(x);
10.64 } finally {
10.65 - if (prepared && !pending) {
10.66 - // return direct buffer(s) to cache if substituted
10.67 - releaseBuffers();
10.68 + // release resources if I/O not pending
10.69 + if (!pending) {
10.70 + if (overlapped != 0L)
10.71 + ioCache.remove(overlapped);
10.72 + if (prepared)
10.73 + releaseBuffers();
10.74 }
10.75 end();
10.76 }
10.77 @@ -721,7 +712,6 @@
10.78 @Override
10.79 @SuppressWarnings("unchecked")
10.80 public void run() {
10.81 - int n = -1;
10.82 long overlapped = 0L;
10.83 boolean prepared = false;
10.84 boolean pending = false;
10.85 @@ -736,56 +726,34 @@
10.86
10.87 // get an OVERLAPPED structure (from the cache or allocate)
10.88 overlapped = ioCache.add(result);
10.89 -
10.90 - // synchronize on result to allow this thread handle the case
10.91 - // where the read completes immediately.
10.92 - synchronized (result) {
10.93 - n = write0(handle, numBufs, writeBufferArray, overlapped);
10.94 - if (n == IOStatus.UNAVAILABLE) {
10.95 - // I/O is pending
10.96 - pending = true;
10.97 - return;
10.98 - }
10.99 -
10.100 - enableWriting();
10.101 -
10.102 - if (n == IOStatus.EOF) {
10.103 - // special case for shutdown output
10.104 - shutdown = true;
10.105 - throw new ClosedChannelException();
10.106 - }
10.107 -
10.108 - // write completed immediately:
10.109 - // 1. enable writing
10.110 - // 2. update buffer position
10.111 - // 3. release waiters
10.112 - updateBuffers(n);
10.113 -
10.114 - // result is a Long or Integer
10.115 - if (gatheringWrite) {
10.116 - result.setResult((V)Long.valueOf(n));
10.117 - } else {
10.118 - result.setResult((V)Integer.valueOf(n));
10.119 - }
10.120 + int n = write0(handle, numBufs, writeBufferArray, overlapped);
10.121 + if (n == IOStatus.UNAVAILABLE) {
10.122 + // I/O is pending
10.123 + pending = true;
10.124 + return;
10.125 }
10.126 + if (n == IOStatus.EOF) {
10.127 + // special case for shutdown output
10.128 + shutdown = true;
10.129 + throw new ClosedChannelException();
10.130 + }
10.131 + // write completed immediately
10.132 + throw new InternalError("Write completed immediately");
10.133 } catch (Throwable x) {
10.134 + // write failed. Enable writing before releasing waiters.
10.135 enableWriting();
10.136 -
10.137 - // failed to initiate read:
10.138 if (!shutdown && (x instanceof ClosedChannelException))
10.139 x = new AsynchronousCloseException();
10.140 if (!(x instanceof IOException))
10.141 x = new IOException(x);
10.142 result.setFailure(x);
10.143 -
10.144 - // release resources
10.145 - if (overlapped != 0L)
10.146 - ioCache.remove(overlapped);
10.147 -
10.148 } finally {
10.149 - if (prepared && !pending) {
10.150 - // return direct buffer(s) to cache if substituted
10.151 - releaseBuffers();
10.152 + // release resources if I/O not pending
10.153 + if (!pending) {
10.154 + if (overlapped != 0L)
10.155 + ioCache.remove(overlapped);
10.156 + if (prepared)
10.157 + releaseBuffers();
10.158 }
10.159 end();
10.160 }
11.1 --- a/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c Mon May 04 18:28:26 2009 -0700
11.2 +++ b/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c Mon May 04 22:16:02 2009 -0700
11.3 @@ -157,14 +157,13 @@
11.4 WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
11.5 OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
11.6 BOOL res;
11.7 - DWORD nread = 0;
11.8 DWORD flags = 0;
11.9
11.10 ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
11.11 res = WSARecv(s,
11.12 lpWsaBuf,
11.13 (DWORD)count,
11.14 - &nread,
11.15 + NULL,
11.16 &flags,
11.17 lpOverlapped,
11.18 NULL);
11.19 @@ -175,17 +174,12 @@
11.20 return IOS_UNAVAILABLE;
11.21 }
11.22 if (error == WSAESHUTDOWN) {
11.23 - return 0; // input shutdown
11.24 + return IOS_EOF; // input shutdown
11.25 }
11.26 JNU_ThrowIOExceptionWithLastError(env, "WSARecv failed");
11.27 return IOS_THROWN;
11.28 }
11.29 - if (nread == 0) {
11.30 - // Handle graceful close or bytes not yet available cases
11.31 - // via completion port notification.
11.32 - return IOS_UNAVAILABLE;
11.33 - }
11.34 - return (jint)nread;
11.35 + return IOS_UNAVAILABLE;
11.36 }
11.37
11.38 JNIEXPORT jint JNICALL
11.39 @@ -196,13 +190,12 @@
11.40 WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
11.41 OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
11.42 BOOL res;
11.43 - DWORD nwritten;
11.44
11.45 ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
11.46 res = WSASend(s,
11.47 lpWsaBuf,
11.48 (DWORD)count,
11.49 - &nwritten,
11.50 + NULL,
11.51 0,
11.52 lpOverlapped,
11.53 NULL);
11.54 @@ -218,5 +211,5 @@
11.55 JNU_ThrowIOExceptionWithLastError(env, "WSASend failed");
11.56 return IOS_THROWN;
11.57 }
11.58 - return (jint)nwritten;
11.59 + return IOS_UNAVAILABLE;
11.60 }
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/test/java/lang/Runtime/shutdown/ShutdownHooks.java Mon May 04 22:16:02 2009 -0700
12.3 @@ -0,0 +1,69 @@
12.4 +/*
12.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12.7 + *
12.8 + * This code is free software; you can redistribute it and/or modify it
12.9 + * under the terms of the GNU General Public License version 2 only, as
12.10 + * published by the Free Software Foundation.
12.11 + *
12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12.15 + * version 2 for more details (a copy is included in the LICENSE file that
12.16 + * accompanied this code).
12.17 + *
12.18 + * You should have received a copy of the GNU General Public License version
12.19 + * 2 along with this work; if not, write to the Free Software Foundation,
12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12.21 + *
12.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
12.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
12.24 + * have any questions.
12.25 + */
12.26 +
12.27 +/*
12.28 + * @bug 6829503
12.29 + * @summary 1) Test Console and DeleteOnExitHook can be initialized
12.30 + * while shutdown is in progress
12.31 + * 2) Test if files that are added by the application shutdown
12.32 + * hook are deleted on exit during shutdown
12.33 + */
12.34 +import java.io.*;
12.35 +public class ShutdownHooks {
12.36 + private static File file;
12.37 + public static void main(String[] args) throws Exception {
12.38 + if (args.length != 2) {
12.39 + throw new IllegalArgumentException("Usage: ShutdownHooks <dir> <filename>");
12.40 + }
12.41 +
12.42 + // Add a shutdown hook
12.43 + Runtime.getRuntime().addShutdownHook(new Cleaner());
12.44 +
12.45 + File dir = new File(args[0]);
12.46 + file = new File(dir, args[1]);
12.47 + // write to file
12.48 + System.out.println("writing to "+ file);
12.49 + PrintWriter pw = new PrintWriter(file);
12.50 + pw.println("Shutdown begins");
12.51 + pw.close();
12.52 + }
12.53 +
12.54 + public static class Cleaner extends Thread {
12.55 + public void run() {
12.56 + // register the Console's shutdown hook while the application
12.57 + // shutdown hook is running
12.58 + Console cons = System.console();
12.59 + // register the DeleteOnExitHook while the application
12.60 + // shutdown hook is running
12.61 + file.deleteOnExit();
12.62 + try {
12.63 + PrintWriter pw = new PrintWriter(file);
12.64 + pw.println("file is being deleted");
12.65 + pw.close();
12.66 + } catch (FileNotFoundException e) {
12.67 + throw new RuntimeException(e);
12.68 + }
12.69 + }
12.70 + }
12.71 +
12.72 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/test/java/lang/Runtime/shutdown/ShutdownHooks.sh Mon May 04 22:16:02 2009 -0700
13.3 @@ -0,0 +1,57 @@
13.4 +#!/bin/sh
13.5 +
13.6 +#
13.7 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
13.8 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.9 +#
13.10 +# This code is free software; you can redistribute it and/or modify it
13.11 +# under the terms of the GNU General Public License version 2 only, as
13.12 +# published by the Free Software Foundation.
13.13 +#
13.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
13.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 +# version 2 for more details (a copy is included in the LICENSE file that
13.18 +# accompanied this code).
13.19 +#
13.20 +# You should have received a copy of the GNU General Public License version
13.21 +# 2 along with this work; if not, write to the Free Software Foundation,
13.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 +#
13.24 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
13.25 +# CA 95054 USA or visit www.sun.com if you need additional information or
13.26 +# have any questions.
13.27 +#
13.28 +
13.29 +
13.30 +# @test
13.31 +# @bug 6829503
13.32 +# @summary 1) Test Console and DeleteOnExitHook can be initialized
13.33 +# while shutdown is in progress
13.34 +# 2) Test if files that are added by the application shutdown
13.35 +# hook are deleted on exit during shutdown
13.36 +#
13.37 +# @build ShutdownHooks
13.38 +# @run shell ShutdownHooks.sh
13.39 +
13.40 +if [ "${TESTJAVA}" = "" ]
13.41 +then
13.42 + echo "TESTJAVA not set. Test cannot execute. Failed."
13.43 + exit 1
13.44 +fi
13.45 +
13.46 +FILENAME=fileToBeDeleted
13.47 +rm -f ${TESTCLASSES}/${FILENAME}
13.48 +
13.49 +# create the file to be deleted on exit
13.50 +echo "testing shutdown" > ${TESTCLASSES}/${FILENAME}
13.51 +
13.52 +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} ShutdownHooks ${TESTCLASSES} $FILENAME
13.53 +if [ $? != 0 ] ; then
13.54 + echo "Test Failed"; exit 1
13.55 +fi
13.56 +
13.57 +if [ -f ${TESTCLASSES}/${FILENAME} ]; then
13.58 + echo "Test Failed: ${TESTCLASSES}/${FILENAME} not deleted"; exit 2
13.59 +fi
13.60 +echo "ShutdownHooks test passed.";
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Mon May 04 22:16:02 2009 -0700
14.3 @@ -0,0 +1,183 @@
14.4 +/*
14.5 + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14.7 + *
14.8 + * This code is free software; you can redistribute it and/or modify it
14.9 + * under the terms of the GNU General Public License version 2 only, as
14.10 + * published by the Free Software Foundation.
14.11 + *
14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14.15 + * version 2 for more details (a copy is included in the LICENSE file that
14.16 + * accompanied this code).
14.17 + *
14.18 + * You should have received a copy of the GNU General Public License version
14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14.21 + *
14.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
14.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
14.24 + * have any questions.
14.25 + */
14.26 +
14.27 +/* @test
14.28 + * @bug 6834246
14.29 + * @summary Stress test connections through the loopback interface
14.30 + */
14.31 +
14.32 +import java.nio.ByteBuffer;
14.33 +import java.net.*;
14.34 +import java.nio.channels.*;
14.35 +import java.util.Random;
14.36 +import java.io.IOException;
14.37 +
14.38 +public class StressLoopback {
14.39 + static final Random rand = new Random();
14.40 +
14.41 + public static void main(String[] args) throws Exception {
14.42 + // setup listener
14.43 + AsynchronousServerSocketChannel listener =
14.44 + AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
14.45 + int port =((InetSocketAddress)(listener.getLocalAddress())).getPort();
14.46 + InetAddress lh = InetAddress.getLocalHost();
14.47 + SocketAddress remote = new InetSocketAddress(lh, port);
14.48 +
14.49 + // create sources and sinks
14.50 + int count = 2 + rand.nextInt(9);
14.51 + Source[] source = new Source[count];
14.52 + Sink[] sink = new Sink[count];
14.53 + for (int i=0; i<count; i++) {
14.54 + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
14.55 + ch.connect(remote).get();
14.56 + source[i] = new Source(ch);
14.57 + sink[i] = new Sink(listener.accept().get());
14.58 + }
14.59 +
14.60 + // start the sinks and sources
14.61 + for (int i=0; i<count; i++) {
14.62 + sink[i].start();
14.63 + source[i].start();
14.64 + }
14.65 +
14.66 + // let the test run for a while
14.67 + Thread.sleep(20*1000);
14.68 +
14.69 + // wait until everyone is done
14.70 + boolean failed = false;
14.71 + long total = 0L;
14.72 + for (int i=0; i<count; i++) {
14.73 + long nwrote = source[i].finish();
14.74 + long nread = sink[i].finish();
14.75 + if (nread != nwrote)
14.76 + failed = true;
14.77 + System.out.format("%d -> %d (%s)\n",
14.78 + nwrote, nread, (failed) ? "FAIL" : "PASS");
14.79 + total += nwrote;
14.80 + }
14.81 + if (failed)
14.82 + throw new RuntimeException("Test failed - see log for details");
14.83 + System.out.format("Total sent %d MB\n", total / (1024L * 1024L));
14.84 + }
14.85 +
14.86 + /**
14.87 + * Writes bytes to a channel until "done". When done the channel is closed.
14.88 + */
14.89 + static class Source {
14.90 + private final AsynchronousByteChannel channel;
14.91 + private final ByteBuffer sentBuffer;
14.92 + private volatile long bytesSent;
14.93 + private volatile boolean finished;
14.94 +
14.95 + Source(AsynchronousByteChannel channel) {
14.96 + this.channel = channel;
14.97 + int size = 1024 + rand.nextInt(10000);
14.98 + this.sentBuffer = (rand.nextBoolean()) ?
14.99 + ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size);
14.100 + }
14.101 +
14.102 + void start() {
14.103 + sentBuffer.position(0);
14.104 + sentBuffer.limit(sentBuffer.capacity());
14.105 + channel.write(sentBuffer, null, new CompletionHandler<Integer,Void> () {
14.106 + public void completed(Integer nwrote, Void att) {
14.107 + bytesSent += nwrote;
14.108 + if (finished) {
14.109 + closeUnchecked(channel);
14.110 + } else {
14.111 + sentBuffer.position(0);
14.112 + sentBuffer.limit(sentBuffer.capacity());
14.113 + channel.write(sentBuffer, null, this);
14.114 + }
14.115 + }
14.116 + public void failed(Throwable exc, Void att) {
14.117 + exc.printStackTrace();
14.118 + closeUnchecked(channel);
14.119 + }
14.120 + public void cancelled(Void att) {
14.121 + }
14.122 + });
14.123 + }
14.124 +
14.125 + long finish() {
14.126 + finished = true;
14.127 + waitUntilClosed(channel);
14.128 + return bytesSent;
14.129 + }
14.130 + }
14.131 +
14.132 + /**
14.133 + * Read bytes from a channel until EOF is received.
14.134 + */
14.135 + static class Sink {
14.136 + private final AsynchronousByteChannel channel;
14.137 + private final ByteBuffer readBuffer;
14.138 + private volatile long bytesRead;
14.139 +
14.140 + Sink(AsynchronousByteChannel channel) {
14.141 + this.channel = channel;
14.142 + int size = 1024 + rand.nextInt(10000);
14.143 + this.readBuffer = (rand.nextBoolean()) ?
14.144 + ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size);
14.145 + }
14.146 +
14.147 + void start() {
14.148 + channel.read(readBuffer, null, new CompletionHandler<Integer,Void> () {
14.149 + public void completed(Integer nread, Void att) {
14.150 + if (nread < 0) {
14.151 + closeUnchecked(channel);
14.152 + } else {
14.153 + bytesRead += nread;
14.154 + readBuffer.clear();
14.155 + channel.read(readBuffer, null, this);
14.156 + }
14.157 + }
14.158 + public void failed(Throwable exc, Void att) {
14.159 + exc.printStackTrace();
14.160 + closeUnchecked(channel);
14.161 + }
14.162 + public void cancelled(Void att) {
14.163 + }
14.164 + });
14.165 + }
14.166 +
14.167 + long finish() {
14.168 + waitUntilClosed(channel);
14.169 + return bytesRead;
14.170 + }
14.171 + }
14.172 +
14.173 + static void waitUntilClosed(Channel c) {
14.174 + while (c.isOpen()) {
14.175 + try {
14.176 + Thread.sleep(100);
14.177 + } catch (InterruptedException ignore) { }
14.178 + }
14.179 + }
14.180 +
14.181 + static void closeUnchecked(Channel c) {
14.182 + try {
14.183 + c.close();
14.184 + } catch (IOException ignore) { }
14.185 + }
14.186 +}