changeset 1590:b3f3240135f0 jdk7-b71

Merge
author xdono
date Tue, 01 Sep 2009 13:03:09 -0700
parents e0b26d347302 b71a03c75515
children ce3fde68c495
files src/share/classes/sun/nio/ch/AbstractFuture.java
diffstat 108 files changed, 5235 insertions(+), 1901 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Aug 24 17:26:09 2009 -0700
+++ b/.hgignore	Tue Sep 01 13:03:09 2009 -0700
@@ -1,3 +1,6 @@
 ^build/
 ^dist/
 ^nbproject/private/
+^make/netbeans/.*/nbproject/private/
+^make/netbeans/.*/build/
+^make/netbeans/.*/dist/
--- a/make/java/nio/FILES_java.gmk	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/java/nio/FILES_java.gmk	Tue Sep 01 13:03:09 2009 -0700
@@ -160,7 +160,6 @@
 	\
 	sun/nio/ByteBuffered.java \
 	\
-	sun/nio/ch/AbstractFuture.java \
         sun/nio/ch/AbstractPollArrayWrapper.java \
 	sun/nio/ch/AllocatedNativeObject.java \
 	sun/nio/ch/AsynchronousChannelGroupImpl.java \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/build.xml	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="jdwpgen" default="default" basedir=".">
+    <description>Builds, tests, and runs the project jdwpgen.</description>
+    <import file="nbproject/build-impl.xml"/>
+    <!--
+
+    There exist several targets which are by default empty and which can be 
+    used for execution of your tasks. These targets are usually executed 
+    before and after some main targets. They are: 
+
+      -pre-init:                 called before initialization of project properties
+      -post-init:                called after initialization of project properties
+      -pre-compile:              called before javac compilation
+      -post-compile:             called after javac compilation
+      -pre-compile-single:       called before javac compilation of single file
+      -post-compile-single:      called after javac compilation of single file
+      -pre-compile-test:         called before javac compilation of JUnit tests
+      -post-compile-test:        called after javac compilation of JUnit tests
+      -pre-compile-test-single:  called before javac compilation of single JUnit test
+      -post-compile-test-single: called after javac compilation of single JUunit test
+      -pre-jar:                  called before JAR building
+      -post-jar:                 called after JAR building
+      -post-clean:               called after cleaning build products
+
+    (Targets beginning with '-' are not intended to be called on their own.)
+
+    Example of inserting an obfuscator after compilation could look like this:
+
+        <target name="-post-compile">
+            <obfuscate>
+                <fileset dir="${build.classes.dir}"/>
+            </obfuscate>
+        </target>
+
+    For list of available properties check the imported 
+    nbproject/build-impl.xml file. 
+
+
+    Another way to customize the build is by overriding existing main targets.
+    The targets of interest are: 
+
+      -init-macrodef-javac:     defines macro for javac compilation
+      -init-macrodef-junit:     defines macro for junit execution
+      -init-macrodef-debug:     defines macro for class debugging
+      -init-macrodef-java:      defines macro for class execution
+      -do-jar-with-manifest:    JAR building (if you are using a manifest)
+      -do-jar-without-manifest: JAR building (if you are not using a manifest)
+      run:                      execution of project 
+      -javadoc-build:           Javadoc generation
+      test-report:              JUnit report generation
+
+    An example of overriding the target for project execution could look like this:
+
+        <target name="run" depends="jdwpgen-impl.jar">
+            <exec dir="bin" executable="launcher.exe">
+                <arg file="${dist.jar}"/>
+            </exec>
+        </target>
+
+    Notice that the overridden target depends on the jar target and not only on 
+    the compile target as the regular run target does. Again, for a list of available 
+    properties which you can use, check the target you are overriding in the
+    nbproject/build-impl.xml file. 
+
+    -->
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/build-impl.xml	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,642 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+  - initialization
+  - compilation
+  - jar
+  - execution
+  - debugging
+  - javadoc
+  - junit compilation
+  - junit execution
+  - junit debugging
+  - applet
+  - cleanup
+
+        -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="jdwpgen-impl">
+    <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+    <!-- 
+                ======================
+                INITIALIZATION SECTION 
+                ======================
+            -->
+    <target name="-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-pre-init" name="-init-private">
+        <property file="nbproject/private/config.properties"/>
+        <property file="nbproject/private/configs/${config}.properties"/>
+        <property file="nbproject/private/private.properties"/>
+    </target>
+    <target depends="-pre-init,-init-private" name="-init-user">
+        <property file="${user.properties.file}"/>
+        <!-- The two properties below are usually overridden -->
+        <!-- by the active platform. Just a fallback. -->
+        <property name="default.javac.source" value="1.4"/>
+        <property name="default.javac.target" value="1.4"/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+        <property file="nbproject/configs/${config}.properties"/>
+        <property file="nbproject/project.properties"/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+        <available file="${manifest.file}" property="manifest.available"/>
+        <condition property="manifest.available+main.class">
+            <and>
+                <isset property="manifest.available"/>
+                <isset property="main.class"/>
+                <not>
+                    <equals arg1="${main.class}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="manifest.available+main.class+mkdist.available">
+            <and>
+                <istrue value="${manifest.available+main.class}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+            </and>
+        </condition>
+        <condition property="have.tests">
+            <or>
+                <available file="${test.src.dir}"/>
+            </or>
+        </condition>
+        <condition property="have.sources">
+            <or>
+                <available file="${src.src.dir}"/>
+            </or>
+        </condition>
+        <condition property="netbeans.home+have.tests">
+            <and>
+                <isset property="netbeans.home"/>
+                <isset property="have.tests"/>
+            </and>
+        </condition>
+        <condition property="no.javadoc.preview">
+            <and>
+                <isset property="javadoc.preview"/>
+                <isfalse value="${javadoc.preview}"/>
+            </and>
+        </condition>
+        <property name="run.jvmargs" value=""/>
+        <property name="javac.compilerargs" value=""/>
+        <property name="work.dir" value="${basedir}"/>
+        <condition property="no.deps">
+            <and>
+                <istrue value="${no.dependencies}"/>
+            </and>
+        </condition>
+        <property name="javac.debug" value="true"/>
+        <property name="javadoc.preview" value="true"/>
+        <property name="application.args" value=""/>
+        <property name="source.encoding" value="${file.encoding}"/>
+        <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+            <and>
+                <isset property="javadoc.encoding"/>
+                <not>
+                    <equals arg1="${javadoc.encoding}" arg2=""/>
+                </not>
+            </and>
+        </condition>
+        <property name="javadoc.encoding.used" value="${source.encoding}"/>
+        <property name="includes" value="**"/>
+        <property name="excludes" value=""/>
+        <property name="do.depend" value="false"/>
+        <condition property="do.depend.true">
+            <istrue value="${do.depend}"/>
+        </condition>
+        <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
+            <and>
+                <isset property="jaxws.endorsed.dir"/>
+                <available file="nbproject/jaxws-build.xml"/>
+            </and>
+        </condition>
+    </target>
+    <target name="-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+        <fail unless="src.src.dir">Must set src.src.dir</fail>
+        <fail unless="test.src.dir">Must set test.src.dir</fail>
+        <fail unless="build.dir">Must set build.dir</fail>
+        <fail unless="dist.dir">Must set dist.dir</fail>
+        <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+        <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+        <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+        <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+        <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+        <fail unless="dist.jar">Must set dist.jar</fail>
+    </target>
+    <target name="-init-macrodef-property">
+        <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="name"/>
+            <attribute name="value"/>
+            <sequential>
+                <property name="@{name}" value="${@{value}}"/>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-javac">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="${javac.debug}" name="debug"/>
+            <attribute default="/does/not/exist" name="sourcepath"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+        <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <sequential>
+                <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </depend>
+            </sequential>
+        </macrodef>
+        <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <sequential>
+                <fail unless="javac.includes">Must set javac.includes</fail>
+                <pathconvert pathsep="," property="javac.includes.binary">
+                    <path>
+                        <filelist dir="@{destdir}" files="${javac.includes}"/>
+                    </path>
+                    <globmapper from="*.java" to="*.class"/>
+                </pathconvert>
+                <delete>
+                    <files includes="${javac.includes.binary}"/>
+                </delete>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-junit">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <sequential>
+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
+                    <batchtest todir="${build.test.results.dir}">
+                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                            <filename name="@{testincludes}"/>
+                        </fileset>
+                    </batchtest>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${main.class}" name="name"/>
+            <attribute default="${debug.classpath}" name="classpath"/>
+            <attribute default="" name="stopclassname"/>
+            <sequential>
+                <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </nbjpdastart>
+            </sequential>
+        </macrodef>
+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${build.classes.dir}" name="dir"/>
+            <sequential>
+                <nbjpdareload>
+                    <fileset dir="@{dir}" includes="${fix.classes}">
+                        <include name="${fix.includes}*.class"/>
+                    </fileset>
+                </nbjpdareload>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-debug-args">
+        <property name="version-output" value="java version &quot;${ant.java.version}"/>
+        <condition property="have-jdk-older-than-1.4">
+            <or>
+                <contains string="${version-output}" substring="java version &quot;1.0"/>
+                <contains string="${version-output}" substring="java version &quot;1.1"/>
+                <contains string="${version-output}" substring="java version &quot;1.2"/>
+                <contains string="${version-output}" substring="java version &quot;1.3"/>
+            </or>
+        </condition>
+        <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+            <istrue value="${have-jdk-older-than-1.4}"/>
+        </condition>
+        <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+            <os family="windows"/>
+        </condition>
+        <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+            <isset property="debug.transport"/>
+        </condition>
+    </target>
+    <target depends="-init-debug-args" name="-init-macrodef-debug">
+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${debug.classpath}" name="classpath"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" fork="true">
+                    <jvmarg line="${debug-args-line}"/>
+                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-java">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${main.class}" name="classname"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" fork="true">
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="${run.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-presetdef-jar">
+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <jar compress="${jar.compress}" jarfile="${dist.jar}">
+                <j2seproject1:fileset dir="${build.classes.dir}"/>
+            </jar>
+        </presetdef>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
+    <!--
+                ===================
+                COMPILATION SECTION
+                ===================
+            -->
+    <target depends="init" name="deps-jar" unless="no.deps"/>
+    <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+    <target depends="init" name="-check-automatic-build">
+        <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+    </target>
+    <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+        <antcall target="clean"/>
+    </target>
+    <target depends="init,deps-jar" name="-pre-pre-compile">
+        <mkdir dir="${build.classes.dir}"/>
+    </target>
+    <target name="-pre-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target if="do.depend.true" name="-compile-depend">
+        <j2seproject3:depend/>
+    </target>
+    <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
+        <j2seproject3:javac/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${src.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+    <target name="-pre-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:force-recompile/>
+        <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.src.dir}"/>
+    </target>
+    <target name="-post-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+    <!--
+                ====================
+                JAR BUILDING SECTION
+                ====================
+            -->
+    <target depends="init" name="-pre-pre-jar">
+        <dirname file="${dist.jar}" property="dist.jar.dir"/>
+        <mkdir dir="${dist.jar.dir}"/>
+    </target>
+    <target name="-pre-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
+        <j2seproject1:jar/>
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
+        <j2seproject1:jar manifest="${manifest.file}"/>
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+        <j2seproject1:jar manifest="${manifest.file}">
+            <j2seproject1:manifest>
+                <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+            </j2seproject1:manifest>
+        </j2seproject1:jar>
+        <echo>To run this application from the command line without Ant, try:</echo>
+        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+        <property location="${dist.jar}" name="dist.jar.resolved"/>
+        <pathconvert property="run.classpath.with.dist.jar">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+        </pathconvert>
+        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
+        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+        <pathconvert property="run.classpath.without.build.classes.dir">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to=""/>
+        </pathconvert>
+        <pathconvert pathsep=" " property="jar.classpath">
+            <path path="${run.classpath.without.build.classes.dir}"/>
+            <chainedmapper>
+                <flattenmapper/>
+                <globmapper from="*" to="lib/*"/>
+            </chainedmapper>
+        </pathconvert>
+        <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+        <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+            <fileset dir="${build.classes.dir}"/>
+            <manifest>
+                <attribute name="Main-Class" value="${main.class}"/>
+                <attribute name="Class-Path" value="${jar.classpath}"/>
+            </manifest>
+        </copylibs>
+        <echo>To run this application from the command line without Ant, try:</echo>
+        <property location="${dist.jar}" name="dist.jar.resolved"/>
+        <echo>java -jar "${dist.jar.resolved}"</echo>
+    </target>
+    <target name="-post-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
+    <!--
+                =================
+                EXECUTION SECTION
+                =================
+            -->
+    <target depends="init,compile" description="Run a main class." name="run">
+        <j2seproject1:java>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <target name="-do-not-recompile">
+        <property name="javac.includes.binary" value=""/>
+    </target>
+    <target depends="init,-do-not-recompile,compile-single" name="run-single">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}"/>
+    </target>
+    <!--
+                =================
+                DEBUGGING SECTION
+                =================
+            -->
+    <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+        <j2seproject1:nbjpdastart name="${debug.class}"/>
+    </target>
+    <target depends="init,compile" name="-debug-start-debuggee">
+        <j2seproject3:debug>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+    <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+    </target>
+    <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}"/>
+    </target>
+    <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+    <target depends="init" name="-pre-debug-fix">
+        <fail unless="fix.includes">Must set fix.includes</fail>
+        <property name="javac.includes" value="${fix.includes}.java"/>
+    </target>
+    <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+        <j2seproject1:nbjpdareload/>
+    </target>
+    <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+    <!--
+                ===============
+                JAVADOC SECTION
+                ===============
+            -->
+    <target depends="init" name="-javadoc-build">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <fileset dir="${src.src.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/*.java"/>
+            </fileset>
+        </javadoc>
+    </target>
+    <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+    </target>
+    <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+    <!--
+                =========================
+                JUNIT COMPILATION SECTION
+                =========================
+            -->
+    <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+        <mkdir dir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-pre-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target if="do.depend.true" name="-compile-test-depend">
+        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+        <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+        <copy todir="${build.test.classes.dir}">
+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+    <target name="-pre-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+        <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+        <copy todir="${build.test.classes.dir}">
+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+    <!--
+                =======================
+                JUNIT EXECUTION SECTION
+                =======================
+            -->
+    <target depends="init" if="have.tests" name="-pre-test-run">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+        <j2seproject3:junit testincludes="**/*Test.java"/>
+    </target>
+    <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target depends="init" if="have.tests" name="test-report"/>
+    <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+    <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+    <target depends="init" if="have.tests" name="-pre-test-run-single">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <j2seproject3:junit excludes="" includes="${test.includes}"/>
+    </target>
+    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+    <!--
+                =======================
+                JUNIT DEBUGGING SECTION
+                =======================
+            -->
+    <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
+        <delete file="${test.report.file}"/>
+        <mkdir dir="${build.test.results.dir}"/>
+        <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
+            <customize>
+                <syspropertyset>
+                    <propertyref prefix="test-sys-prop."/>
+                    <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                </syspropertyset>
+                <arg value="${test.class}"/>
+                <arg value="showoutput=true"/>
+                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
+                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+    </target>
+    <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+    <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+    </target>
+    <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+    <!--
+                =========================
+                APPLET EXECUTION SECTION
+                =========================
+            -->
+    <target depends="init,compile-single" name="run-applet">
+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+        <j2seproject1:java classname="sun.applet.AppletViewer">
+            <customize>
+                <arg value="${applet.url}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <!--
+                =========================
+                APPLET DEBUGGING  SECTION
+                =========================
+            -->
+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+        <j2seproject3:debug classname="sun.applet.AppletViewer">
+            <customize>
+                <arg value="${applet.url}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+    <!--
+                ===============
+                CLEANUP SECTION
+                ===============
+            -->
+    <target depends="init" name="deps-clean" unless="no.deps"/>
+    <target depends="init" name="-do-clean">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.dir}"/>
+    </target>
+    <target name="-post-clean">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/findbugs.settings	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,72 @@
+#FindBugs User Preferences
+#Mon Jun 15 13:37:16 PDT 2009
+detectorAbnormalFinallyBlockReturn=AbnormalFinallyBlockReturn|false
+detectorAbstractClassEmptyMethods=AbstractClassEmptyMethods|false
+detectorAbstractOverriddenMethod=AbstractOverriddenMethod|false
+detectorArrayBasedCollections=ArrayBasedCollections|false
+detectorArrayWrappedCallByReference=ArrayWrappedCallByReference|false
+detectorBloatedAssignmentScope=BloatedAssignmentScope|false
+detectorBloatedSynchronizedBlock=BloatedSynchronizedBlock|false
+detectorClassEnvy=ClassEnvy|false
+detectorCollectStatistics=CollectStatistics|false
+detectorConfusingAutoboxedOverloading=ConfusingAutoboxedOverloading|false
+detectorConstantListIndex=ConstantListIndex|false
+detectorCopiedOverriddenMethod=CopiedOverriddenMethod|false
+detectorCustomBuiltXML=CustomBuiltXML|false
+detectorCyclomaticComplexity=CyclomaticComplexity|false
+detectorDateComparison=DateComparison|false
+detectorDeclaredRuntimeException=DeclaredRuntimeException|false
+detectorDeletingWhileIterating=DeletingWhileIterating|false
+detectorDubiousListCollection=DubiousListCollection|false
+detectorFieldCouldBeLocal=FieldCouldBeLocal|false
+detectorFinalParameters=FinalParameters|false
+detectorFloatingPointLoops=FloatingPointLoops|false
+detectorInefficientStringBuffering=InefficientStringBuffering|false
+detectorInheritanceTypeChecking=InheritanceTypeChecking|false
+detectorJDBCVendorReliance=JDBCVendorReliance|false
+detectorListIndexedIterating=ListIndexedIterating|false
+detectorLiteralStringComparison=LiteralStringComparison|false
+detectorLocalSynchronizedCollection=LocalSynchronizedCollection|false
+detectorLostExceptionStackTrace=LostExceptionStackTrace|false
+detectorManualArrayCopy=ManualArrayCopy|false
+detectorMethodReturnsConstant=MethodReturnsConstant|false
+detectorNeedlessAutoboxing=NeedlessAutoboxing|false
+detectorNeedlessCustomSerialization=NeedlessCustomSerialization|false
+detectorNeedlessInstanceRetrieval=NeedlessInstanceRetrieval|false
+detectorNeedlessMemberCollectionSynchronization=NeedlessMemberCollectionSynchronization|false
+detectorNonCollectionMethodUse=NonCollectionMethodUse|false
+detectorNonOwnedSynchronization=NonOwnedSynchronization|false
+detectorNonRecycleableTaglibs=NonRecycleableTaglibs|false
+detectorOrphanedDOMNode=OrphanedDOMNode|false
+detectorOverlyConcreteParameter=OverlyConcreteParameter|false
+detectorParallelLists=ParallelLists|false
+detectorPartiallyConstructedObjectAccess=PartiallyConstructedObjectAccess|false
+detectorPossibleIncompleteSerialization=PossibleIncompleteSerialization|false
+detectorPossibleMemoryBloat=PossibleMemoryBloat|false
+detectorPossiblyRedundantMethodCalls=PossiblyRedundantMethodCalls|false
+detectorSQLInLoop=SQLInLoop|false
+detectorSection508Compliance=Section508Compliance|false
+detectorSillynessPotPourri=SillynessPotPourri|false
+detectorSloppyClassReflection=SloppyClassReflection|false
+detectorSluggishGui=SluggishGui|false
+detectorSpoiledChildInterfaceImplementor=SpoiledChildInterfaceImplementor|false
+detectorSpuriousThreadStates=SpuriousThreadStates|false
+detectorStaticArrayCreatedInMethod=StaticArrayCreatedInMethod|false
+detectorStaticMethodInstanceInvocation=StaticMethodInstanceInvocation|false
+detectorSuspiciousComparatorReturnValues=SuspiciousComparatorReturnValues|false
+detectorSuspiciousJDKVersionUse=SuspiciousJDKVersionUse|false
+detectorSuspiciousWaitOnConcurrentObject=SuspiciousWaitOnConcurrentObject|false
+detectorSyncCollectionIterators=SyncCollectionIterators|false
+detectorTailRecursion=TailRecursion|false
+detectorUnnecessaryStoreBeforeReturn=UnnecessaryStoreBeforeReturn|false
+detectorUnrelatedCollectionContents=UnrelatedCollectionContents|false
+detectorUnrelatedReturnValues=UnrelatedReturnValues|false
+detectorUseAddAll=UseAddAll|false
+detectorUseCharacterParameterizedMethod=UseCharacterParameterizedMethod|false
+detectorUseEnumCollections=UseEnumCollections|false
+detectorUseSplit=UseSplit|false
+detectorUseToArray=UseToArray|false
+detector_threshold=2
+effort=default
+filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false
+filter_settings_neg=|
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/genfiles.properties	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=b40e775f
+build.xml.script.CRC32=af8dc3cb
+build.xml.stylesheet.CRC32=958a1d3e
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=b40e775f
+nbproject/build-impl.xml.script.CRC32=624d12c5
+nbproject/build-impl.xml.stylesheet.CRC32=65b8de21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/project.properties	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,65 @@
+application.title=jdwpgen
+application.vendor=sun
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+    ${run.classpath}
+debug.test.classpath=\
+    ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/jdwpgen.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+file.reference.tools-jdwpgen=../../tools/src/build/tools/jdwpgen
+file.reference.tools-src=../../tools/src
+includes=build/tools/jdwpgen/**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=-Xlint:all
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}:\
+    ${libs.junit.classpath}:\
+    ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=true
+javadoc.nonavbar=true
+javadoc.notree=true
+javadoc.private=true
+javadoc.splitindex=false
+javadoc.use=false
+javadoc.version=false
+javadoc.windowtitle=
+main.class=jdwpgen.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+    ${javac.test.classpath}:\
+    ${build.test.classes.dir}
+source.encoding=UTF-8
+src.src.dir=${file.reference.tools-src}
+test.src.dir=test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/project.xml	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.java.j2seproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+            <name>jdwpgen</name>
+            <minimum-ant-version>1.6.5</minimum-ant-version>
+            <source-roots>
+                <root id="src.src.dir"/>
+            </source-roots>
+            <test-roots>
+                <root id="test.src.dir"/>
+            </test-roots>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/netbeans/jdwpgen/nbproject/sqe.properties	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,2 @@
+#Path to FindbugsSettingsFile (relative)
+findbugs.settings.file=findbugs.settings
--- a/make/tools/src/build/tools/jdwpgen/AbstractNamedNode.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/AbstractNamedNode.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,7 +30,7 @@
 
 abstract class AbstractNamedNode extends Node {
 
-    NameNode nameNode;
+    NameNode nameNode = null;
     String name;
 
     public String name() {
--- a/make/tools/src/build/tools/jdwpgen/AltNode.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/AltNode.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,7 +30,7 @@
 
 class AltNode extends AbstractGroupNode implements TypeNode {
 
-    SelectNode select;
+    SelectNode select = null;
 
     void constrain(Context ctx) {
         super.constrain(ctx);
--- a/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java	Tue Sep 01 13:03:09 2009 -0700
@@ -33,13 +33,7 @@
     /**
      * The mapping between a constant and its value.
      */
-    protected static Map<String, String> constantMap;
-
-    ConstantSetNode(){
-        if (constantMap == null) {
-            constantMap = new HashMap<String, String>();
-        }
-    }
+    protected static final Map<String, String> constantMap = new HashMap<String, String>();
 
     void prune() {
         List<Node> addons = new ArrayList<Node>();
@@ -95,9 +89,6 @@
     }
 
     public static String getConstant(String key){
-        if (constantMap == null) {
-            return "";
-        }
         String com = constantMap.get(key);
         if(com == null){
             return "";
--- a/make/tools/src/build/tools/jdwpgen/Main.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/Main.java	Tue Sep 01 13:03:09 2009 -0700
@@ -25,13 +25,11 @@
 
 package build.tools.jdwpgen;
 
-import java.util.*;
 import java.io.*;
 
 class Main {
 
     static String specSource;
-    static Map nameMap = new HashMap();
     static boolean genDebug = true;
 
     static void usage() {
@@ -43,7 +41,6 @@
         System.err.println("-doc <doc_output>");
         System.err.println("-jdi <java_output>");
         System.err.println("-include <include_file_output>");
-        System.exit(1);
     }
 
     public static void main(String args[]) throws IOException {
@@ -66,6 +63,7 @@
                 } else {
                     System.err.println("Invalid option: " + arg);
                     usage();
+                    return;
                 }
             } else {
                 specSource = arg;
@@ -75,6 +73,7 @@
         if (reader == null) {
             System.err.println("<spec_input> must be specified");
             usage();
+            return;
         }
 
         Parse parse = new Parse(reader);
--- a/make/tools/src/build/tools/jdwpgen/Node.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/Node.java	Tue Sep 01 13:03:09 2009 -0700
@@ -36,7 +36,7 @@
     int lineno;
     List<String> commentList = new ArrayList<String>();
     Node parent = null;
-    Context context;
+    Context context = null;
 
     static final int maxStructIndent = 5;
     static int structIndent = 0; // horrible hack
@@ -82,7 +82,7 @@
     }
 
     void indent(PrintWriter writer, int depth) {
-        for (int i = depth; i > 0; --i) {
+        for (int i = 0; i < depth; i++) {
             writer.print("    ");
         }
     }
@@ -195,6 +195,6 @@
         System.err.println(Main.specSource + ":" + lineno + ": " +
                            kind + " - " + errmsg);
         System.err.println();
-        System.exit(1);
+        throw new RuntimeException("Error: " + errmsg);
     }
 }
--- a/make/tools/src/build/tools/jdwpgen/Parse.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/Parse.java	Tue Sep 01 13:03:09 2009 -0700
@@ -146,8 +146,12 @@
                             Node node = (Node)proto.getClass().newInstance();
                             node.set(kind, list, izer.lineno());
                             return node;
-                        } catch (Exception exc) {
+                        } catch (InstantiationException exc) {
                             error(exc.toString());
+                            return null;
+                        } catch (IllegalAccessException exc) {
+                            error(exc.toString());
+                            return null;
                         }
                     }
                 } else {
@@ -166,6 +170,6 @@
     void error(String errmsg) {
         System.err.println(Main.specSource + ":" + izer.lineno() +
                            ": " + errmsg);
-        System.exit(1);
+        throw new RuntimeException("Error: " + errmsg);
     }
 }
--- a/make/tools/src/build/tools/jdwpgen/RepeatNode.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/RepeatNode.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,7 +30,7 @@
 
 class RepeatNode extends AbstractTypeNode {
 
-    Node member;
+    Node member = null;
 
     void constrain(Context ctx) {
         super.constrain(ctx);
--- a/make/tools/src/build/tools/jdwpgen/SelectNode.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/make/tools/src/build/tools/jdwpgen/SelectNode.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,7 +30,7 @@
 
 class SelectNode extends AbstractGroupNode implements TypeNode {
 
-    AbstractSimpleTypeNode typeNode;
+    AbstractSimpleTypeNode typeNode = null;
 
     void prune() {
         super.prune();
--- a/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java	Tue Sep 01 13:03:09 2009 -0700
@@ -129,7 +129,7 @@
                 System.err.print(pc.getPrompt());
                 System.err.flush();
 
-                pc.setPassword(Password.readPassword(System.in));
+                pc.setPassword(Password.readPassword(System.in, pc.isEchoOn()));
 
             } else if (callbacks[i] instanceof ConfirmationCallback) {
                 confirmation = (ConfirmationCallback) callbacks[i];
--- a/src/share/classes/com/sun/security/sasl/Provider.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/com/sun/security/sasl/Provider.java	Tue Sep 01 13:03:09 2009 -0700
@@ -51,7 +51,7 @@
         " server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
 
     public Provider() {
-        super("SunSASL", 1.5, info);
+        super("SunSASL", 1.7d, info);
 
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
--- a/src/share/classes/java/lang/EnumConstantNotPresentException.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/EnumConstantNotPresentException.java	Tue Sep 01 13:03:09 2009 -0700
@@ -28,8 +28,12 @@
 /**
  * Thrown when an application tries to access an enum constant by name
  * and the enum type contains no constant with the specified name.
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
  *
  * @author  Josh Bloch
+ * @see     java.lang.reflect.AnnotatedElement
  * @since   1.5
  */
 public class EnumConstantNotPresentException extends RuntimeException {
--- a/src/share/classes/java/lang/String.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/String.java	Tue Sep 01 13:03:09 2009 -0700
@@ -2301,6 +2301,54 @@
      * @spec JSR-51
      */
     public String[] split(String regex, int limit) {
+        /* fastpath if the regex is a
+           (1)one-char String and this character is not one of the
+              RegEx's meta characters ".$|()[{^?*+\\", or
+           (2)two-char String and the first char is the backslash and
+              the second is not the ascii digit or ascii letter.
+        */
+        char ch = 0;
+        if (((regex.count == 1 &&
+             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
+             (regex.length() == 2 &&
+              regex.charAt(0) == '\\' &&
+              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
+              ((ch-'a')|('z'-ch)) < 0 &&
+              ((ch-'A')|('Z'-ch)) < 0)) &&
+            (ch < Character.MIN_HIGH_SURROGATE ||
+             ch > Character.MAX_LOW_SURROGATE))
+        {
+            int off = 0;
+            int next = 0;
+            boolean limited = limit > 0;
+            ArrayList<String> list = new ArrayList<String>();
+            while ((next = indexOf(ch, off)) != -1) {
+                if (!limited || list.size() < limit - 1) {
+                    list.add(substring(off, next));
+                    off = next + 1;
+                } else {    // last one
+                    //assert (list.size() == limit - 1);
+                    list.add(substring(off, count));
+                    off = count;
+                    break;
+                }
+            }
+            // If no match was found, return this
+            if (off == 0)
+                return new String[] { this };
+
+            // Add remaining segment
+            if (!limited || list.size() < limit)
+                list.add(substring(off, count));
+
+            // Construct result
+            int resultSize = list.size();
+            if (limit == 0)
+                while (resultSize > 0 && list.get(resultSize-1).length() == 0)
+                    resultSize--;
+            String[] result = new String[resultSize];
+            return list.subList(0, resultSize).toArray(result);
+        }
         return Pattern.compile(regex).split(this, limit);
     }
 
--- a/src/share/classes/java/lang/TypeNotPresentException.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/TypeNotPresentException.java	Tue Sep 01 13:03:09 2009 -0700
@@ -35,8 +35,12 @@
  * <p>Note that this exception may be used when undefined type variables
  * are accessed as well as when types (e.g., classes, interfaces or
  * annotation types) are loaded.
+ * In particular, this exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
  *
  * @author  Josh Bloch
+ * @see     java.lang.reflect.AnnotatedElement
  * @since 1.5
  */
 public class TypeNotPresentException extends RuntimeException {
--- a/src/share/classes/java/lang/annotation/AnnotationFormatError.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/annotation/AnnotationFormatError.java	Tue Sep 01 13:03:09 2009 -0700
@@ -28,8 +28,12 @@
 /**
  * Thrown when the annotation parser attempts to read an annotation
  * from a class file and determines that the annotation is malformed.
+ * This error can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
  *
  * @author  Josh Bloch
+ * @see     java.lang.reflect.AnnotatedElement
  * @since   1.5
  */
 public class AnnotationFormatError extends Error {
--- a/src/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,8 +30,12 @@
  * Thrown to indicate that a program has attempted to access an element of
  * an annotation whose type has changed after the annotation was compiled
  * (or serialized).
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
  *
  * @author  Josh Bloch
+ * @see     java.lang.reflect.AnnotatedElement
  * @since 1.5
  */
 public class AnnotationTypeMismatchException extends RuntimeException {
--- a/src/share/classes/java/lang/annotation/IncompleteAnnotationException.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/annotation/IncompleteAnnotationException.java	Tue Sep 01 13:03:09 2009 -0700
@@ -30,8 +30,12 @@
  * an annotation type that was added to the annotation type definition after
  * the annotation was compiled (or serialized).  This exception will not be
  * thrown if the new element has a default value.
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
  *
  * @author  Josh Bloch
+ * @see     java.lang.reflect.AnnotatedElement
  * @since 1.5
  */
 public class IncompleteAnnotationException extends RuntimeException {
--- a/src/share/classes/java/lang/reflect/AnnotatedElement.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/lang/reflect/AnnotatedElement.java	Tue Sep 01 13:03:09 2009 -0700
@@ -50,6 +50,11 @@
  * java.lang.annotation.AnnotationTypeMismatchException} or an
  * {@link java.lang.annotation.IncompleteAnnotationException}.
  *
+ * @see java.lang.EnumConstantNotPresentException
+ * @see java.lang.TypeNotPresentException
+ * @see java.lang.annotation.AnnotationFormatError
+ * @see java.lang.annotation.AnnotationTypeMismatchException
+ * @see java.lang.annotation.IncompleteAnnotationException
  * @since 1.5
  * @author Josh Bloch
  */
--- a/src/share/classes/java/nio/channels/AsynchronousByteChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousByteChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -56,18 +56,18 @@
     /**
      * Reads a sequence of bytes from this channel into the given buffer.
      *
-     * <p> This method initiates an operation to read a sequence of bytes from
-     * this channel into the given buffer. The method returns a {@link Future}
-     * representing the pending result of the operation. The result of the
-     * operation, obtained by invoking the {@code Future} 's {@link
-     * Future#get() get} method, is the number of bytes read or {@code -1} if
-     * all bytes have been read and the channel has reached end-of-stream.
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the read
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes read or {@code -1} if no bytes could be
+     * read because the channel has reached end-of-stream.
      *
-     * <p> This method initiates a read operation to read up to <i>r</i> bytes
-     * from the channel, where <i>r</i> is the number of bytes remaining in the
-     * buffer, that is, {@code dst.remaining()} at the time that the read is
-     * attempted. Where <i>r</i> is 0, the read operation completes immediately
-     * with a result of {@code 0} without initiating an I/O operation.
+     * <p> The read operation may read up to <i>r</i> bytes from the channel,
+     * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+     * {@code dst.remaining()} at the time that the read is attempted. Where
+     * <i>r</i> is 0, the read operation completes immediately with a result of
+     * {@code 0} without initiating an I/O operation.
      *
      * <p> Suppose that a byte sequence of length <i>n</i> is read, where
      * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
@@ -79,44 +79,46 @@
      * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
      *
      * <p> Buffers are not safe for use by multiple concurrent threads so care
-     * should be taken to not to access the buffer until the operaton has completed.
+     * should be taken to not access the buffer until the operation has
+     * completed.
      *
      * <p> This method may be invoked at any time. Some channel types may not
      * allow more than one read to be outstanding at any given time. If a thread
      * initiates a read operation before a previous read operation has
      * completed then a {@link ReadPendingException} will be thrown.
      *
-     * <p> The <tt>handler</tt> parameter is used to specify a {@link
-     * CompletionHandler}. When the read operation completes the handler's
-     * {@link CompletionHandler#completed completed} method is executed.
-     *
-     *
      * @param   dst
      *          The buffer into which bytes are to be transferred
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The completion handler object; can be {@code null}
-     *
-     * @return  A Future representing the result of the operation
+     *          The completion handler
      *
      * @throws  IllegalArgumentException
      *          If the buffer is read-only
      * @throws  ReadPendingException
      *          If the channel does not allow more than one read to be outstanding
      *          and a previous read has not completed
+     * @throws  ShutdownChannelGroupException
+     *          If the channel is associated with a {@link AsynchronousChannelGroup
+     *          group} that has terminated
      */
-    <A> Future<Integer> read(ByteBuffer dst,
-                             A attachment,
-                             CompletionHandler<Integer,? super A> handler);
+    <A> void read(ByteBuffer dst,
+                  A attachment,
+                  CompletionHandler<Integer,? super A> handler);
 
     /**
      * Reads a sequence of bytes from this channel into the given buffer.
      *
-     * <p> An invocation of this method of the form <tt>c.read(dst)</tt>
-     * behaves in exactly the same manner as the invocation
-     * <blockquote><pre>
-     * c.read(dst, null, null);</pre></blockquote>
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The method
+     * behaves in exactly the same manner as the {@link
+     * #read(ByteBuffer,Object,CompletionHandler)
+     * read(ByteBuffer,Object,CompletionHandler)} method except that instead
+     * of specifying a completion handler, this method returns a {@code Future}
+     * representing the pending result. The {@code Future}'s {@link Future#get()
+     * get} method returns the number of bytes read or {@code -1} if no bytes
+     * could be read because the channel has reached end-of-stream.
      *
      * @param   dst
      *          The buffer into which bytes are to be transferred
@@ -134,17 +136,17 @@
     /**
      * Writes a sequence of bytes to this channel from the given buffer.
      *
-     * <p> This method initiates an operation to write a sequence of bytes to
-     * this channel from the given buffer. This method returns a {@link
-     * Future} representing the pending result of the operation. The result
-     * of the operation, obtained by invoking the <tt>Future</tt>'s {@link
-     * Future#get() get} method, is the number of bytes written, possibly zero.
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the write
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes written.
      *
-     * <p> This method initiates a write operation to write up to <i>r</i> bytes
-     * to the channel, where <i>r</i> is the number of bytes remaining in the
-     * buffer, that is, {@code src.remaining()}  at the moment the write is
-     * attempted. Where <i>r</i> is 0, the write operation completes immediately
-     * with a result of {@code 0} without initiating an I/O operation.
+     * <p> The write operation may write up to <i>r</i> bytes to the channel,
+     * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+     * {@code src.remaining()} at the time that the write is attempted. Where
+     * <i>r</i> is 0, the write operation completes immediately with a result of
+     * {@code 0} without initiating an I/O operation.
      *
      * <p> Suppose that a byte sequence of length <i>n</i> is written, where
      * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
@@ -156,41 +158,43 @@
      * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
      *
      * <p> Buffers are not safe for use by multiple concurrent threads so care
-     * should be taken to not to access the buffer until the operaton has completed.
+     * should be taken to not access the buffer until the operation has
+     * completed.
      *
      * <p> This method may be invoked at any time. Some channel types may not
      * allow more than one write to be outstanding at any given time. If a thread
      * initiates a write operation before a previous write operation has
      * completed then a {@link WritePendingException} will be thrown.
      *
-     * <p> The <tt>handler</tt> parameter is used to specify a {@link
-     * CompletionHandler}. When the write operation completes the handler's
-     * {@link CompletionHandler#completed completed} method is executed.
-     *
      * @param   src
      *          The buffer from which bytes are to be retrieved
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The completion handler object; can be {@code null}
-     *
-     * @return  A Future representing the result of the operation
+     *          The completion handler object
      *
      * @throws  WritePendingException
      *          If the channel does not allow more than one write to be outstanding
      *          and a previous write has not completed
+     * @throws  ShutdownChannelGroupException
+     *          If the channel is associated with a {@link AsynchronousChannelGroup
+     *          group} that has terminated
      */
-    <A> Future<Integer> write(ByteBuffer src,
-                              A attachment,
-                              CompletionHandler<Integer,? super A> handler);
+    <A> void write(ByteBuffer src,
+                   A attachment,
+                   CompletionHandler<Integer,? super A> handler);
 
     /**
      * Writes a sequence of bytes to this channel from the given buffer.
      *
-     * <p> An invocation of this method of the form <tt>c.write(src)</tt>
-     * behaves in exactly the same manner as the invocation
-     * <blockquote><pre>
-     * c.write(src, null, null);</pre></blockquote>
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The method
+     * behaves in exactly the same manner as the {@link
+     * #write(ByteBuffer,Object,CompletionHandler)
+     * write(ByteBuffer,Object,CompletionHandler)} method except that instead
+     * of specifying a completion handler, this method returns a {@code Future}
+     * representing the pending result. The {@code Future}'s {@link Future#get()
+     * get} method returns the number of bytes written.
      *
      * @param   src
      *          The buffer from which bytes are to be retrieved
--- a/src/share/classes/java/nio/channels/AsynchronousChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -34,7 +34,8 @@
  *
  * <ol>
  * <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li>
- * <li><pre>Future&lt;V&gt; <em>operation</em>(<em>...</em> A attachment, {@link CompletionHandler}&lt;V,? super A&gt handler)</pre></li>
+ * <li><pre>void <em>operation</em>(<em>...</em> A attachment, {@link
+ *   CompletionHandler}&lt;V,? super A&gt; handler)</pre></li>
  * </ol>
  *
  * where <i>operation</i> is the name of the I/O operation (read or write for
@@ -48,7 +49,7 @@
  * interface may be used to check if the operation has completed, wait for its
  * completion, and to retrieve the result. In the second form, a {@link
  * CompletionHandler} is invoked to consume the result of the I/O operation when
- * it completes, fails, or is cancelled.
+ * it completes or fails.
  *
  * <p> A channel that implements this interface is <em>asynchronously
  * closeable</em>: If an I/O operation is outstanding on the channel and the
@@ -63,33 +64,33 @@
  * <h4>Cancellation</h4>
  *
  * <p> The {@code Future} interface defines the {@link Future#cancel cancel}
- * method to cancel execution of a task.
+ * method to cancel execution. This causes all threads waiting on the result of
+ * the I/O operation to throw {@link java.util.concurrent.CancellationException}.
+ * Whether the underlying I/O operation can be cancelled is highly implementation
+ * specific and therefore not specified. Where cancellation leaves the channel,
+ * or the entity to which it is connected, in an inconsistent state, then the
+ * channel is put into an implementation specific <em>error state</em> that
+ * prevents further attempts to initiate I/O operations that are <i>similar</i>
+ * to the operation that was cancelled. For example, if a read operation is
+ * cancelled but the implementation cannot guarantee that bytes have not been
+ * read from the channel then it puts the channel into an error state; further
+ * attempts to initiate a {@code read} operation cause an unspecified runtime
+ * exception to be thrown. Similarly, if a write operation is cancelled but the
+ * implementation cannot guarantee that bytes have not been written to the
+ * channel then subsequent attempts to initiate a {@code write} will fail with
+ * an unspecified runtime exception.
  *
- * <p> Where the {@code cancel} method is invoked with the {@code
+ * <p> Where the {@link Future#cancel cancel} method is invoked with the {@code
  * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
- * may be interrupted by closing the channel. This will cause any other I/O
- * operations outstanding on the channel to complete with the exception {@link
- * AsynchronousCloseException}.
- *
- * <p> If a {@code CompletionHandler} is specified when initiating an I/O
- * operation, and the {@code cancel} method is invoked to cancel the I/O
- * operation before it completes, then the {@code CompletionHandler}'s {@link
- * CompletionHandler#cancelled cancelled} method is invoked.
- *
- * <p> If an implementation of this interface supports a means to cancel I/O
- * operations, and where cancellation may leave the channel, or the entity to
- * which it is connected, in an inconsistent state, then the channel is put into
- * an implementation specific <em>error state</em> that prevents further
- * attempts to initiate I/O operations on the channel. For example, if a read
- * operation is cancelled but the implementation cannot guarantee that bytes
- * have not been read from the channel then it puts the channel into error state
- * state; further attempts to initiate a {@code read} operation causes an
- * unspecified runtime exception to be thrown.
+ * may be interrupted by closing the channel. In that case all threads waiting
+ * on the result of the I/O operation throw {@code CancellationException} and
+ * any other I/O operations outstanding on the channel complete with the
+ * exception {@link AsynchronousCloseException}.
  *
  * <p> Where the {@code cancel} method is invoked to cancel read or write
- * operations then it recommended that all buffers used in the I/O operations be
- * discarded or care taken to ensure that the buffers are not accessed while the
- * channel remains open.
+ * operations then it is recommended that all buffers used in the I/O operations
+ * be discarded or care taken to ensure that the buffers are not accessed while
+ * the channel remains open.
  *
  *  @since 1.7
  */
@@ -102,7 +103,7 @@
      *
      * <p> Any outstanding asynchronous operations upon this channel will
      * complete with the exception {@link AsynchronousCloseException}. After a
-     * channel is closed then further attempts to initiate asynchronous I/O
+     * channel is closed, further attempts to initiate asynchronous I/O
      * operations complete immediately with cause {@link ClosedChannelException}.
      *
      * <p>  This method otherwise behaves exactly as specified by the {@link
--- a/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -109,19 +109,13 @@
  *  // print the source address of all packets that we receive
  *  dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
  *      public void completed(SocketAddress sa, ByteBuffer buffer) {
- *          try {
- *               System.out.println(sa);
- *
- *               buffer.clear();
- *               dc.receive(buffer, buffer, this);
- *           } catch (...) { ... }
+ *          System.out.println(sa);
+ *          buffer.clear();
+ *          dc.receive(buffer, buffer, this);
  *      }
  *      public void failed(Throwable exc, ByteBuffer buffer) {
  *          ...
  *      }
- *      public void cancelled(ByteBuffer buffer) {
- *          ...
- *      }
  *  });
  * </pre>
  *
@@ -314,10 +308,10 @@
     /**
      * Receives a datagram via this channel.
      *
-     * <p> This method initiates the receiving of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The {@code Future}'s {@link Future#get() get} method returns
-     * the source address of the datagram upon successful completion.
+     * <p> This method initiates the receiving of a datagram into the given
+     * buffer. The {@code handler} parameter is a completion handler that is
+     * invoked when the receive operation completes (or fails). The result
+     * passed to the completion handler is the datagram's source address.
      *
      * <p> The datagram is transferred into the given byte buffer starting at
      * its current position, as if by a regular {@link AsynchronousByteChannel#read
@@ -350,28 +344,26 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the timeout is negative or the buffer is read-only
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<SocketAddress> receive(ByteBuffer dst,
-                                                      long timeout,
-                                                      TimeUnit unit,
-                                                      A attachment,
-                                                      CompletionHandler<SocketAddress,? super A> handler);
+    public abstract <A> void receive(ByteBuffer dst,
+                                     long timeout,
+                                     TimeUnit unit,
+                                     A attachment,
+                                     CompletionHandler<SocketAddress,? super A> handler);
 
     /**
      * Receives a datagram via this channel.
      *
-     * <p> This method initiates the receiving of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The {@code Future}'s {@link Future#get() get} method returns
-     * the source address of the datagram upon successful completion.
+     * <p> This method initiates the receiving of a datagram into the given
+     * buffer. The {@code handler} parameter is a completion handler that is
+     * invoked when the receive operation completes (or fails). The result
+     * passed to the completion handler is the datagram's source address.
      *
      * <p> This method is equivalent to invoking {@link
      * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
@@ -382,34 +374,30 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the buffer is read-only
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public final <A> Future<SocketAddress> receive(ByteBuffer dst,
-                                                   A attachment,
-                                                   CompletionHandler<SocketAddress,? super A> handler)
+    public final <A> void receive(ByteBuffer dst,
+                                  A attachment,
+                                  CompletionHandler<SocketAddress,? super A> handler)
     {
-        return receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+        receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
     }
 
     /**
      * Receives a datagram via this channel.
      *
-     * <p> This method initiates the receiving of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The {@code Future}'s {@link Future#get() get} method returns
-     * the source address of the datagram upon successful completion.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
-     * timeout of {@code 0L}, and an attachment and completion handler
-     * of {@code null}.
+     * <p> This method initiates the receiving of a datagram into the given
+     * buffer. The method behaves in exactly the same manner as the {@link
+     * #receive(ByteBuffer,Object,CompletionHandler)
+     * receive(ByteBuffer,Object,CompletionHandler)} method except that instead
+     * of specifying a completion handler, this method returns a {@code Future}
+     * representing the pending result. The {@code Future}'s {@link Future#get()
+     * get} method returns the datagram's source address.
      *
      * @param   dst
      *          The buffer into which the datagram is to be transferred
@@ -419,84 +407,19 @@
      * @throws  IllegalArgumentException
      *          If the buffer is read-only
      */
-    public final <A> Future<SocketAddress> receive(ByteBuffer dst) {
-        return receive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
+    public abstract Future<SocketAddress> receive(ByteBuffer dst);
 
     /**
      * Sends a datagram via this channel.
      *
-     * <p> This method initiates sending of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The operation sends the remaining bytes in the given buffer as a single
-     * datagram to the given target address. The result of the operation, obtained
-     * by invoking the {@code Future}'s {@link Future#get() get}
-     * method, is the number of bytes sent.
+     * <p> This method initiates sending of a datagram from the given buffer to
+     * the given address. The {@code handler} parameter is a completion handler
+     * that is invoked when the send completes (or fails). The result passed to
+     * the completion handler is the number of bytes sent.
      *
-     * <p> The datagram is transferred from the byte buffer as if by a regular
-     * {@link AsynchronousByteChannel#write write} operation.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * <p> If there is a security manager installed and the channel is not
-     * connected then this method verifies that the target address and port number
-     * are permitted by the security manager's {@link SecurityManager#checkConnect
-     * checkConnect} method.  The overhead of this security check can be avoided
-     * by first connecting the socket via the {@link #connect connect} method.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative, or if the channel's socket is
-     *          connected to an address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
-     */
-    public abstract <A> Future<Integer> send(ByteBuffer src,
-                                             SocketAddress target,
-                                             long timeout,
-                                             TimeUnit unit,
-                                             A attachment,
-                                             CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The operation sends the remaining bytes in the given buffer as a single
-     * datagram to the given target address. The result of the operation, obtained
-     * by invoking the {@code Future}'s {@link Future#get() get}
-     * method, is the number of bytes sent.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
-     * with a timeout of {@code 0L}.
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+     * method.
      *
      * @param   src
      *          The buffer containing the datagram to be sent
@@ -505,9 +428,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  UnresolvedAddressException
      *          If the given remote address is not fully resolved
@@ -520,30 +441,23 @@
      *          If a security manager has been installed and it does not permit
      *          datagrams to be sent to the given address
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public final <A> Future<Integer> send(ByteBuffer src,
-                                          SocketAddress target,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
-    {
-        return send(src, target, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
+    public abstract <A> void send(ByteBuffer src,
+                                  SocketAddress target,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler);
 
     /**
      * Sends a datagram via this channel.
      *
-     * <p> This method initiates sending of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The operation sends the remaining bytes in the given buffer as a single
-     * datagram to the given target address. The result of the operation, obtained
-     * by invoking the {@code Future}'s {@link Future#get() get}
-     * method, is the number of bytes sent.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
-     * with a timeout of {@code 0L} and an attachment and completion handler
-     * of {@code null}.
+     * <p> This method initiates sending of a datagram from the given buffer to
+     * the given address. The method behaves in exactly the same manner as the
+     * {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
+     * send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
+     * that instead of specifying a completion handler, this method returns a
+     * {@code Future} representing the pending result. The {@code Future}'s
+     * {@link Future#get() get} method returns the number of bytes sent.
      *
      * @param   src
      *          The buffer containing the datagram to be sent
@@ -563,17 +477,15 @@
      *          If a security manager has been installed and it does not permit
      *          datagrams to be sent to the given address
      */
-    public final Future<Integer> send(ByteBuffer src, SocketAddress target) {
-        return send(src, target, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
+    public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
 
     /**
      * Receives a datagram via this channel.
      *
-     * <p> This method initiates the receiving of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The {@code Future}'s {@link Future#get() get} method returns
-     * the number of bytes transferred upon successful completion.
+     * <p> This method initiates the receiving of a datagram into the given
+     * buffer. The {@code handler} parameter is a completion handler that is
+     * invoked when the receive operation completes (or fails). The result
+     * passed to the completion handler is number of bytes read.
      *
      * <p> This method may only be invoked if this channel is connected, and it
      * only accepts datagrams from the peer that the channel is connected too.
@@ -599,120 +511,62 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the timeout is negative or buffer is read-only
      * @throws  NotYetConnectedException
      *          If this channel is not connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<Integer> read(ByteBuffer dst,
-                                             long timeout,
-                                             TimeUnit unit,
-                                             A attachment,
-                                             CompletionHandler<Integer,? super A> handler);
+    public abstract <A> void read(ByteBuffer dst,
+                                  long timeout,
+                                  TimeUnit unit,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler);
 
     /**
      * @throws  NotYetConnectedException
      *          If this channel is not connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
     @Override
-    public final <A> Future<Integer> read(ByteBuffer dst,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
+    public final <A> void read(ByteBuffer dst,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
     {
-        return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
     }
 
     /**
      * @throws  NotYetConnectedException
      *          If this channel is not connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
     @Override
-    public final Future<Integer> read(ByteBuffer dst) {
-        return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
-
-    /**
-     * Writes a datagram to this channel.
-     *
-     * <p> This method initiates sending of a datagram, returning a
-     * {@code Future} representing the pending result of the operation.
-     * The operation sends the remaining bytes in the given buffer as a single
-     * datagram. The result of the operation, obtained by invoking the
-     * {@code Future}'s {@link Future#get() get} method, is the
-     * number of bytes sent.
-     *
-     * <p> The datagram is transferred from the byte buffer as if by a regular
-     * {@link AsynchronousByteChannel#write write} operation.
-     *
-     * <p> This method may only be invoked if this channel is connected,
-     * in which case it sends datagrams directly to the socket's peer.  Otherwise
-     * it behaves exactly as specified in the {@link
-     * AsynchronousByteChannel} interface.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
-     */
-    public abstract <A> Future<Integer> write(ByteBuffer src,
-                                              long timeout,
-                                              TimeUnit unit,
-                                              A attachment,
-                                              CompletionHandler<Integer,? super A> handler);
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
-     */
-    @Override
-    public final <A> Future<Integer> write(ByteBuffer src,
-                                           A attachment,
-                                           CompletionHandler<Integer,? super A> handler)
-    {
-        return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
+    public abstract Future<Integer> read(ByteBuffer dst);
 
     /**
      * @throws  NotYetConnectedException
      *          If this channel is not connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
     @Override
-    public final Future<Integer> write(ByteBuffer src) {
-        return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
+    public abstract <A> void  write(ByteBuffer src,
+                                    A attachment,
+                                    CompletionHandler<Integer,? super A> handler);
+
+
+    /**
+     * @throws  NotYetConnectedException
+     *          If this channel is not connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    @Override
+    public abstract Future<Integer> write(ByteBuffer src);
 }
--- a/src/share/classes/java/nio/channels/AsynchronousFileChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousFileChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -48,7 +48,12 @@
  *
  * <p> An asynchronous file channel does not have a <i>current position</i>
  * within the file. Instead, the file position is specified to each read and
- * write operation.
+ * write methd that initiate asynchronous operations. A {@link CompletionHandler}
+ * is specified as a parameter and is invoked to consume the result of the I/O
+ * operation. This class also defines read and write methods that initiate
+ * asynchronous operations, returning a {@link Future} to represent the pending
+ * result of the operation. The {@code Future} may be used to check if the
+ * operation has completed, to wait for its completion.
  *
  * <p> In addition to read and write operations, this class defines the
  * following operations: </p>
@@ -59,18 +64,11 @@
  *   out</i>} to the underlying storage device, ensuring that data are not
  *   lost in the event of a system crash.  </p></li>
  *
- *   <li><p> A region of a file may be {@link FileLock <i>locked</i>}
- *   against access by other programs.  </p></li>
+ *   <li><p> A region of a file may be {@link #lock <i>locked</i>} against
+ *   access by other programs.  </p></li>
  *
  * </ul>
  *
- * <p> The {@link #read read}, {@link #write write}, and {@link #lock lock}
- * methods defined by this class are asynchronous  and return a {@link Future}
- * to represent the pending result of the operation. This may be used to check
- * if the operation has completed, to wait for its completion, and to retrieve
- * the result. These method may optionally specify a {@link CompletionHandler}
- * that is invoked to consume the result of the I/O operation when it completes.
- *
  * <p> An {@code AsynchronousFileChannel} is associated with a thread pool to
  * which tasks are submitted to handle I/O events and dispatch to completion
  * handlers that consume the results of I/O operations on the channel. The
@@ -123,22 +121,6 @@
     }
 
     /**
-     * Closes this channel.
-     *
-     * <p> If this channel is associated with its own thread pool then closing
-     * the channel causes the thread pool to shutdown after all actively
-     * executing completion handlers have completed. No attempt is made to stop
-     * or interrupt actively completion handlers.
-     *
-     * <p> This method otherwise behaves exactly as specified by the {@link
-     * AsynchronousChannel} interface.
-     *
-     * @throws  IOException     {@inheritDoc}
-     */
-    @Override
-    public abstract void close() throws IOException;
-
-    /**
      * Opens or creates a file for reading and/or writing, returning an
      * asynchronous file channel to access the file.
      *
@@ -215,9 +197,8 @@
      * should be taken when configuring the {@code Executor}. Minimally it
      * should support an unbounded work queue and should not run tasks on the
      * caller thread of the {@link ExecutorService#execute execute} method.
-     * {@link #close Closing} the channel results in the orderly {@link
-     * ExecutorService#shutdown shutdown} of the executor service. Shutting down
-     * the executor service by other means results in unspecified behavior.
+     * Shutting down the executor service while the channel is open results in
+     * unspecified behavior.
      *
      * <p> The {@code attrs} parameter is an optional array of file {@link
      * FileAttribute file-attributes} to set atomically when creating the file.
@@ -276,7 +257,8 @@
      * <p> An invocation of this method behaves in exactly the same way as the
      * invocation
      * <pre>
-     *     ch.{@link #open(Path,Set,ExecutorService,FileAttribute[]) open}(file, opts, null, new FileAttribute&lt;?&gt;[0]);
+     *     ch.{@link #open(Path,Set,ExecutorService,FileAttribute[])
+     *       open}(file, opts, null, new FileAttribute&lt;?&gt;[0]);
      * </pre>
      * where {@code opts} is a {@code Set} containing the options specified to
      * this method.
@@ -405,10 +387,11 @@
     /**
      * Acquires a lock on the given region of this channel's file.
      *
-     * <p> This method initiates an operation to acquire a lock on the given region
-     * of this channel's file. The method returns a {@code Future} representing
-     * the pending result of the operation. Its {@link Future#get() get}
-     * method returns the {@link FileLock} on successful completion.
+     * <p> This method initiates an operation to acquire a lock on the given
+     * region of this channel's file. The {@code handler} parameter is a
+     * completion handler that is invoked when the lock is acquired (or the
+     * operation fails). The result passed to the completion handler is the
+     * resulting {@code FileLock}.
      *
      * <p> The region specified by the {@code position} and {@code size}
      * parameters need not be contained within, or even overlap, the actual
@@ -455,9 +438,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  a {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  OverlappingFileLockException
      *          If a lock that overlaps the requested region is already held by
@@ -466,26 +447,24 @@
      * @throws  IllegalArgumentException
      *          If the preconditions on the parameters do not hold
      * @throws  NonReadableChannelException
-     *          If {@code shared} is true this channel but was not opened for reading
+     *          If {@code shared} is true but this channel was not opened for reading
      * @throws  NonWritableChannelException
      *          If {@code shared} is false but this channel was not opened for writing
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, the channel is closed, and the channel
-     *          was originally created with its own thread pool
      */
-    public abstract <A> Future<FileLock> lock(long position,
-                                              long size,
-                                              boolean shared,
-                                              A attachment,
-                                              CompletionHandler<FileLock,? super A> handler);
+    public abstract <A> void lock(long position,
+                                  long size,
+                                  boolean shared,
+                                  A attachment,
+                                  CompletionHandler<FileLock,? super A> handler);
 
     /**
      * Acquires an exclusive lock on this channel's file.
      *
-     * <p> This method initiates an operation to acquire an exclusive lock on this
-     * channel's file. The method returns a {@code Future} representing
-     * the pending result of the operation. Its {@link Future#get() get}
-     * method returns the {@link FileLock} on successful completion.
+     * <p> This method initiates an operation to acquire a lock on the given
+     * region of this channel's file. The {@code handler} parameter is a
+     * completion handler that is invoked when the lock is acquired (or the
+     * operation fails). The result passed to the completion handler is the
+     * resulting {@code FileLock}.
      *
      * <p> An invocation of this method of the form {@code ch.lock(att,handler)}
      * behaves in exactly the same way as the invocation
@@ -496,7 +475,70 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
+     *          The handler for consuming the result
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock is already held by this Java virtual machine, or there
+     *          is already a pending attempt to lock a region
+     * @throws  NonWritableChannelException
+     *          If this channel was not opened for writing
+     */
+    public final <A> void lock(A attachment,
+                               CompletionHandler<FileLock,? super A> handler)
+    {
+        lock(0L, Long.MAX_VALUE, false, attachment, handler);
+    }
+
+    /**
+     * Acquires a lock on the given region of this channel's file.
+     *
+     * <p> This method initiates an operation to acquire a lock on the given
+     * region of this channel's file.  The method behaves in exactly the same
+     * manner as the {@link #lock(long, long, boolean, Object, CompletionHandler)}
+     * method except that instead of specifying a completion handler, this
+     * method returns a {@code Future} representing the pending result. The
+     * {@code Future}'s {@link Future#get() get} method returns the {@link
+     * FileLock} on successful completion.
+     *
+     * @param   position
+     *          The position at which the locked region is to start; must be
+     *          non-negative
+     * @param   size
+     *          The size of the locked region; must be non-negative, and the sum
+     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
+     * @param   shared
+     *          {@code true} to request a shared lock, in which case this
+     *          channel must be open for reading (and possibly writing);
+     *          {@code false} to request an exclusive lock, in which case this
+     *          channel must be open for writing (and possibly reading)
+     *
+     * @return  a {@code Future} object representing the pending result
+     *
+     * @throws  OverlappingFileLockException
+     *          If a lock is already held by this Java virtual machine, or there
+     *          is already a pending attempt to lock a region
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     * @throws  NonReadableChannelException
+     *          If {@code shared} is true but this channel was not opened for reading
+     * @throws  NonWritableChannelException
+     *          If {@code shared} is false but this channel was not opened for writing
+     */
+    public abstract Future<FileLock> lock(long position, long size, boolean shared);
+
+    /**
+     * Acquires an exclusive lock on this channel's file.
+     *
+     * <p> This method initiates an operation to acquire an exclusive lock on this
+     * channel's file. The method returns a {@code Future} representing the
+     * pending result of the operation. The {@code Future}'s {@link Future#get()
+     * get} method returns the {@link FileLock} on successful completion.
+     *
+     * <p> An invocation of this method behaves in exactly the same way as the
+     * invocation
+     * <pre>
+     *     ch.{@link #lock(long,long,boolean) lock}(0L, Long.MAX_VALUE, false)
+     * </pre>
      *
      * @return  a {@code Future} object representing the pending result
      *
@@ -505,40 +547,9 @@
      *          is already a pending attempt to lock a region
      * @throws  NonWritableChannelException
      *          If this channel was not opened for writing
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, the channel is closed, and the channel
-     *          was originally created with its own thread pool
-     */
-    public final <A> Future<FileLock> lock(A attachment,
-                                           CompletionHandler<FileLock,? super A> handler)
-    {
-        return lock(0L, Long.MAX_VALUE, false, attachment, handler);
-    }
-
-    /**
-     * Acquires an exclusive lock on this channel's file.
-     *
-     * <p> This method initiates an operation to acquire an exclusive lock on this
-     * channel's file. The method returns a {@code Future} representing the
-     * pending result of the operation. Its {@link Future#get() get} method
-     * returns the {@link FileLock} on successful completion.
-     *
-     * <p> An invocation of this method behaves in exactly the same way as the
-     * invocation
-     * <pre>
-     *     ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, null, null)
-     * </pre>
-     *
-     * @return  A {@code Future} object representing the pending result
-     *
-     * @throws  OverlappingFileLockException
-     *          If a lock is already held by this Java virtual machine, or there
-     *          is already a pending attempt to lock a region
-     * @throws  NonWritableChannelException
-     *          If this channel was not opened for writing
      */
     public final Future<FileLock> lock() {
-        return lock(0L, Long.MAX_VALUE, false, null, null);
+        return lock(0L, Long.MAX_VALUE, false);
     }
 
     /**
@@ -576,7 +587,7 @@
      *          blocked in this method and is attempting to lock an overlapping
      *          region of the same file
      * @throws  NonReadableChannelException
-     *          If {@code shared} is true this channel but was not opened for reading
+     *          If {@code shared} is true but this channel was not opened for reading
      * @throws  NonWritableChannelException
      *          If {@code shared} is false but this channel was not opened for writing
      *
@@ -629,11 +640,10 @@
      * starting at the given file position.
      *
      * <p> This method initiates the reading of a sequence of bytes from this
-     * channel into the given buffer, starting at the given file position. This
-     * method returns a {@code Future} representing the pending result of the
-     * operation. The Future's {@link Future#get() get} method returns the
-     * number of bytes read or {@code -1} if the given position is greater than
-     * or equal to the file's size at the time that the read is attempted.
+     * channel into the given buffer, starting at the given file position. The
+     * result of the read is the number of bytes read or {@code -1} if the given
+     * position is greater than or equal to the file's size at the time that the
+     * read is attempted.
      *
      * <p> This method works in the same manner as the {@link
      * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
@@ -649,22 +659,17 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the position is negative or the buffer is read-only
      * @throws  NonReadableChannelException
      *          If this channel was not opened for reading
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, the channel is closed, and the channel
-     *          was originally created with its own thread pool
      */
-    public abstract <A> Future<Integer> read(ByteBuffer dst,
-                                             long position,
-                                             A attachment,
-                                             CompletionHandler<Integer,? super A> handler);
+    public abstract <A> void read(ByteBuffer dst,
+                                  long position,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler);
 
     /**
      * Reads a sequence of bytes from this channel into the given buffer,
@@ -673,13 +678,15 @@
      * <p> This method initiates the reading of a sequence of bytes from this
      * channel into the given buffer, starting at the given file position. This
      * method returns a {@code Future} representing the pending result of the
-     * operation. The Future's {@link Future#get() get} method returns the
-     * number of bytes read or {@code -1} if the given position is greater
+     * operation. The {@code Future}'s {@link Future#get() get} method returns
+     * the number of bytes read or {@code -1} if the given position is greater
      * than or equal to the file's size at the time that the read is attempted.
      *
-     * <p> This method is equivalent to invoking {@link
-     * #read(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
-     * and handler parameters set to {@code null}.
+     * <p> This method works in the same manner as the {@link
+     * AsynchronousByteChannel#read(ByteBuffer)} method, except that bytes are
+     * read starting at the given file position. If the given file position is
+     * greater than the file's size at the time that the read is attempted then
+     * no bytes are read.
      *
      * @param   dst
      *          The buffer into which bytes are to be transferred
@@ -694,20 +701,12 @@
      * @throws  NonReadableChannelException
      *          If this channel was not opened for reading
      */
-    public final Future<Integer> read(ByteBuffer dst, long position) {
-        return read(dst, position, null, null);
-    }
+    public abstract Future<Integer> read(ByteBuffer dst, long position);
 
     /**
      * Writes a sequence of bytes to this channel from the given buffer, starting
      * at the given file position.
      *
-     * <p> This method initiates the writing of a sequence of bytes to this channel
-     * from the given buffer, starting at the given file position. The method
-     * returns a {@code Future} representing the pending result of the write
-     * operation. The Future's {@link Future#get() get} method returns the
-     * number of bytes written.
-     *
      * <p> This method works in the same manner as the {@link
      * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
      * method, except that bytes are written starting at the given file position.
@@ -724,36 +723,35 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the position is negative
      * @throws  NonWritableChannelException
      *          If this channel was not opened for writing
-     * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, the channel is closed, and the channel
-     *          was originally created with its own thread pool
      */
-    public abstract <A> Future<Integer> write(ByteBuffer src,
-                                              long position,
-                                              A attachment,
-                                              CompletionHandler<Integer,? super A> handler);
+    public abstract <A> void write(ByteBuffer src,
+                                   long position,
+                                   A attachment,
+                                   CompletionHandler<Integer,? super A> handler);
 
     /**
      * Writes a sequence of bytes to this channel from the given buffer, starting
      * at the given file position.
      *
-     * <p> This method initiates the writing of a sequence of bytes to this channel
-     * from the given buffer, starting at the given file position. The method
-     * returns a {@code Future} representing the pending result of the write
-     * operation. The Future's {@link Future#get() get} method returns the
-     * number of bytes written.
+     * <p> This method initiates the writing of a sequence of bytes to this
+     * channel from the given buffer, starting at the given file position. The
+     * method returns a {@code Future} representing the pending result of the
+     * write operation. The {@code Future}'s {@link Future#get() get} method
+     * returns the number of bytes written.
      *
-     * <p> This method is equivalent to invoking {@link
-     * #write(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
-     * and handler parameters set to {@code null}.
+     * <p> This method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer)} method, except that bytes are
+     * written starting at the given file position. If the given position is
+     * greater than the file's size, at the time that the write is attempted,
+     * then the file will be grown to accommodate the new bytes; the values of
+     * any bytes between the previous end-of-file and the newly-written bytes
+     * are unspecified.
      *
      * @param   src
      *          The buffer from which bytes are to be transferred
@@ -768,7 +766,5 @@
      * @throws  NonWritableChannelException
      *          If this channel was not opened for writing
      */
-    public final Future<Integer> write(ByteBuffer src, long position) {
-        return write(src, position, null, null);
-    }
+    public abstract Future<Integer> write(ByteBuffer src, long position);
 }
--- a/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -85,9 +85,6 @@
  *      public void failed(Throwable exc, Void att) {
  *          ...
  *      }
- *      public void cancelled(Void att) {
- *          ...
- *      }
  *  });
  * </pre>
  *
@@ -240,11 +237,11 @@
     /**
      * Accepts a connection.
      *
-     * <p> This method initiates accepting a connection made to this channel's
-     * socket, returning a {@link Future} representing the pending result
-     * of the operation. The {@code Future}'s {@link Future#get() get}
-     * method will return the {@link AsynchronousSocketChannel} for the new
-     * connection on successful completion.
+     * <p> This method initiates an asynchronous operation to accept a
+     * connection made to this channel's socket. The {@code handler} parameter is
+     * a completion handler that is invoked when a connection is accepted (or
+     * the operation fails). The result passed to the completion handler is
+     * the {@link AsynchronousSocketChannel} to the new connection.
      *
      * <p> When a new connection is accepted then the resulting {@code
      * AsynchronousSocketChannel} will be bound to the same {@link
@@ -269,35 +266,35 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  an <tt>Future</tt> object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  AcceptPendingException
      *          If an accept operation is already in progress on this channel
      * @throws  NotYetBoundException
      *          If this channel's socket has not yet been bound
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<AsynchronousSocketChannel>
-        accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
+    public abstract <A> void accept(A attachment,
+                                    CompletionHandler<AsynchronousSocketChannel,? super A> handler);
 
     /**
      * Accepts a connection.
      *
-     * <p> This method is equivalent to invoking {@link
-     * #accept(Object,CompletionHandler)} with the {@code attachment}
-     * and {@code handler} parameters set to {@code null}.
+     * <p> This method initiates an asynchronous operation to accept a
+     * connection made to this channel's socket. The method behaves in exactly
+     * the same manner as the {@link #accept(Object, CompletionHandler)} method
+     * except that instead of specifying a completion handler, this method
+     * returns a {@code Future} representing the pending result. The {@code
+     * Future}'s {@link Future#get() get} method returns the {@link
+     * AsynchronousSocketChannel} to the new connection on successful completion.
      *
-     * @return  an <tt>Future</tt> object representing the pending result
+     * @return  a {@code Future} object representing the pending result
      *
      * @throws  AcceptPendingException
      *          If an accept operation is already in progress on this channel
      * @throws  NotYetBoundException
      *          If this channel's socket has not yet been bound
      */
-    public final Future<AsynchronousSocketChannel> accept() {
-        return accept(null, null);
-    }
+    public abstract Future<AsynchronousSocketChannel> accept();
 }
--- a/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -274,14 +274,11 @@
     /**
      * Connects this channel.
      *
-     * <p> This method initiates an operation to connect this channel, returning
-     * a {@code Future} representing the pending result of the operation. If
-     * the connection is successfully established then the {@code Future}'s
-     * {@link Future#get() get} method will return {@code null}. If the
-     * connection cannot be established then the channel is closed. In that case,
-     * invoking the {@code get} method throws {@link
-     * java.util.concurrent.ExecutionException} with an {@code IOException} as
-     * the cause.
+     * <p> This method initiates an operation to connect this channel. The
+     * {@code handler} parameter is a completion handler that is invoked when
+     * the connection is successfully established or connection cannot be
+     * established. If the connection cannot be established then the channel is
+     * closed.
      *
      * <p> This method performs exactly the same security checks as the {@link
      * java.net.Socket} class.  That is, if a security manager has been
@@ -294,9 +291,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  UnresolvedAddressException
      *          If the given remote address is not fully resolved
@@ -307,23 +302,26 @@
      * @throws  ConnectionPendingException
      *          If a connection operation is already in progress on this channel
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      * @throws  SecurityException
      *          If a security manager has been installed
      *          and it does not permit access to the given remote endpoint
      *
      * @see #getRemoteAddress
      */
-    public abstract <A> Future<Void> connect(SocketAddress remote,
-                                             A attachment,
-                                             CompletionHandler<Void,? super A> handler);
+    public abstract <A> void connect(SocketAddress remote,
+                                     A attachment,
+                                     CompletionHandler<Void,? super A> handler);
 
     /**
      * Connects this channel.
      *
-     * <p> This method is equivalent to invoking {@link
-     * #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
-     * and handler parameters set to {@code null}.
+     * <p> This method initiates an operation to connect this channel. This
+     * method behaves in exactly the same manner as the {@link
+     * #connect(SocketAddress, Object, CompletionHandler)} method except that
+     * instead of specifying a completion handler, this method returns a {@code
+     * Future} representing the pending result. The {@code Future}'s {@link
+     * Future#get() get} method returns {@code null} on successful completion.
      *
      * @param   remote
      *          The remote address to which this channel is to be connected
@@ -342,18 +340,17 @@
      *          If a security manager has been installed
      *          and it does not permit access to the given remote endpoint
      */
-    public final Future<Void> connect(SocketAddress remote) {
-        return connect(remote, null, null);
-    }
+    public abstract Future<Void> connect(SocketAddress remote);
 
     /**
      * Reads a sequence of bytes from this channel into the given buffer.
      *
-     * <p> This method initiates the reading of a sequence of bytes from this
-     * channel into the given buffer, returning a {@code Future} representing
-     * the pending result of the operation. The {@code Future}'s {@link
-     * Future#get() get} method returns the number of bytes read or {@code -1}
-     * if all bytes have been read and channel has reached end-of-stream.
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the read
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes read or {@code -1} if no bytes could be
+     * read because the channel has reached end-of-stream.
      *
      * <p> If a timeout is specified and the timeout elapses before the operation
      * completes then the operation completes with the exception {@link
@@ -376,9 +373,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the {@code timeout} parameter is negative or the buffer is
@@ -388,13 +383,13 @@
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<Integer> read(ByteBuffer dst,
-                                             long timeout,
-                                             TimeUnit unit,
-                                             A attachment,
-                                             CompletionHandler<Integer,? super A> handler);
+    public abstract <A> void read(ByteBuffer dst,
+                                  long timeout,
+                                  TimeUnit unit,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler);
 
     /**
      * @throws  IllegalArgumentException        {@inheritDoc}
@@ -402,14 +397,14 @@
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
     @Override
-    public final <A> Future<Integer> read(ByteBuffer dst,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
+    public final <A> void read(ByteBuffer dst,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
     {
-        return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
     }
 
     /**
@@ -419,16 +414,18 @@
      *          If this channel is not yet connected
      */
     @Override
-    public final Future<Integer> read(ByteBuffer dst) {
-        return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
+    public abstract Future<Integer> read(ByteBuffer dst);
 
     /**
      * Reads a sequence of bytes from this channel into a subsequence of the
      * given buffers. This operation, sometimes called a <em>scattering read</em>,
      * is often useful when implementing network protocols that group data into
      * segments consisting of one or more fixed-length headers followed by a
-     * variable-length body.
+     * variable-length body. The {@code handler} parameter is a completion
+     * handler that is invoked when the read operation completes (or fails). The
+     * result passed to the completion handler is the number of bytes read or
+     * {@code -1} if no bytes could be read because the channel has reached
+     * end-of-stream.
      *
      * <p> This method initiates a read of up to <i>r</i> bytes from this channel,
      * where <i>r</i> is the total number of bytes remaining in the specified
@@ -456,11 +453,6 @@
      * I/O operation is performed with the maximum number of buffers allowed by
      * the operating system.
      *
-     * <p> The return value from this method is a {@code Future} representing
-     * the pending result of the operation. The {@code Future}'s {@link
-     * Future#get() get} method returns the number of bytes read or {@code -1L}
-     * if all bytes have been read and the channel has reached end-of-stream.
-     *
      * <p> If a timeout is specified and the timeout elapses before the operation
      * completes then it completes with the exception {@link
      * InterruptedByTimeoutException}. Where a timeout occurs, and the
@@ -485,9 +477,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IndexOutOfBoundsException
      *          If the pre-conditions for the {@code offset}  and {@code length}
@@ -500,23 +490,24 @@
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<Long> read(ByteBuffer[] dsts,
-                                          int offset,
-                                          int length,
-                                          long timeout,
-                                          TimeUnit unit,
-                                          A attachment,
-                                          CompletionHandler<Long,? super A> handler);
+    public abstract <A> void read(ByteBuffer[] dsts,
+                                  int offset,
+                                  int length,
+                                  long timeout,
+                                  TimeUnit unit,
+                                  A attachment,
+                                  CompletionHandler<Long,? super A> handler);
 
     /**
      * Writes a sequence of bytes to this channel from the given buffer.
      *
-     * <p> This method initiates the writing of a sequence of bytes to this channel
-     * from the given buffer, returning a {@code Future} representing the
-     * pending result of the operation. The {@code Future}'s {@link Future#get()
-     * get} method will return the number of bytes written.
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the write
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes written.
      *
      * <p> If a timeout is specified and the timeout elapses before the operation
      * completes then it completes with the exception {@link
@@ -539,9 +530,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IllegalArgumentException
      *          If the {@code timeout} parameter is negative
@@ -550,28 +539,28 @@
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<Integer> write(ByteBuffer src,
-                                              long timeout,
-                                              TimeUnit unit,
-                                              A attachment,
-                                              CompletionHandler<Integer,? super A> handler);
+    public abstract <A> void write(ByteBuffer src,
+                                   long timeout,
+                                   TimeUnit unit,
+                                   A attachment,
+                                   CompletionHandler<Integer,? super A> handler);
 
     /**
      * @throws  WritePendingException          {@inheritDoc}
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
     @Override
-    public final <A> Future<Integer> write(ByteBuffer src,
-                                           A attachment,
-                                           CompletionHandler<Integer,? super A> handler)
+    public final <A> void write(ByteBuffer src,
+                                A attachment,
+                                CompletionHandler<Integer,? super A> handler)
 
     {
-        return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+        write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
     }
 
     /**
@@ -580,16 +569,16 @@
      *          If this channel is not yet connected
      */
     @Override
-    public final Future<Integer> write(ByteBuffer src) {
-        return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
+    public abstract Future<Integer> write(ByteBuffer src);
 
     /**
      * Writes a sequence of bytes to this channel from a subsequence of the given
      * buffers. This operation, sometimes called a <em>gathering write</em>, is
      * often useful when implementing network protocols that group data into
      * segments consisting of one or more fixed-length headers followed by a
-     * variable-length body.
+     * variable-length body. The {@code handler} parameter is a completion
+     * handler that is invoked when the write operation completes (or fails).
+     * The result passed to the completion handler is the number of bytes written.
      *
      * <p> This method initiates a write of up to <i>r</i> bytes to this channel,
      * where <i>r</i> is the total number of bytes remaining in the specified
@@ -616,10 +605,6 @@
      * remaining), exceeds this limit, then the I/O operation is performed with
      * the maximum number of buffers allowed by the operating system.
      *
-     * <p> The return value from this method is a {@code Future} representing
-     * the pending result of the operation. The {@code Future}'s {@link
-     * Future#get() get} method will return the number of bytes written.
-     *
      * <p> If a timeout is specified and the timeout elapses before the operation
      * completes then it completes with the exception {@link
      * InterruptedByTimeoutException}. Where a timeout occurs, and the
@@ -644,9 +629,7 @@
      * @param   attachment
      *          The object to attach to the I/O operation; can be {@code null}
      * @param   handler
-     *          The handler for consuming the result; can be {@code null}
-     *
-     * @return  A {@code Future} object representing the pending result
+     *          The handler for consuming the result
      *
      * @throws  IndexOutOfBoundsException
      *          If the pre-conditions for the {@code offset}  and {@code length}
@@ -658,13 +641,13 @@
      * @throws  NotYetConnectedException
      *          If this channel is not yet connected
      * @throws  ShutdownChannelGroupException
-     *          If a handler is specified, and the channel group is shutdown
+     *          If the channel group has terminated
      */
-    public abstract <A> Future<Long> write(ByteBuffer[] srcs,
-                                           int offset,
-                                           int length,
-                                           long timeout,
-                                           TimeUnit unit,
-                                           A attachment,
-                                           CompletionHandler<Long,? super A> handler);
+    public abstract <A> void write(ByteBuffer[] srcs,
+                                   int offset,
+                                   int length,
+                                   long timeout,
+                                   TimeUnit unit,
+                                   A attachment,
+                                   CompletionHandler<Long,? super A> handler);
 }
--- a/src/share/classes/java/nio/channels/Channels.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/Channels.java	Tue Sep 01 13:03:09 2009 -0700
@@ -182,7 +182,6 @@
     }
 
     /**
-     * {@note new}
      * Constructs a stream that reads bytes from the given channel.
      *
      * <p> The stream will not be buffered, and it will not support the {@link
@@ -258,7 +257,6 @@
     }
 
     /**
-     * {@note new}
      * Constructs a stream that writes bytes to the given channel.
      *
      * <p> The stream will not be buffered. The stream will be safe for access
--- a/src/share/classes/java/nio/channels/CompletionHandler.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/CompletionHandler.java	Tue Sep 01 13:03:09 2009 -0700
@@ -32,11 +32,9 @@
  * handler to be specified to consume the result of an asynchronous operation.
  * The {@link #completed completed} method is invoked when the I/O operation
  * completes successfully. The {@link #failed failed} method is invoked if the
- * I/O operations fails. The {@link #cancelled cancelled} method is invoked when
- * the I/O operation is cancelled by invoking the {@link
- * java.util.concurrent.Future#cancel cancel} method. The implementations of
- * these methods should complete in a timely manner so as to avoid keeping the
- * invoking thread from dispatching to other completion handlers.
+ * I/O operations fails. The implementations of these methods should complete
+ * in a timely manner so as to avoid keeping the invoking thread from dispatching
+ * to other completion handlers.
  *
  * @param   <V>     The result type of the I/O operation
  * @param   <A>     The type of the object attached to the I/O operation
@@ -65,13 +63,4 @@
      *          The object attached to the I/O operation when it was initiated.
      */
     void failed(Throwable exc, A attachment);
-
-    /**
-     * Invoked when an operation is cancelled by invoking the {@link
-     * java.util.concurrent.Future#cancel cancel} method.
-     *
-     * @param   attachment
-     *          The object attached to the I/O operation when it was initiated.
-     */
-    void cancelled(A attachment);
 }
--- a/src/share/classes/java/nio/channels/FileChannel.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/FileChannel.java	Tue Sep 01 13:03:09 2009 -0700
@@ -39,8 +39,7 @@
 /**
  * A channel for reading, writing, mapping, and manipulating a file.
  *
- * <p> {@note revised}
- * A file channel is a {@link SeekableByteChannel} that is connected to
+ * <p> A file channel is a {@link SeekableByteChannel} that is connected to
  * a file. It has a current <i>position</i> within its file which can
  * be both {@link #position() <i>queried</i>} and {@link #position(long)
  * <i>modified</i>}.  The file itself contains a variable-length sequence
@@ -151,7 +150,6 @@
  * @author Mike McCloskey
  * @author JSR-51 Expert Group
  * @since 1.4
- * @updated 1.7
  */
 
 public abstract class FileChannel
@@ -164,7 +162,6 @@
     protected FileChannel() { }
 
     /**
-     * {@note new}
      * Opens or creates a file, returning a file channel to access the file.
      *
      * <p> The {@code options} parameter determines how the file is opened.
@@ -293,7 +290,6 @@
     private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
 
     /**
-     * {@note new}
      * Opens or creates a file, returning a file channel to access the file.
      *
      * <p> An invocation of this method behaves in exactly the same way as the
--- a/src/share/classes/java/nio/channels/FileLock.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/FileLock.java	Tue Sep 01 13:03:09 2009 -0700
@@ -114,7 +114,6 @@
  * @author Mark Reinhold
  * @author JSR-51 Expert Group
  * @since 1.4
- * @updated 1.7
  */
 
 public abstract class FileLock {
@@ -161,7 +160,7 @@
     }
 
     /**
-     * {@note new} Initializes a new instance of this class.
+     * Initializes a new instance of this class.
      *
      * @param  channel
      *         The channel upon whose file this lock is held
@@ -199,7 +198,6 @@
     }
 
     /**
-     * {@note revised}
      * Returns the file channel upon whose file this lock was acquired.
      *
      * <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
@@ -213,7 +211,6 @@
     }
 
     /**
-     * {@note new}
      * Returns the channel upon whose file this lock was acquired.
      *
      * @return  The channel upon whose file this lock was acquired.
--- a/src/share/classes/java/nio/channels/exceptions	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/exceptions	Tue Sep 01 13:03:09 2009 -0700
@@ -190,5 +190,5 @@
 gen ShutdownChannelGroupException "
  * Unchecked exception thrown when an attempt is made to construct a channel in 
  * a group that is shutdown or the completion handler for an I/O operation 
- * cannot be invoked because the channel group is shutdown." \
+ * cannot be invoked because the channel group has terminated." \
  -3903801676350154157L
--- a/src/share/classes/java/nio/channels/package-info.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/channels/package-info.java	Tue Sep 01 13:03:09 2009 -0700
@@ -285,7 +285,6 @@
  * java.lang.NullPointerException NullPointerException} to be thrown.
  *
  * @since 1.4
- * @updated 1.7
  * @author Mark Reinhold
  * @author JSR-51 Expert Group
  */
--- a/src/share/classes/java/nio/file/FileRef.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/nio/file/FileRef.java	Tue Sep 01 13:03:09 2009 -0700
@@ -39,8 +39,6 @@
  * metadata or file attributes.
  *
  * @since 1.7
- * @see java.io.Inputs
- * @see java.io.Outputs
  * @see java.nio.file.attribute.Attributes
  * @see java.io.File#toPath
  */
--- a/src/share/classes/java/util/Scanner.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/java/util/Scanner.java	Tue Sep 01 13:03:09 2009 -0700
@@ -674,7 +674,6 @@
     }
 
     /**
-     * {@note new}
      * Constructs a new <code>Scanner</code> that produces values scanned
      * from the specified file. Bytes from the file are converted into
      * characters using the underlying platform's
@@ -694,7 +693,6 @@
     }
 
     /**
-     * {@note new}
      * Constructs a new <code>Scanner</code> that produces values scanned
      * from the specified file. Bytes from the file are converted into
      * characters using the specified charset.
--- a/src/share/classes/sun/nio/ch/AbstractFuture.java	Mon Aug 24 17:26:09 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.nio.ch;
-
-import java.nio.channels.AsynchronousChannel;
-import java.util.concurrent.Future;
-
-/**
- * Base implementation of Future used for asynchronous I/O
- */
-
-abstract class AbstractFuture<V,A>
-    implements Future<V>
-{
-    private final AsynchronousChannel channel;
-    private final A attachment;
-
-    protected AbstractFuture(AsynchronousChannel channel, A attachment) {
-        this.channel = channel;
-        this.attachment = attachment;
-    }
-
-    final AsynchronousChannel channel() {
-        return channel;
-    }
-
-    final A attachment() {
-        return attachment;
-    }
-
-    /**
-     * Returns the result of the operation if it has completed successfully.
-     */
-    abstract V value();
-
-    /**
-     * Returns the exception if the operation has failed.
-     */
-    abstract Throwable exception();
-}
--- a/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -32,8 +32,8 @@
 import java.io.FileDescriptor;
 import java.util.Queue;
 import java.util.concurrent.*;
-import java.util.concurrent.locks.*;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.security.PrivilegedAction;
 import java.security.AccessController;
 import java.security.AccessControlContext;
@@ -65,11 +65,8 @@
     private final Queue<Runnable> taskQueue;
 
     // group shutdown
-    // shutdownLock is RW lock so as to allow for concurrent queuing of tasks
-    // when using a fixed thread pool.
-    private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
+    private final AtomicBoolean shutdown = new AtomicBoolean();
     private final Object shutdownNowLock = new Object();
-    private volatile boolean shutdown;
     private volatile boolean terminateInitiated;
 
     AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
@@ -214,7 +211,7 @@
 
     @Override
     public final boolean isShutdown() {
-        return shutdown;
+        return shutdown.get();
     }
 
     @Override
@@ -260,17 +257,10 @@
 
     @Override
     public final void shutdown() {
-        shutdownLock.writeLock().lock();
-        try {
-            if (shutdown) {
-                // already shutdown
-                return;
-            }
-            shutdown = true;
-        } finally {
-            shutdownLock.writeLock().unlock();
+        if (shutdown.getAndSet(true)) {
+            // already shutdown
+            return;
         }
-
         // if there are channels in the group then shutdown will continue
         // when the last channel is closed
         if (!isEmpty()) {
@@ -289,12 +279,7 @@
 
     @Override
     public final void shutdownNow() throws IOException {
-        shutdownLock.writeLock().lock();
-        try {
-            shutdown = true;
-        } finally {
-            shutdownLock.writeLock().unlock();
-        }
+        shutdown.set(true);
         synchronized (shutdownNowLock) {
             if (!terminateInitiated) {
                 terminateInitiated = true;
@@ -305,6 +290,18 @@
         }
     }
 
+    /**
+     * For use by AsynchronousFileChannel to release resources without shutting
+     * down the thread pool.
+     */
+    final void detachFromThreadPool() {
+        if (shutdown.getAndSet(true))
+            throw new AssertionError("Already shutdown");
+        if (!isEmpty())
+            throw new AssertionError("Group not empty");
+        shutdownHandlerTasks();
+    }
+
     @Override
     public final boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException
--- a/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -25,8 +25,10 @@
 
 package sun.nio.ch;
 
+import java.nio.ByteBuffer;
 import java.nio.channels.*;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 import java.util.concurrent.locks.*;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -101,6 +103,33 @@
 
     // -- file locking --
 
+    abstract <A> Future<FileLock> implLock(long position,
+                                           long size,
+                                           boolean shared,
+                                           A attachment,
+                                           CompletionHandler<FileLock,? super A> handler);
+
+    @Override
+    public final Future<FileLock> lock(long position,
+                                       long size,
+                                       boolean shared)
+
+    {
+        return implLock(position, size, shared, null, null);
+    }
+
+    @Override
+    public final <A> void lock(long position,
+                               long size,
+                               boolean shared,
+                               A attachment,
+                               CompletionHandler<FileLock,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implLock(position, size, shared, attachment, handler);
+    }
+
     private volatile FileLockTable fileLockTable;
 
     final void ensureFileLockTableInitialized() throws IOException {
@@ -175,4 +204,50 @@
             end();
         }
     }
+
+
+    // -- reading and writing --
+
+    abstract <A> Future<Integer> implRead(ByteBuffer dst,
+                                         long position,
+                                         A attachment,
+                                         CompletionHandler<Integer,? super A> handler);
+
+    @Override
+    public final Future<Integer> read(ByteBuffer dst, long position) {
+        return implRead(dst, position, null, null);
+    }
+
+    @Override
+    public final <A> void read(ByteBuffer dst,
+                               long position,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implRead(dst, position, attachment, handler);
+    }
+
+    abstract <A> Future<Integer> implWrite(ByteBuffer src,
+                                           long position,
+                                           A attachment,
+                                           CompletionHandler<Integer,? super A> handler);
+
+
+    @Override
+    public final Future<Integer> write(ByteBuffer src, long position) {
+        return implWrite(src, position, null, null);
+    }
+
+    @Override
+    public final <A> void write(ByteBuffer src,
+                                long position,
+                                A attachment,
+                                CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implWrite(src, position, attachment, handler);
+    }
 }
--- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -35,6 +35,7 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
+import java.util.concurrent.Future;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import sun.net.NetHooks;
@@ -108,6 +109,29 @@
         implClose();
     }
 
+    /**
+     * Invoked by accept to accept connection
+     */
+    abstract Future<AsynchronousSocketChannel>
+        implAccept(Object attachment,
+                   CompletionHandler<AsynchronousSocketChannel,Object> handler);
+
+
+    @Override
+    public final Future<AsynchronousSocketChannel> accept() {
+        return implAccept(null, null);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <A> void accept(A attachment,
+                                 CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);
+    }
+
     final boolean isAcceptKilled() {
         return acceptKilled;
     }
--- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -184,28 +184,53 @@
     }
 
     /**
+     * Invoked by connect to initiate the connect operation.
+     */
+    abstract <A> Future<Void> implConnect(SocketAddress remote,
+                                          A attachment,
+                                          CompletionHandler<Void,? super A> handler);
+
+    @Override
+    public final Future<Void> connect(SocketAddress remote) {
+        return implConnect(remote, null, null);
+    }
+
+    @Override
+    public final <A> void connect(SocketAddress remote,
+                                  A attachment,
+                                  CompletionHandler<Void,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implConnect(remote, attachment, handler);
+    }
+
+    /**
      * Invoked by read to initiate the I/O operation.
      */
-    abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
-                                                     boolean isScatteringRead,
+    abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+                                                     ByteBuffer dst,
+                                                     ByteBuffer[] dsts,
                                                      long timeout,
                                                      TimeUnit unit,
                                                      A attachment,
                                                      CompletionHandler<V,? super A> handler);
 
     @SuppressWarnings("unchecked")
-    private <V extends Number,A> Future<V> read(ByteBuffer[] dsts,
-                                                boolean isScatteringRead,
+    private <V extends Number,A> Future<V> read(boolean isScatteringRead,
+                                                ByteBuffer dst,
+                                                ByteBuffer[] dsts,
                                                 long timeout,
                                                 TimeUnit unit,
-                                                A attachment,
+                                                A att,
                                                 CompletionHandler<V,? super A> handler)
     {
         if (!isOpen()) {
-            CompletedFuture<V,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable e = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(e);
+            Invoker.invoke(this, handler, att, null, e);
+            return null;
         }
 
         if (remoteAddress == null)
@@ -213,13 +238,13 @@
         if (timeout < 0L)
             throw new IllegalArgumentException("Negative timeout");
 
-        boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining();
+        boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
         boolean shutdown = false;
 
         // check and update state
         synchronized (readLock) {
             if (readKilled)
-                throw new RuntimeException("Reading not allowed due to timeout or cancellation");
+                throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
             if (reading)
                 throw new ReadPendingException();
             if (readShutdown) {
@@ -234,44 +259,53 @@
         // immediately complete with -1 if shutdown for read
         // immediately complete with 0 if no space remaining
         if (shutdown || !hasSpaceToRead) {
-            CompletedFuture<V,A> result;
+            Number result;
             if (isScatteringRead) {
-                Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
-                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+                result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
             } else {
-                int value = (shutdown) ? -1 : 0;
-                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+                result = (shutdown) ? -1 : 0;
             }
-            Invoker.invoke(handler, result);
-            return result;
+            if (handler == null)
+                return CompletedFuture.withResult((V)result);
+            Invoker.invoke(this, handler, att, (V)result, null);
+            return null;
         }
 
-        return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler);
+        return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
     }
 
     @Override
-    public final <A> Future<Integer> read(ByteBuffer dst,
-                                          long timeout,
-                                          TimeUnit unit,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
-    {
+    public final Future<Integer> read(ByteBuffer dst) {
         if (dst.isReadOnly())
             throw new IllegalArgumentException("Read-only buffer");
-        ByteBuffer[] bufs = new ByteBuffer[1];
-        bufs[0] = dst;
-        return read(bufs, false, timeout, unit, attachment, handler);
+        return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
     }
 
     @Override
-    public final <A> Future<Long> read(ByteBuffer[] dsts,
-                                       int offset,
-                                       int length,
-                                       long timeout,
-                                       TimeUnit unit,
-                                       A attachment,
-                                       CompletionHandler<Long,? super A> handler)
+    public final <A> void read(ByteBuffer dst,
+                               long timeout,
+                               TimeUnit unit,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
     {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        read(false, dst, null, timeout, unit, attachment, handler);
+    }
+
+    @Override
+    public final <A> void read(ByteBuffer[] dsts,
+                               int offset,
+                               int length,
+                               long timeout,
+                               TimeUnit unit,
+                               A attachment,
+                               CompletionHandler<Long,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
             throw new IndexOutOfBoundsException();
         ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
@@ -279,39 +313,41 @@
             if (bufs[i].isReadOnly())
                 throw new IllegalArgumentException("Read-only buffer");
         }
-        return read(bufs, true, timeout, unit, attachment, handler);
+        read(true, null, bufs, timeout, unit, attachment, handler);
     }
 
     /**
      * Invoked by write to initiate the I/O operation.
      */
-    abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
-                                                      boolean isGatheringWrite,
+    abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+                                                      ByteBuffer src,
+                                                      ByteBuffer[] srcs,
                                                       long timeout,
                                                       TimeUnit unit,
                                                       A attachment,
                                                       CompletionHandler<V,? super A> handler);
 
     @SuppressWarnings("unchecked")
-    private <V extends Number,A> Future<V> write(ByteBuffer[] srcs,
-                                                 boolean isGatheringWrite,
+    private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
+                                                 ByteBuffer src,
+                                                 ByteBuffer[] srcs,
                                                  long timeout,
                                                  TimeUnit unit,
-                                                 A attachment,
+                                                 A att,
                                                  CompletionHandler<V,? super A> handler)
     {
-        boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining();
+        boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
 
         boolean closed = false;
         if (isOpen()) {
             if (remoteAddress == null)
                 throw new NotYetConnectedException();
-            if (timeout < 0L)
+             if (timeout < 0L)
                 throw new IllegalArgumentException("Negative timeout");
             // check and update state
             synchronized (writeLock) {
                 if (writeKilled)
-                    throw new RuntimeException("Writing not allowed due to timeout or cancellation");
+                    throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
                 if (writing)
                     throw new WritePendingException();
                 if (writeShutdown) {
@@ -327,52 +363,57 @@
 
         // channel is closed or shutdown for write
         if (closed) {
-            CompletedFuture<V,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable e = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(e);
+            Invoker.invoke(this, handler, att, null, e);
+            return null;
         }
 
         // nothing to write so complete immediately
         if (!hasDataToWrite) {
-            CompletedFuture<V,A> result;
-            if (isGatheringWrite) {
-                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment);
-            } else {
-                result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment);
-            }
-            Invoker.invoke(handler, result);
-            return result;
+            Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
+            if (handler == null)
+                return CompletedFuture.withResult((V)result);
+            Invoker.invoke(this, handler, att, (V)result, null);
+            return null;
         }
 
-        return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler);
+        return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
     }
 
     @Override
-    public final <A> Future<Integer> write(ByteBuffer src,
-                                           long timeout,
-                                           TimeUnit unit,
-                                           A attachment,
-                                           CompletionHandler<Integer,? super A> handler)
-    {
-        ByteBuffer[] bufs = new ByteBuffer[1];
-        bufs[0] = src;
-        return write(bufs, false, timeout, unit, attachment, handler);
+    public final Future<Integer> write(ByteBuffer src) {
+        return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
     }
 
     @Override
-    public final <A> Future<Long> write(ByteBuffer[] srcs,
-                                        int offset,
-                                        int length,
-                                        long timeout,
-                                        TimeUnit unit,
-                                        A attachment,
-                                        CompletionHandler<Long,? super A> handler)
+    public final <A> void write(ByteBuffer src,
+                                long timeout,
+                                TimeUnit unit,
+                                A attachment,
+                                CompletionHandler<Integer,? super A> handler)
     {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        write(false, src, null, timeout, unit, attachment, handler);
+    }
+
+    @Override
+    public final <A> void  write(ByteBuffer[] srcs,
+                                 int offset,
+                                 int length,
+                                 long timeout,
+                                 TimeUnit unit,
+                                 A attachment,
+                                 CompletionHandler<Long,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
             throw new IndexOutOfBoundsException();
         srcs = Util.subsequence(srcs, offset, length);
-        return write(srcs, true, timeout, unit, attachment, handler);
+        write(true, null, srcs, timeout, unit, attachment, handler);
     }
 
     @Override
@@ -461,7 +502,6 @@
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public final SocketAddress getRemoteAddress() throws IOException {
         if (!isOpen())
             throw new ClosedChannelException();
--- a/src/share/classes/sun/nio/ch/CompletedFuture.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/CompletedFuture.java	Tue Sep 01 13:03:09 2009 -0700
@@ -25,7 +25,7 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.AsynchronousChannel;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.ExecutionException;
 import java.io.IOException;
@@ -35,39 +35,35 @@
  * completed.
  */
 
-final class CompletedFuture<V,A>
-    extends AbstractFuture<V,A>
-{
+final class CompletedFuture<V> implements Future<V> {
     private final V result;
     private final Throwable exc;
 
-    private CompletedFuture(AsynchronousChannel channel,
-                            V result,
-                            Throwable exc,
-                            A attachment)
-    {
-        super(channel, attachment);
+    private CompletedFuture(V result, Throwable exc) {
         this.result = result;
         this.exc = exc;
     }
 
     @SuppressWarnings("unchecked")
-    static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel,
-                                                 V result,
-                                                 A attachment)
-    {
-        return new CompletedFuture<V,A>(channel, result, null, attachment);
+    static <V> CompletedFuture<V> withResult(V result) {
+        return new CompletedFuture<V>(result, null);
     }
 
     @SuppressWarnings("unchecked")
-    static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel,
-                                                  Throwable exc,
-                                                  A attachment)
-    {
+    static <V> CompletedFuture<V> withFailure(Throwable exc) {
         // exception must be IOException or SecurityException
         if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
             exc = new IOException(exc);
-        return new CompletedFuture(channel, null, exc, attachment);
+        return new CompletedFuture(null, exc);
+    }
+
+    @SuppressWarnings("unchecked")
+    static <V> CompletedFuture<V> withResult(V result, Throwable exc) {
+        if (exc == null) {
+            return withResult(result);
+        } else {
+            return withFailure(exc);
+        }
     }
 
     @Override
@@ -100,14 +96,4 @@
     public boolean cancel(boolean mayInterruptIfRunning) {
         return false;
     }
-
-    @Override
-    Throwable exception() {
-        return exc;
-    }
-
-    @Override
-    V value() {
-        return result;
-    }
 }
--- a/src/share/classes/sun/nio/ch/Invoker.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/Invoker.java	Tue Sep 01 13:03:09 2009 -0700
@@ -117,33 +117,32 @@
      * Invoke handler without checking the thread identity or number of handlers
      * on the thread stack.
      */
-    @SuppressWarnings("unchecked")
     static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
-                                      AbstractFuture<V,A> result)
+                                      A attachment,
+                                      V value,
+                                      Throwable exc)
     {
-        if (handler != null && !result.isCancelled()) {
-            Throwable exc = result.exception();
-            if (exc == null) {
-                handler.completed(result.value(), result.attachment());
-            } else {
-                handler.failed(exc, result.attachment());
-            }
+        if (exc == null) {
+            handler.completed(value, attachment);
+        } else {
+            handler.failed(exc, attachment);
+        }
 
-            // clear interrupt
-            Thread.interrupted();
-        }
+        // clear interrupt
+        Thread.interrupted();
     }
 
-
     /**
-     * Invoke handler after incrementing the invoke count.
+     * Invoke handler assuming thread identity already checked
      */
     static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
                                    CompletionHandler<V,? super A> handler,
-                                   AbstractFuture<V,A> result)
+                                   A attachment,
+                                   V result,
+                                   Throwable exc)
     {
         myGroupAndInvokeCount.incrementInvokeCount();
-        invokeUnchecked(handler, result);
+        Invoker.invokeUnchecked(handler, attachment, result, exc);
     }
 
     /**
@@ -151,64 +150,64 @@
      * thread pool then the handler is invoked directly, otherwise it is
      * invoked indirectly.
      */
-    static <V,A> void invoke(CompletionHandler<V,? super A> handler,
-                             AbstractFuture<V,A> result)
+    static <V,A> void invoke(AsynchronousChannel channel,
+                             CompletionHandler<V,? super A> handler,
+                             A attachment,
+                             V result,
+                             Throwable exc)
     {
-        if (handler != null) {
-            boolean invokeDirect = false;
-            boolean identityOkay = false;
-            GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
-            if (thisGroupAndInvokeCount != null) {
-                AsynchronousChannel channel = result.channel();
-                if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
-                    identityOkay = true;
-                if (identityOkay &&
-                    (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
-                {
-                    // group match
-                    invokeDirect = true;
-                }
+        boolean invokeDirect = false;
+        boolean identityOkay = false;
+        GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+        if (thisGroupAndInvokeCount != null) {
+            if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
+                identityOkay = true;
+            if (identityOkay &&
+                (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
+            {
+                // group match
+                invokeDirect = true;
             }
-            if (invokeDirect) {
-                thisGroupAndInvokeCount.incrementInvokeCount();
-                invokeUnchecked(handler, result);
-            } else {
-                try {
-                    invokeIndirectly(handler, result);
-                } catch (RejectedExecutionException ree) {
-                    // channel group shutdown; fallback to invoking directly
-                    // if the current thread has the right identity.
-                    if (identityOkay) {
-                        invokeUnchecked(handler, result);
-                    } else {
-                        throw new ShutdownChannelGroupException();
-                    }
+        }
+        if (invokeDirect) {
+            invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
+        } else {
+            try {
+                invokeIndirectly(channel, handler, attachment, result, exc);
+            } catch (RejectedExecutionException ree) {
+                // channel group shutdown; fallback to invoking directly
+                // if the current thread has the right identity.
+                if (identityOkay) {
+                    invokeDirect(thisGroupAndInvokeCount,
+                                 handler, attachment, result, exc);
+                } else {
+                    throw new ShutdownChannelGroupException();
                 }
             }
         }
     }
 
     /**
-     * Invokes the handler "indirectly" in the channel group's thread pool.
+     * Invokes the handler indirectly via the channel group's thread pool.
      */
-    static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
-                                       final AbstractFuture<V,A> result)
+    static <V,A> void invokeIndirectly(AsynchronousChannel channel,
+                                       final CompletionHandler<V,? super A> handler,
+                                       final A attachment,
+                                       final V result,
+                                       final Throwable exc)
     {
-        if (handler != null) {
-            AsynchronousChannel channel = result.channel();
-            try {
-                ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
-                    public void run() {
-                        GroupAndInvokeCount thisGroupAndInvokeCount =
-                            myGroupAndInvokeCount.get();
-                        if (thisGroupAndInvokeCount != null)
-                            thisGroupAndInvokeCount.setInvokeCount(1);
-                        invokeUnchecked(handler, result);
-                    }
-                });
-            } catch (RejectedExecutionException ree) {
-                throw new ShutdownChannelGroupException();
-            }
+        try {
+            ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
+                public void run() {
+                    GroupAndInvokeCount thisGroupAndInvokeCount =
+                        myGroupAndInvokeCount.get();
+                    if (thisGroupAndInvokeCount != null)
+                        thisGroupAndInvokeCount.setInvokeCount(1);
+                    invokeUnchecked(handler, attachment, result, exc);
+                }
+            });
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
         }
     }
 
@@ -216,19 +215,19 @@
      * Invokes the handler "indirectly" in the given Executor
      */
     static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
-                                       final AbstractFuture<V,A> result,
+                                       final A attachment,
+                                       final V value,
+                                       final Throwable exc,
                                        Executor executor)
     {
-        if (handler != null) {
-            try {
-                executor.execute(new Runnable() {
-                    public void run() {
-                        invokeUnchecked(handler, result);
-                    }
-                });
-            } catch (RejectedExecutionException ree) {
-                throw new ShutdownChannelGroupException();
-            }
+         try {
+            executor.execute(new Runnable() {
+                public void run() {
+                    invokeUnchecked(handler, attachment, value, exc);
+                }
+            });
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
         }
     }
 
@@ -258,4 +257,52 @@
             throw new ShutdownChannelGroupException();
         }
     }
+
+    /**
+     * Invoke handler with completed result. This method does not check the
+     * thread identity or the number of handlers on the thread stack.
+     */
+    static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invokeUnchecked(handler,
+                            future.attachment(),
+                            future.value(),
+                            future.exception());
+        }
+    }
+
+    /**
+     * Invoke handler with completed result. If the current thread is in the
+     * channel group's thread pool then the handler is invoked directly,
+     * otherwise it is invoked indirectly.
+     */
+    static <V,A> void invoke(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invoke(future.channel(),
+                   handler,
+                   future.attachment(),
+                   future.value(),
+                   future.exception());
+        }
+    }
+
+    /**
+     * Invoke handler with completed result. The handler is invoked indirectly,
+     * via the channel group's thread pool.
+     */
+    static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invokeIndirectly(future.channel(),
+                             handler,
+                             future.attachment(),
+                             future.value(),
+                             future.exception());
+        }
+    }
 }
--- a/src/share/classes/sun/nio/ch/PendingFuture.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/PendingFuture.java	Tue Sep 01 13:03:09 2009 -0700
@@ -34,13 +34,13 @@
  * attachment of an additional arbitrary context object and a timer task.
  */
 
-final class PendingFuture<V,A>
-    extends AbstractFuture<V,A>
-{
+final class PendingFuture<V,A> implements Future<V> {
     private static final CancellationException CANCELLED =
         new CancellationException();
 
+    private final AsynchronousChannel channel;
     private final CompletionHandler<V,? super A> handler;
+    private final A attachment;
 
     // true if result (or exception) is available
     private volatile boolean haveResult;
@@ -56,14 +56,14 @@
     // optional context object
     private volatile Object context;
 
-
     PendingFuture(AsynchronousChannel channel,
                   CompletionHandler<V,? super A> handler,
                   A attachment,
                   Object context)
     {
-        super(channel, attachment);
+        this.channel = channel;
         this.handler = handler;
+        this.attachment = attachment;
         this.context = context;
     }
 
@@ -71,14 +71,31 @@
                   CompletionHandler<V,? super A> handler,
                   A attachment)
     {
-        super(channel, attachment);
+        this.channel = channel;
         this.handler = handler;
+        this.attachment = attachment;
+    }
+
+    PendingFuture(AsynchronousChannel channel) {
+        this(channel, null, null);
+    }
+
+    PendingFuture(AsynchronousChannel channel, Object context) {
+        this(channel, null, null, context);
+    }
+
+    AsynchronousChannel channel() {
+        return channel;
     }
 
     CompletionHandler<V,? super A> handler() {
         return handler;
     }
 
+    A attachment() {
+        return attachment;
+    }
+
     void setContext(Object context) {
         this.context = context;
     }
@@ -113,36 +130,45 @@
     /**
      * Sets the result, or a no-op if the result or exception is already set.
      */
-    boolean setResult(V res) {
+    void setResult(V res) {
         synchronized (this) {
             if (haveResult)
-                return false;
+                return;
             result = res;
             haveResult = true;
             if (timeoutTask != null)
                 timeoutTask.cancel(false);
             if (latch != null)
                 latch.countDown();
-            return true;
         }
     }
 
     /**
      * Sets the result, or a no-op if the result or exception is already set.
      */
-    boolean setFailure(Throwable x) {
+    void setFailure(Throwable x) {
         if (!(x instanceof IOException) && !(x instanceof SecurityException))
             x = new IOException(x);
         synchronized (this) {
             if (haveResult)
-                return false;
+                return;
             exc = x;
             haveResult = true;
             if (timeoutTask != null)
                 timeoutTask.cancel(false);
             if (latch != null)
                 latch.countDown();
-            return true;
+        }
+    }
+
+    /**
+     * Sets the result
+     */
+    void setResult(V res, Throwable x) {
+        if (x == null) {
+            setResult(res);
+        } else {
+            setFailure(x);
         }
     }
 
@@ -178,12 +204,10 @@
         return result;
     }
 
-    @Override
     Throwable exception() {
         return (exc != CANCELLED) ? exc : null;
     }
 
-    @Override
     V value() {
         return result;
     }
@@ -204,33 +228,6 @@
             if (haveResult)
                 return false;    // already completed
 
-            // A shutdown of the channel group will close all channels and
-            // shutdown the executor. To ensure that the completion handler
-            // is executed we queue the task while holding the lock.
-            if (handler != null) {
-                prepareForWait();
-                Runnable cancelTask = new Runnable() {
-                    public void run() {
-                        while (!haveResult) {
-                            try {
-                                latch.await();
-                            } catch (InterruptedException ignore) { }
-                        }
-                        handler.cancelled(attachment());
-                    }
-                };
-                AsynchronousChannel ch = channel();
-                if (ch instanceof Groupable) {
-                    ((Groupable)ch).group().executeOnPooledThread(cancelTask);
-                } else {
-                    if (ch instanceof AsynchronousFileChannelImpl) {
-                        ((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask);
-                    } else {
-                        throw new AssertionError("Should not get here");
-                    }
-                }
-            }
-
             // notify channel
             if (channel() instanceof Cancellable)
                 ((Cancellable)channel()).onCancel(this);
@@ -249,7 +246,7 @@
             } catch (IOException ignore) { }
         }
 
-        // release waiters (this also releases the invoker)
+        // release waiters
         if (latch != null)
             latch.countDown();
         return true;
--- a/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -317,51 +317,71 @@
         return new WrappedMembershipKey(this, key);
     }
 
-    @Override
-    public <A> Future<Integer> send(ByteBuffer src,
-                                    SocketAddress target,
-                                    long timeout,
-                                    TimeUnit unit,
-                                    A attachment,
-                                    CompletionHandler<Integer,? super A> handler)
+    private <A> Future<Integer> implSend(ByteBuffer src,
+                                         SocketAddress target,
+                                         A attachment,
+                                         CompletionHandler<Integer,? super A> handler)
     {
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
-
-        CompletedFuture<Integer,A> result;
+        int n = 0;
+        Throwable exc = null;
         try {
-            int n = dc.send(src, target);
-            result = CompletedFuture.withResult(this, n, attachment);
+            n = dc.send(src, target);
         } catch (IOException ioe) {
-            result = CompletedFuture.withFailure(this, ioe, attachment);
+            exc = ioe;
         }
-        Invoker.invoke(handler, result);
-        return result;
+        if (handler == null)
+            return CompletedFuture.withResult(n, exc);
+        Invoker.invoke(this, handler, attachment, n, exc);
+        return null;
     }
 
     @Override
-    public <A> Future<Integer> write(ByteBuffer src,
-                                     long timeout,
-                                     TimeUnit unit,
-                                     A attachment,
-                                     CompletionHandler<Integer,? super A> handler)
+    public Future<Integer> send(ByteBuffer src, SocketAddress target) {
+        return implSend(src, target, null, null);
+    }
+
+    @Override
+    public <A> void send(ByteBuffer src,
+                         SocketAddress target,
+                         A attachment,
+                         CompletionHandler<Integer,? super A> handler)
     {
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implSend(src, target, attachment, handler);
+    }
 
-        CompletedFuture<Integer,A> result;
+    private <A> Future<Integer> implWrite(ByteBuffer src,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        int n = 0;
+        Throwable exc = null;
         try {
-            int n = dc.write(src);
-            result = CompletedFuture.withResult(this, n, attachment);
+            n = dc.write(src);
         } catch (IOException ioe) {
-            result = CompletedFuture.withFailure(this, ioe, attachment);
+            exc = ioe;
         }
-        Invoker.invoke(handler, result);
-        return result;
+        if (handler == null)
+            return CompletedFuture.withResult(n, exc);
+        Invoker.invoke(this, handler, attachment, n, exc);
+        return null;
+
+    }
+
+    @Override
+    public Future<Integer> write(ByteBuffer src) {
+        return implWrite(src, null, null);
+    }
+
+    @Override
+    public <A> void write(ByteBuffer src,
+                          A attachment,
+                          CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implWrite(src, attachment, handler);
     }
 
     /**
@@ -390,12 +410,11 @@
         }
     }
 
-    @Override
-    public <A> Future<SocketAddress> receive(final ByteBuffer dst,
-                                             final long timeout,
-                                             final TimeUnit unit,
-                                             A attachment,
-                                             final CompletionHandler<SocketAddress,? super A> handler)
+    private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
+                                                  final long timeout,
+                                                  final TimeUnit unit,
+                                                  A attachment,
+                                                  final CompletionHandler<SocketAddress,? super A> handler)
     {
         if (dst.isReadOnly())
             throw new IllegalArgumentException("Read-only buffer");
@@ -406,10 +425,11 @@
 
         // complete immediately if channel closed
         if (!isOpen()) {
-            CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this,
-                new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
         }
 
         final AccessControlContext acc = (System.getSecurityManager() == null) ?
@@ -471,7 +491,7 @@
                         x = new AsynchronousCloseException();
                     result.setFailure(x);
                 }
-                Invoker.invokeUnchecked(handler, result);
+                Invoker.invokeUnchecked(result);
             }
         };
         try {
@@ -483,11 +503,27 @@
     }
 
     @Override
-    public <A> Future<Integer> read(final ByteBuffer dst,
-                                    final long timeout,
-                                    final TimeUnit unit,
-                                    A attachment,
-                                    final CompletionHandler<Integer,? super A> handler)
+    public Future<SocketAddress> receive(ByteBuffer dst) {
+        return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    @Override
+    public <A> void receive(ByteBuffer dst,
+                            long timeout,
+                            TimeUnit unit,
+                            A attachment,
+                            CompletionHandler<SocketAddress,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implReceive(dst, timeout, unit, attachment, handler);
+    }
+
+    private <A> Future<Integer> implRead(final ByteBuffer dst,
+                                         final long timeout,
+                                         final TimeUnit unit,
+                                         A attachment,
+                                         final CompletionHandler<Integer,? super A> handler)
     {
         if (dst.isReadOnly())
             throw new IllegalArgumentException("Read-only buffer");
@@ -495,18 +531,20 @@
             throw new IllegalArgumentException("Negative timeout");
         if (unit == null)
             throw new NullPointerException();
+
+        // complete immediately if channel closed
+        if (!isOpen()) {
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
+        }
+
         // another thread may disconnect before read is initiated
         if (!dc.isConnected())
             throw new NotYetConnectedException();
 
-        // complete immediately if channel closed
-        if (!isOpen()) {
-            CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this,
-                new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
-        }
-
         final PendingFuture<Integer,A> result =
             new PendingFuture<Integer,A>(this, handler, attachment);
         Runnable task = new Runnable() {
@@ -563,7 +601,7 @@
                         x = new AsynchronousCloseException();
                     result.setFailure(x);
                 }
-                Invoker.invokeUnchecked(handler, result);
+                Invoker.invokeUnchecked(result);
             }
         };
         try {
@@ -575,6 +613,23 @@
     }
 
     @Override
+    public Future<Integer> read(ByteBuffer dst) {
+        return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    @Override
+    public <A> void read(ByteBuffer dst,
+                            long timeout,
+                            TimeUnit unit,
+                            A attachment,
+                            CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implRead(dst, timeout, unit, attachment, handler);
+    }
+
+    @Override
     public  AsynchronousDatagramChannel bind(SocketAddress local)
         throws IOException
     {
--- a/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -50,9 +50,6 @@
     // Used to make native read and write calls
     private static final FileDispatcher nd = new FileDispatcherImpl();
 
-    // indicates if the associated thread pool is the default thread pool
-    private final boolean isDefaultExecutor;
-
     // Thread-safe set of IDs of native threads, for signalling
     private final NativeThreadSet threads = new NativeThreadSet(2);
 
@@ -60,11 +57,9 @@
     SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
                                       boolean reading,
                                       boolean writing,
-                                      ExecutorService executor,
-                                      boolean isDefaultexecutor)
+                                      ExecutorService executor)
     {
         super(fdObj, reading, writing, executor);
-        this.isDefaultExecutor = isDefaultexecutor;
     }
 
     public static AsynchronousFileChannel open(FileDescriptor fdo,
@@ -73,17 +68,9 @@
                                                ThreadPool pool)
     {
         // Executor is either default or based on pool parameters
-        ExecutorService executor;
-        boolean isDefaultexecutor;
-        if (pool == null) {
-            executor = DefaultExecutorHolder.defaultExecutor;
-            isDefaultexecutor = true;
-        } else {
-            executor = pool.executor();
-            isDefaultexecutor = false;
-        }
-        return new SimpleAsynchronousFileChannelImpl(fdo,
-            reading, writing, executor, isDefaultexecutor);
+        ExecutorService executor = (pool == null) ?
+            DefaultExecutorHolder.defaultExecutor : pool.executor();
+        return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
     }
 
     @Override
@@ -114,16 +101,6 @@
 
         // close file
         nd.close(fdObj);
-
-        // shutdown executor if specific to this channel
-        if (!isDefaultExecutor) {
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    executor.shutdown();
-                    return null;
-                }
-            });
-        }
     }
 
     @Override
@@ -194,11 +171,11 @@
     }
 
     @Override
-    public <A> Future<FileLock> lock(final long position,
-                                     final long size,
-                                     final boolean shared,
-                                     A attachment,
-                                     final CompletionHandler<FileLock,? super A> handler)
+    <A> Future<FileLock> implLock(final long position,
+                                  final long size,
+                                  final boolean shared,
+                                  final A attachment,
+                                  final CompletionHandler<FileLock,? super A> handler)
     {
         if (shared && !reading)
             throw new NonReadableChannelException();
@@ -208,16 +185,19 @@
         // add to lock table
         final FileLockImpl fli = addToFileLockTable(position, size, shared);
         if (fli == null) {
-            CompletedFuture<FileLock,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invokeIndirectly(handler, result, executor);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
+            return null;
         }
 
-        final PendingFuture<FileLock,A> result =
-            new PendingFuture<FileLock,A>(this, handler, attachment);
+        final PendingFuture<FileLock,A> result = (handler == null) ?
+            new PendingFuture<FileLock,A>(this) : null;
         Runnable task = new Runnable() {
             public void run() {
+                Throwable exc = null;
+
                 int ti = threads.add();
                 try {
                     int n;
@@ -226,31 +206,36 @@
                         do {
                             n = nd.lock(fdObj, true, position, size, shared);
                         } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
-                        if (n == FileDispatcher.LOCKED && isOpen()) {
-                            result.setResult(fli);
-                        } else {
+                        if (n != FileDispatcher.LOCKED || !isOpen()) {
                             throw new AsynchronousCloseException();
                         }
                     } catch (IOException x) {
                         removeFromFileLockTable(fli);
                         if (!isOpen())
                             x = new AsynchronousCloseException();
-                        result.setFailure(x);
+                        exc = x;
                     } finally {
                         end();
                     }
                 } finally {
                     threads.remove(ti);
                 }
-                Invoker.invokeUnchecked(handler, result);
+                if (handler == null) {
+                    result.setResult(fli, exc);
+                } else {
+                    Invoker.invokeUnchecked(handler, attachment, fli, exc);
+                }
             }
         };
+        boolean executed = false;
         try {
             executor.execute(task);
-        } catch (RejectedExecutionException ree) {
-            // rollback
-            removeFromFileLockTable(fli);
-            throw new ShutdownChannelGroupException();
+            executed = true;
+        } finally {
+            if (!executed) {
+                // rollback
+                removeFromFileLockTable(fli);
+            }
         }
         return result;
     }
@@ -301,10 +286,10 @@
     }
 
     @Override
-    public <A> Future<Integer> read(final ByteBuffer dst,
-                                    final long position,
-                                    A attachment,
-                                    final CompletionHandler<Integer,? super A> handler)
+    <A> Future<Integer> implRead(final ByteBuffer dst,
+                                 final long position,
+                                 final A attachment,
+                                 final CompletionHandler<Integer,? super A> handler)
     {
         if (position < 0)
             throw new IllegalArgumentException("Negative position");
@@ -315,55 +300,52 @@
 
         // complete immediately if channel closed or no space remaining
         if (!isOpen() || (dst.remaining() == 0)) {
-            CompletedFuture<Integer,A> result;
-            if (isOpen()) {
-                result = CompletedFuture.withResult(this, 0, attachment);
-            } else {
-                result = CompletedFuture.withFailure(this,
-                    new ClosedChannelException(), attachment);
-            }
-            Invoker.invokeIndirectly(handler, result, executor);
-            return result;
+            Throwable exc = (isOpen()) ? null : new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withResult(0, exc);
+            Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
+            return null;
         }
 
-        final PendingFuture<Integer,A> result =
-            new PendingFuture<Integer,A>(this, handler, attachment);
+        final PendingFuture<Integer,A> result = (handler == null) ?
+            new PendingFuture<Integer,A>(this) : null;
         Runnable task = new Runnable() {
             public void run() {
+                int n = 0;
+                Throwable exc = null;
+
                 int ti = threads.add();
                 try {
                     begin();
-                    int n;
                     do {
                         n = IOUtil.read(fdObj, dst, position, nd, null);
                     } while ((n == IOStatus.INTERRUPTED) && isOpen());
                     if (n < 0 && !isOpen())
                         throw new AsynchronousCloseException();
-                    result.setResult(n);
                 } catch (IOException x) {
                     if (!isOpen())
                         x = new AsynchronousCloseException();
-                    result.setFailure(x);
+                    exc = x;
                 } finally {
                     end();
                     threads.remove(ti);
                 }
-                Invoker.invokeUnchecked(handler, result);
+                if (handler == null) {
+                    result.setResult(n, exc);
+                } else {
+                    Invoker.invokeUnchecked(handler, attachment, n, exc);
+                }
             }
         };
-        try {
-            executor.execute(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
+        executor.execute(task);
         return result;
     }
 
     @Override
-    public <A> Future<Integer> write(final ByteBuffer src,
-                                     final long position,
-                                     A attachment,
-                                     final CompletionHandler<Integer,? super A> handler)
+    <A> Future<Integer> implWrite(final ByteBuffer src,
+                                  final long position,
+                                  final A attachment,
+                                  final CompletionHandler<Integer,? super A> handler)
     {
         if (position < 0)
             throw new IllegalArgumentException("Negative position");
@@ -372,47 +354,44 @@
 
         // complete immediately if channel is closed or no bytes remaining
         if (!isOpen() || (src.remaining() == 0)) {
-            CompletedFuture<Integer,A> result;
-            if (isOpen()) {
-                result = CompletedFuture.withResult(this, 0, attachment);
-            } else {
-                result = CompletedFuture.withFailure(this,
-                    new ClosedChannelException(), attachment);
-            }
-            Invoker.invokeIndirectly(handler, result, executor);
-            return result;
+            Throwable exc = (isOpen()) ? null : new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withResult(0, exc);
+            Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
+            return null;
         }
 
-        final PendingFuture<Integer,A> result =
-            new PendingFuture<Integer,A>(this, handler, attachment);
+        final PendingFuture<Integer,A> result = (handler == null) ?
+            new PendingFuture<Integer,A>(this) : null;
         Runnable task = new Runnable() {
             public void run() {
+                int n = 0;
+                Throwable exc = null;
+
                 int ti = threads.add();
                 try {
                     begin();
-                    int n;
                     do {
                         n = IOUtil.write(fdObj, src, position, nd, null);
                     } while ((n == IOStatus.INTERRUPTED) && isOpen());
                     if (n < 0 && !isOpen())
                         throw new AsynchronousCloseException();
-                    result.setResult(n);
                 } catch (IOException x) {
                     if (!isOpen())
                         x = new AsynchronousCloseException();
-                    result.setFailure(x);
+                    exc = x;
                 } finally {
                     end();
                     threads.remove(ti);
                 }
-                Invoker.invokeUnchecked(handler, result);
+                if (handler == null) {
+                    result.setResult(n, exc);
+                } else {
+                    Invoker.invokeUnchecked(handler, attachment, n, exc);
+                }
             }
         };
-        try {
-            executor.execute(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
+        executor.execute(task);
         return result;
     }
 }
--- a/src/share/classes/sun/nio/cs/ext/ISO2022.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/cs/ext/ISO2022.java	Tue Sep 01 13:03:09 2009 -0700
@@ -388,9 +388,9 @@
 
     protected static class Encoder extends CharsetEncoder {
         private final Surrogate.Parser sgp = new Surrogate.Parser();
-        private final byte SS2 = (byte)0x8e;
-        private final byte PLANE2 = (byte)0xA2;
-        private final byte PLANE3 = (byte)0xA3;
+        public static final byte SS2 = (byte)0x8e;
+        public static final byte PLANE2 = (byte)0xA2;
+        public static final byte PLANE3 = (byte)0xA3;
         private final byte MSB = (byte)0x80;
 
         protected final byte maximumDesignatorLength = 4;
--- a/src/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java	Tue Sep 01 13:03:09 2009 -0700
@@ -76,6 +76,15 @@
             } catch (Exception e) { }
         }
 
+        private byte[] bb = new byte[4];
+        public boolean canEncode(char c) {
+            int n = 0;
+            return (c <= '\u007f' ||
+                    (n = ((EUC_TW.Encoder)ISOEncoder).toEUC(c, bb)) == 2 ||
+                    (n == 4 && bb[0] == SS2 &&
+                     (bb[1] == PLANE2 || bb[1] == PLANE3)));
+        }
+
         /*
          * Since ISO2022-CN-CNS possesses a CharsetEncoder
          * without the corresponding CharsetDecoder half the
--- a/src/share/classes/sun/security/jgss/SunProvider.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/jgss/SunProvider.java	Tue Sep 01 13:03:09 2009 -0700
@@ -62,7 +62,7 @@
 
     public SunProvider() {
         /* We are the Sun JGSS provider */
-        super("SunJGSS", 1.0, INFO);
+        super("SunJGSS", 1.7d, INFO);
 
         AccessController.doPrivileged(
                         new java.security.PrivilegedAction<Void>() {
--- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Tue Sep 01 13:03:09 2009 -0700
@@ -41,6 +41,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.File;
+import java.util.Comparator;
 import java.util.StringTokenizer;
 
 /**
@@ -229,10 +230,11 @@
     /**
      * Reads the service key from the keytab file.
      * @param service the PrincipalName of the requested service.
-     * @return the last service key in the keytab
+     * @return the last service key in the keytab with the highest kvno
      */
     public EncryptionKey readServiceKey(PrincipalName service) {
         KeyTabEntry entry = null;
+        EncryptionKey key = null;
         if (entries != null) {
             // Find latest entry for this service that has an etype
             // that has been configured for use
@@ -240,9 +242,12 @@
                 entry = entries.elementAt(i);
                 if (entry.service.match(service)) {
                     if (EType.isSupported(entry.keyType)) {
-                        return new EncryptionKey(entry.keyblock,
+                        if (key == null ||
+                                entry.keyVersion > key.getKeyVersionNumber()) {
+                            key = new EncryptionKey(entry.keyblock,
                                              entry.keyType,
                                              new Integer(entry.keyVersion));
+                        }
                     } else if (DEBUG) {
                         System.out.println("Found unsupported keytype (" +
                             entry.keyType + ") for " + service);
@@ -250,12 +255,13 @@
                 }
             }
         }
-        return null;
+        return key;
     }
 
     /**
      * Reads all keys for a service from the keytab file that have
-     * etypes that have been configured for use.
+     * etypes that have been configured for use. If there are multiple
+     * keys with same etype, the one with the highest kvno is returned.
      * @param service the PrincipalName of the requested service
      * @return an array containing all the service keys
      */
@@ -288,49 +294,39 @@
         size = keys.size();
         if (size == 0)
             return null;
-        EncryptionKey[] retVal = new EncryptionKey[size];
+        EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
 
         // Sort keys according to default_tkt_enctypes
-        int pos = 0;
-        EncryptionKey k;
         if (DEBUG) {
             System.out.println("Ordering keys wrt default_tkt_enctypes list");
         }
-        int[] etypes = EType.getDefaults("default_tkt_enctypes");
-        if (etypes == null || etypes == EType.getBuiltInDefaults()) {
-            // Either no supported types specified in default_tkt_enctypes
-            // or no default_tkt_enctypes entry at all. For both cases,
-            // just return supported keys in the order retrieved
-            for (int i = 0; i < size; i++) {
-                retVal[pos++] = keys.get(i);
-            }
-        } else {
-            for (int j = 0; j < etypes.length && pos < size; j++) {
-                int target = etypes[j];
-                for (int i = 0; i < size && pos < size; i++) {
-                    k = keys.get(i);
-                    if (k != null && k.getEType() == target) {
-                        if (DEBUG) {
-                            System.out.println(pos + ": " + k);
+
+        final int[] etypes = EType.getDefaults("default_tkt_enctypes");
+
+        // Sort the keys, k1 is preferred than k2 if:
+        // 1. k1's etype appears earlier in etypes than k2's
+        // 2. If same, k1's KVNO is higher
+        Arrays.sort(retVal, new Comparator<EncryptionKey>() {
+            @Override
+            public int compare(EncryptionKey o1, EncryptionKey o2) {
+                if (etypes != null && etypes != EType.getBuiltInDefaults()) {
+                    int o1EType = o1.getEType();
+                    int o2EType = o2.getEType();
+                    if (o1EType != o2EType) {
+                        for (int i=0; i<etypes.length; i++) {
+                            if (etypes[i] == o1EType) {
+                                return -1;
+                            } else if (etypes[i] == o2EType) {
+                                return 1;
+                            }
                         }
-                        retVal[pos++] = k;
-                        keys.set(i, null);  // Cleared from consideration
                     }
                 }
+                return o2.getKeyVersionNumber().intValue()
+                        - o1.getKeyVersionNumber().intValue();
             }
-            // copy the rest
-            for (int i = 0; i < size && pos < size; i++) {
-                k = keys.get(i);
-                if (k != null) {
-                    retVal[pos++] = k;
-                }
-            }
-        }
-        if (pos != size) {
-            throw new RuntimeException(
-                "Internal Error: did not copy all keys;expecting " + size +
-                    "; got " + pos);
-        }
+        });
+
         return retVal;
     }
 
--- a/src/share/classes/sun/security/provider/Sun.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/provider/Sun.java	Tue Sep 01 13:03:09 2009 -0700
@@ -46,7 +46,7 @@
 
     public Sun() {
         /* We are the SUN provider */
-        super("SUN", 1.6, INFO);
+        super("SUN", 1.7, INFO);
 
         // if there is no security manager installed, put directly into
         // the provider. Otherwise, create a temporary map and use a
--- a/src/share/classes/sun/security/smartcardio/SunPCSC.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/smartcardio/SunPCSC.java	Tue Sep 01 13:03:09 2009 -0700
@@ -40,7 +40,7 @@
     private static final long serialVersionUID = 6168388284028876579L;
 
     public SunPCSC() {
-        super("SunPCSC", 1.6d, "Sun PC/SC provider");
+        super("SunPCSC", 1.7d, "Sun PC/SC provider");
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 put("TerminalFactory.PC/SC", "sun.security.smartcardio.SunPCSC$Factory");
--- a/src/share/classes/sun/security/ssl/SunJSSE.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/ssl/SunJSSE.java	Tue Sep 01 13:03:09 2009 -0700
@@ -103,7 +103,7 @@
 
     // standard constructor
     protected SunJSSE() {
-        super("SunJSSE", 1.6d, info);
+        super("SunJSSE", 1.7d, info);
         subclassCheck();
         if (Boolean.TRUE.equals(fips)) {
             throw new ProviderException
--- a/src/share/classes/sun/security/util/Password.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/classes/sun/security/util/Password.java	Tue Sep 01 13:03:09 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,14 @@
 public class Password {
     /** Reads user password from given input stream. */
     public static char[] readPassword(InputStream in) throws IOException {
+        return readPassword(in, false);
+    }
+
+    /** Reads user password from given input stream.
+     * @param isEchoOn true if the password should be echoed on the screen
+     */
+    public static char[] readPassword(InputStream in, boolean isEchoOn)
+            throws IOException {
 
         char[] consoleEntered = null;
         byte[] consoleBytes = null;
@@ -44,7 +52,7 @@
         try {
             // Use the new java.io.Console class
             Console con = null;
-            if (in == System.in && ((con = System.console()) != null)) {
+            if (!isEchoOn && in == System.in && ((con = System.console()) != null)) {
                 consoleEntered = con.readPassword();
                 // readPassword returns "" if you just print ENTER,
                 // to be compatible with old Password class, change to null
--- a/src/share/native/sun/security/ec/ec.c	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/share/native/sun/security/ec/ec.c	Tue Sep 01 13:03:09 2009 -0700
@@ -422,7 +422,7 @@
      */
     if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
     if (randomlen != 2 * len) {
-        goto cleanup;
+        randomlen = 2 * len;
     }
     /* No need to generate - random bytes are now supplied */
     /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
--- a/src/solaris/classes/sun/nio/ch/EPollPort.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/ch/EPollPort.java	Tue Sep 01 13:03:09 2009 -0700
@@ -248,12 +248,13 @@
         public void run() {
             Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
                 Invoker.getGroupAndInvokeCount();
+            final boolean isPooledThread = (myGroupAndInvokeCount != null);
             boolean replaceMe = false;
             Event ev;
             try {
                 for (;;) {
                     // reset invoke count
-                    if (myGroupAndInvokeCount != null)
+                    if (isPooledThread)
                         myGroupAndInvokeCount.resetInvokeCount();
 
                     try {
@@ -289,7 +290,7 @@
 
                     // process event
                     try {
-                        ev.channel().onEvent(ev.events());
+                        ev.channel().onEvent(ev.events(), isPooledThread);
                     } catch (Error x) {
                         replaceMe = true; throw x;
                     } catch (RuntimeException x) {
--- a/src/solaris/classes/sun/nio/ch/Port.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/ch/Port.java	Tue Sep 01 13:03:09 2009 -0700
@@ -49,7 +49,7 @@
      * Implemented by clients registered with this port.
      */
     interface PollableChannel extends Closeable {
-        void onEvent(int events);
+        void onEvent(int events, boolean mayInvokeDirect);
     }
 
     // maps fd to "pollable" channel
@@ -121,7 +121,7 @@
     final Object attachForeignChannel(final Channel channel, FileDescriptor fd) {
         int fdVal = IOUtil.fdVal(fd);
         register(fdVal, new PollableChannel() {
-            public void onEvent(int events) { }
+            public void onEvent(int events, boolean mayInvokeDirect) { }
             public void close() throws IOException {
                 channel.close();
             }
--- a/src/solaris/classes/sun/nio/ch/SolarisEventPort.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/ch/SolarisEventPort.java	Tue Sep 01 13:03:09 2009 -0700
@@ -151,12 +151,13 @@
         public void run() {
             Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
                 Invoker.getGroupAndInvokeCount();
+            final boolean isPooledThread = (myGroupAndInvokeCount != null);
             boolean replaceMe = false;
             long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
             try {
                 for (;;) {
                     // reset invoke count
-                    if (myGroupAndInvokeCount != null)
+                    if (isPooledThread)
                         myGroupAndInvokeCount.resetInvokeCount();
 
                     // wait for I/O completion event
@@ -205,7 +206,7 @@
                     if (ch != null) {
                         replaceMe = true;
                         // no need to translate events
-                        ch.onEvent(events);
+                        ch.onEvent(events, isPooledThread);
                     }
                 }
             } finally {
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -59,10 +59,13 @@
     private final Object updateLock = new Object();
 
     // pending accept
-    private PendingFuture<AsynchronousSocketChannel,Object> pendingAccept;
+    private boolean acceptPending;
+    private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
+    private Object acceptAttachment;
+    private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
 
     // context for permission check when security manager set
-    private AccessControlContext acc;
+    private AccessControlContext acceptAcc;
 
 
     UnixAsynchronousServerSocketChannelImpl(Port port)
@@ -83,15 +86,6 @@
         port.register(fdVal, this);
     }
 
-    // returns and clears the result of a pending accept
-    private PendingFuture<AsynchronousSocketChannel,Object> grabPendingAccept() {
-        synchronized (updateLock) {
-            PendingFuture<AsynchronousSocketChannel,Object> result = pendingAccept;
-            pendingAccept = null;
-            return result;
-        }
-    }
-
     @Override
     void implClose() throws IOException {
         // remove the mapping
@@ -101,17 +95,27 @@
         nd.close(fd);
 
         // if there is a pending accept then complete it
-        final PendingFuture<AsynchronousSocketChannel,Object> result =
-            grabPendingAccept();
-        if (result != null) {
-            // discard the stack trace as otherwise it may appear that implClose
-            // has thrown the exception.
-            AsynchronousCloseException x = new AsynchronousCloseException();
-            x.setStackTrace(new StackTraceElement[0]);
-            result.setFailure(x);
+        CompletionHandler<AsynchronousSocketChannel,Object> handler;
+        Object att;
+        PendingFuture<AsynchronousSocketChannel,Object> future;
+        synchronized (updateLock) {
+            if (!acceptPending)
+                return;  // no pending accept
+            acceptPending = false;
+            handler = acceptHandler;
+            att = acceptAttachment;
+            future = acceptFuture;
+        }
 
+        // discard the stack trace as otherwise it may appear that implClose
+        // has thrown the exception.
+        AsynchronousCloseException x = new AsynchronousCloseException();
+        x.setStackTrace(new StackTraceElement[0]);
+        if (handler == null) {
+            future.setFailure(x);
+        } else {
             // invoke by submitting task rather than directly
-            Invoker.invokeIndirectly(result.handler(), result);
+            Invoker.invokeIndirectly(this, handler, att, null, x);
         }
     }
 
@@ -124,15 +128,17 @@
      * Invoked by event handling thread when listener socket is polled
      */
     @Override
-    public void onEvent(int events) {
-        PendingFuture<AsynchronousSocketChannel,Object> result = grabPendingAccept();
-        if (result == null)
-            return; // may have been grabbed by asynchronous close
+    public void onEvent(int events, boolean mayInvokeDirect) {
+        synchronized (updateLock) {
+            if (!acceptPending)
+                return;  // may have been grabbed by asynchronous close
+            acceptPending = false;
+        }
 
         // attempt to accept connection
         FileDescriptor newfd = new FileDescriptor();
         InetSocketAddress[] isaa = new InetSocketAddress[1];
-        boolean accepted = false;
+        Throwable exc = null;
         try {
             begin();
             int n = accept0(this.fd, newfd, isaa);
@@ -140,49 +146,52 @@
             // spurious wakeup, is this possible?
             if (n == IOStatus.UNAVAILABLE) {
                 synchronized (updateLock) {
-                    this.pendingAccept = result;
+                    acceptPending = true;
                 }
                 port.startPoll(fdVal, Port.POLLIN);
                 return;
             }
 
-            // connection accepted
-            accepted = true;
-
         } catch (Throwable x) {
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            enableAccept();
-            result.setFailure(x);
+            exc = x;
         } finally {
             end();
         }
 
         // Connection accepted so finish it when not holding locks.
         AsynchronousSocketChannel child = null;
-        if (accepted) {
+        if (exc == null) {
             try {
-                child = finishAccept(newfd, isaa[0], acc);
-                enableAccept();
-                result.setResult(child);
+                child = finishAccept(newfd, isaa[0], acceptAcc);
             } catch (Throwable x) {
-                enableAccept();
                 if (!(x instanceof IOException) && !(x instanceof SecurityException))
                     x = new IOException(x);
-                result.setFailure(x);
+                exc = x;
             }
         }
 
-        // if an async cancel has already cancelled the operation then
-        // close the new channel so as to free resources
-        if (child != null && result.isCancelled()) {
-            try {
-                child.close();
-            } catch (IOException ignore) { }
+        // copy field befores accept is re-renabled
+        CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
+        Object att = acceptAttachment;
+        PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
+
+        // re-enable accepting and invoke handler
+        enableAccept();
+
+        if (handler == null) {
+            future.setResult(child, exc);
+            // if an async cancel has already cancelled the operation then
+            // close the new channel so as to free resources
+            if (child != null && future.isCancelled()) {
+                try {
+                    child.close();
+                } catch (IOException ignore) { }
+            }
+        } else {
+            Invoker.invoke(this, handler, att, child, exc);
         }
-
-        // invoke the handler
-        Invoker.invoke(result.handler(), result);
     }
 
     /**
@@ -234,16 +243,18 @@
     }
 
     @Override
-    @SuppressWarnings("unchecked")
-    public <A> Future<AsynchronousSocketChannel> accept(A attachment,
-        final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    Future<AsynchronousSocketChannel> implAccept(Object att,
+        CompletionHandler<AsynchronousSocketChannel,Object> handler)
     {
         // complete immediately if channel is closed
         if (!isOpen()) {
-            CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invokeIndirectly(handler, result);
-            return result;
+            Throwable e = new ClosedChannelException();
+            if (handler == null) {
+                return CompletedFuture.withFailure(e);
+            } else {
+                Invoker.invoke(this, handler, att, null, e);
+                return null;
+            }
         }
         if (localAddress == null)
             throw new NotYetBoundException();
@@ -258,25 +269,31 @@
             throw new AcceptPendingException();
 
         // attempt accept
-        AbstractFuture<AsynchronousSocketChannel,A> result = null;
         FileDescriptor newfd = new FileDescriptor();
         InetSocketAddress[] isaa = new InetSocketAddress[1];
+        Throwable exc = null;
         try {
             begin();
 
             int n = accept0(this.fd, newfd, isaa);
             if (n == IOStatus.UNAVAILABLE) {
-                // no connection to accept
-                result = new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
 
                 // need calling context when there is security manager as
                 // permission check may be done in a different thread without
                 // any application call frames on the stack
-                synchronized (this) {
-                    this.acc = (System.getSecurityManager() == null) ?
+                PendingFuture<AsynchronousSocketChannel,Object> result = null;
+                synchronized (updateLock) {
+                    if (handler == null) {
+                        this.acceptHandler = null;
+                        result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
+                        this.acceptFuture = result;
+                    } else {
+                        this.acceptHandler = handler;
+                        this.acceptAttachment = att;
+                    }
+                    this.acceptAcc = (System.getSecurityManager() == null) ?
                         null : AccessController.getContext();
-                    this.pendingAccept =
-                        (PendingFuture<AsynchronousSocketChannel,Object>)result;
+                    this.acceptPending = true;
                 }
 
                 // register for connections
@@ -287,25 +304,30 @@
             // accept failed
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            result = CompletedFuture.withFailure(this, x, attachment);
+            exc = x;
         } finally {
             end();
         }
 
-        // connection accepted immediately
-        if (result == null) {
+        AsynchronousSocketChannel child = null;
+        if (exc == null) {
+            // connection accepted immediately
             try {
-                AsynchronousSocketChannel ch = finishAccept(newfd, isaa[0], null);
-                result = CompletedFuture.withResult(this, ch, attachment);
+                child = finishAccept(newfd, isaa[0], null);
             } catch (Throwable x) {
-                result = CompletedFuture.withFailure(this, x, attachment);
+                exc = x;
             }
         }
 
-        // re-enable accepting and invoke handler
+        // re-enable accepting before invoking handler
         enableAccept();
-        Invoker.invokeIndirectly(handler, result);
-        return result;
+
+        if (handler == null) {
+            return CompletedFuture.withResult(child, exc);
+        } else {
+            Invoker.invokeIndirectly(this, handler, att, child, exc);
+            return null;
+        }
     }
 
     // -- Native methods --
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -61,20 +61,33 @@
     private final Object updateLock = new Object();
 
     // pending connect (updateLock)
-    private PendingFuture<Void,Object> pendingConnect;
+    private boolean connectPending;
+    private CompletionHandler<Void,Object> connectHandler;
+    private Object connectAttachment;
+    private PendingFuture<Void,Object> connectFuture;
 
-    // pending remote address (statLock)
+    // pending remote address (stateLock)
     private SocketAddress pendingRemote;
 
     // pending read (updateLock)
+    private boolean readPending;
+    private boolean isScatteringRead;
+    private ByteBuffer readBuffer;
     private ByteBuffer[] readBuffers;
-    private boolean scatteringRead;
-    private PendingFuture<Number,Object> pendingRead;
+    private CompletionHandler<Number,Object> readHandler;
+    private Object readAttachment;
+    private PendingFuture<Number,Object> readFuture;
+    private Future<?> readTimer;
 
     // pending write (updateLock)
+    private boolean writePending;
+    private boolean isGatheringWrite;
+    private ByteBuffer writeBuffer;
     private ByteBuffer[] writeBuffers;
-    private boolean gatheringWrite;
-    private PendingFuture<Number,Object> pendingWrite;
+    private CompletionHandler<Number,Object> writeHandler;
+    private Object writeAttachment;
+    private PendingFuture<Number,Object> writeFuture;
+    private Future<?> writeTimer;
 
 
     UnixAsynchronousSocketChannelImpl(Port port)
@@ -128,43 +141,36 @@
     private void updateEvents() {
         assert Thread.holdsLock(updateLock);
         int events = 0;
-        if (pendingRead != null)
+        if (readPending)
             events |= Port.POLLIN;
-        if (pendingConnect != null || pendingWrite != null)
+        if (connectPending || writePending)
             events |= Port.POLLOUT;
         if (events != 0)
             port.startPoll(fdVal, events);
     }
 
-    /**
-     * Invoked by event handler thread when file descriptor is polled
-     */
-    @Override
-    public void onEvent(int events) {
-        boolean readable = (events & Port.POLLIN) > 0;
-        boolean writable = (events & Port.POLLOUT) > 0;
-        if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
-            readable = true;
-            writable = true;
-        }
-
-        PendingFuture<Void,Object> connectResult = null;
-        PendingFuture<Number,Object> readResult = null;
-        PendingFuture<Number,Object> writeResult = null;
+    // invoke to finish read and/or write operations
+    private void finish(boolean mayInvokeDirect,
+                        boolean readable,
+                        boolean writable)
+    {
+        boolean finishRead = false;
+        boolean finishWrite = false;
+        boolean finishConnect = false;
 
         // map event to pending result
         synchronized (updateLock) {
-            if (readable && (pendingRead != null)) {
-                readResult = pendingRead;
-                pendingRead = null;
+            if (readable && this.readPending) {
+                this.readPending = false;
+                finishRead = true;
             }
             if (writable) {
-                if (pendingWrite != null) {
-                    writeResult = pendingWrite;
-                    pendingWrite = null;
-                } else if (pendingConnect != null) {
-                    connectResult = pendingConnect;
-                    pendingConnect = null;
+                if (this.writePending) {
+                    this.writePending = false;
+                    finishWrite = true;
+                } else if (this.connectPending) {
+                    this.connectPending = false;
+                    finishConnect = true;
                 }
             }
         }
@@ -172,36 +178,32 @@
         // complete the I/O operation. Special case for when channel is
         // ready for both reading and writing. In that case, submit task to
         // complete write if write operation has a completion handler.
-        if (readResult != null) {
-            if (writeResult != null)
-                finishWrite(writeResult, false);
-            finishRead(readResult, true);
+        if (finishRead) {
+            if (finishWrite)
+                finishWrite(false);
+            finishRead(mayInvokeDirect);
             return;
         }
-        if (writeResult != null) {
-            finishWrite(writeResult, true);
+        if (finishWrite) {
+            finishWrite(mayInvokeDirect);
         }
-        if (connectResult != null) {
-            finishConnect(connectResult, true);
+        if (finishConnect) {
+            finishConnect(mayInvokeDirect);
         }
     }
 
-    // returns and clears the result of a pending read
-    PendingFuture<Number,Object> grabPendingRead() {
-        synchronized (updateLock) {
-            PendingFuture<Number,Object> result = pendingRead;
-            pendingRead = null;
-            return result;
+    /**
+     * Invoked by event handler thread when file descriptor is polled
+     */
+    @Override
+    public void onEvent(int events, boolean mayInvokeDirect) {
+        boolean readable = (events & Port.POLLIN) > 0;
+        boolean writable = (events & Port.POLLOUT) > 0;
+        if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
+            readable = true;
+            writable = true;
         }
-    }
-
-    // returns and clears the result of a pending write
-    PendingFuture<Number,Object> grabPendingWrite() {
-        synchronized (updateLock) {
-            PendingFuture<Number,Object> result = pendingWrite;
-            pendingWrite = null;
-            return result;
-        }
+        finish(mayInvokeDirect, readable, writable);
     }
 
     @Override
@@ -213,26 +215,7 @@
         nd.close(fd);
 
         // All outstanding I/O operations are required to fail
-        final PendingFuture<Void,Object> readyToConnect;
-        final PendingFuture<Number,Object> readyToRead;
-        final PendingFuture<Number,Object> readyToWrite;
-        synchronized (updateLock) {
-            readyToConnect = pendingConnect;
-            pendingConnect = null;
-            readyToRead = pendingRead;
-            pendingRead = null;
-            readyToWrite = pendingWrite;
-            pendingWrite = null;
-        }
-        if (readyToConnect != null) {
-            finishConnect(readyToConnect, false);
-        }
-        if (readyToRead != null) {
-            finishRead(readyToRead, false);
-        }
-        if (readyToWrite != null) {
-            finishWrite(readyToWrite, false);
-        }
+        finish(false, true, true);
     }
 
     @Override
@@ -240,9 +223,9 @@
         if (task.getContext() == OpType.CONNECT)
             killConnect();
         if (task.getContext() == OpType.READ)
-            killConnect();
+            killReading();
         if (task.getContext() == OpType.WRITE)
-            killConnect();
+            killWriting();
     }
 
     // -- connect --
@@ -255,15 +238,12 @@
         }
     }
 
-    private void finishConnect(PendingFuture<Void,Object> result,
-                               boolean invokeDirect)
-    {
+    private void finishConnect(boolean mayInvokeDirect) {
         Throwable e = null;
         try {
             begin();
             checkConnect(fdVal);
             setConnected();
-            result.setResult(null);
         } catch (Throwable x) {
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
@@ -276,26 +256,38 @@
             try {
                 close();
             } catch (IOException ignore) { }
-            result.setFailure(e);
         }
-        if (invokeDirect) {
-            Invoker.invoke(result.handler(), result);
+
+
+        // invoke handler and set result
+        CompletionHandler<Void,Object> handler = connectHandler;
+        Object att = connectAttachment;
+        PendingFuture<Void,Object> future = connectFuture;
+        if (handler == null) {
+            future.setResult(null, e);
         } else {
-            Invoker.invokeIndirectly(result.handler(), result);
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, null, e);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, null, e);
+            }
         }
     }
 
     @Override
     @SuppressWarnings("unchecked")
-    public <A> Future<Void> connect(SocketAddress remote,
-                                    A attachment,
-                                    CompletionHandler<Void,? super A> handler)
+    <A> Future<Void> implConnect(SocketAddress remote,
+                                 A attachment,
+                                 CompletionHandler<Void,? super A> handler)
     {
         if (!isOpen()) {
-            CompletedFuture<Void,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable e = new ClosedChannelException();
+            if (handler == null) {
+                return CompletedFuture.withFailure(e);
+            } else {
+                Invoker.invoke(this, handler, attachment, null, e);
+                return null;
+            }
         }
 
         InetSocketAddress isa = Net.checkAddress(remote);
@@ -317,7 +309,6 @@
             notifyBeforeTcpConnect = (localAddress == null);
         }
 
-        AbstractFuture<Void,A> result = null;
         Throwable e = null;
         try {
             begin();
@@ -327,15 +318,21 @@
             int n = Net.connect(fd, isa.getAddress(), isa.getPort());
             if (n == IOStatus.UNAVAILABLE) {
                 // connection could not be established immediately
-                result = new PendingFuture<Void,A>(this, handler, attachment, OpType.CONNECT);
+                PendingFuture<Void,A> result = null;
                 synchronized (updateLock) {
-                    this.pendingConnect = (PendingFuture<Void,Object>)result;
+                    if (handler == null) {
+                        result = new PendingFuture<Void,A>(this, OpType.CONNECT);
+                        this.connectFuture = (PendingFuture<Void,Object>)result;
+                    } else {
+                        this.connectHandler = (CompletionHandler<Void,Object>)handler;
+                        this.connectAttachment = attachment;
+                    }
+                    this.connectPending = true;
                     updateEvents();
                 }
                 return result;
             }
             setConnected();
-            result = CompletedFuture.withResult(this, null, attachment);
         } catch (Throwable x) {
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
@@ -349,84 +346,111 @@
             try {
                 close();
             } catch (IOException ignore) { }
-            result = CompletedFuture.withFailure(this, e, attachment);
         }
-
-        Invoker.invoke(handler, result);
-        return result;
+        if (handler == null) {
+            return CompletedFuture.withResult(null, e);
+        } else {
+            Invoker.invoke(this, handler, attachment, null, e);
+            return null;
+        }
     }
 
     // -- read --
 
-    @SuppressWarnings("unchecked")
-    private void finishRead(PendingFuture<Number,Object> result,
-                            boolean invokeDirect)
-    {
+    private void finishRead(boolean mayInvokeDirect) {
         int n = -1;
-        PendingFuture<Number,Object> pending = null;
+        Throwable exc = null;
+
+        // copy fields as we can't access them after reading is re-enabled.
+        boolean scattering = isScatteringRead;
+        CompletionHandler<Number,Object> handler = readHandler;
+        Object att = readAttachment;
+        PendingFuture<Number,Object> future = readFuture;
+        Future<?> timeout = readTimer;
+
         try {
             begin();
 
-            ByteBuffer[] dsts = readBuffers;
-            if (dsts.length == 1) {
-                n = IOUtil.read(fd, dsts[0], -1, nd, null);
+            if (scattering) {
+                n = (int)IOUtil.read(fd, readBuffers, nd);
             } else {
-                n = (int)IOUtil.read(fd, dsts, nd);
+                n = IOUtil.read(fd, readBuffer, -1, nd, null);
             }
             if (n == IOStatus.UNAVAILABLE) {
                 // spurious wakeup, is this possible?
-                pending = result;
+                synchronized (updateLock) {
+                    readPending = true;
+                }
                 return;
             }
 
-            // allow buffer(s) to be GC'ed.
-            readBuffers = null;
+            // allow objects to be GC'ed.
+            this.readBuffer = null;
+            this.readBuffers = null;
+            this.readAttachment = null;
 
             // allow another read to be initiated
-            boolean wasScatteringRead = scatteringRead;
             enableReading();
 
-            // result is Integer or Long
-            if (wasScatteringRead) {
-                result.setResult(Long.valueOf(n));
-            } else {
-                result.setResult(Integer.valueOf(n));
-            }
-
         } catch (Throwable x) {
             enableReading();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            result.setFailure(x);
+            exc = x;
         } finally {
             // restart poll in case of concurrent write
             synchronized (updateLock) {
-                if (pending != null)
-                    this.pendingRead = pending;
                 updateEvents();
             }
             end();
         }
 
-        if (invokeDirect) {
-            Invoker.invoke(result.handler(), result);
+        // cancel the associated timer
+        if (timeout != null)
+            timeout.cancel(false);
+
+        // create result
+        Number result = (exc != null) ? null : (scattering) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // invoke handler or set result
+        if (handler == null) {
+            future.setResult(result, exc);
         } else {
-            Invoker.invokeIndirectly(result.handler(), result);
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, result, exc);
+            }
         }
     }
 
     private Runnable readTimeoutTask = new Runnable() {
         public void run() {
-            PendingFuture<Number,Object> result = grabPendingRead();
-            if (result == null)
-                return;     // already completed
+            CompletionHandler<Number,Object> handler = null;
+            Object att = null;
+            PendingFuture<Number,Object> future = null;
+
+            synchronized (updateLock) {
+                if (!readPending)
+                    return;
+                readPending = false;
+                handler = readHandler;
+                att = readAttachment;
+                future = readFuture;
+            }
 
             // kill further reading before releasing waiters
             enableReading(true);
 
-            // set completed and invoke handler
-            result.setFailure(new InterruptedByTimeoutException());
-            Invoker.invokeIndirectly(result.handler(), result);
+            // invoke handler or set result
+            Exception exc = new InterruptedByTimeoutException();
+            if (handler == null) {
+                future.setFailure(exc);
+            } else {
+                AsynchronousChannel ch = UnixAsynchronousSocketChannelImpl.this;
+                Invoker.invokeIndirectly(ch, handler, att, null, exc);
+            }
         }
     };
 
@@ -435,8 +459,9 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
-                                            boolean isScatteringRead,
+    <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+                                            ByteBuffer dst,
+                                            ByteBuffer[] dsts,
                                             long timeout,
                                             TimeUnit unit,
                                             A attachment,
@@ -450,144 +475,178 @@
         boolean invokeDirect = false;
         boolean attemptRead = false;
         if (!disableSynchronousRead) {
-            myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
-            invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
-            attemptRead = (handler == null) || invokeDirect ||
-                !port.isFixedThreadPool();  // okay to attempt read with user thread pool
+            if (handler == null) {
+                attemptRead = true;
+            } else {
+                myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
+                invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+                // okay to attempt read with user thread pool
+                attemptRead = invokeDirect || !port.isFixedThreadPool();
+            }
         }
 
-        AbstractFuture<V,A> result;
+        int n = IOStatus.UNAVAILABLE;
+        Throwable exc = null;
+        boolean pending = false;
+
         try {
             begin();
 
-            int n;
             if (attemptRead) {
                 if (isScatteringRead) {
                     n = (int)IOUtil.read(fd, dsts, nd);
                 } else {
-                    n = IOUtil.read(fd, dsts[0], -1, nd, null);
+                    n = IOUtil.read(fd, dst, -1, nd, null);
                 }
-            } else {
-                n = IOStatus.UNAVAILABLE;
             }
 
             if (n == IOStatus.UNAVAILABLE) {
-                result = new PendingFuture<V,A>(this, handler, attachment, OpType.READ);
-
-                // update evetns so that read will complete asynchronously
+                PendingFuture<V,A> result = null;
                 synchronized (updateLock) {
+                    this.isScatteringRead = isScatteringRead;
+                    this.readBuffer = dst;
                     this.readBuffers = dsts;
-                    this.scatteringRead = isScatteringRead;
-                    this.pendingRead = (PendingFuture<Number,Object>)result;
+                    if (handler == null) {
+                        this.readHandler = null;
+                        result = new PendingFuture<V,A>(this, OpType.READ);
+                        this.readFuture = (PendingFuture<Number,Object>)result;
+                        this.readAttachment = null;
+                    } else {
+                        this.readHandler = (CompletionHandler<Number,Object>)handler;
+                        this.readAttachment = attachment;
+                        this.readFuture = null;
+                    }
+                    if (timeout > 0L) {
+                        this.readTimer = port.schedule(readTimeoutTask, timeout, unit);
+                    }
+                    this.readPending = true;
                     updateEvents();
                 }
-
-                // schedule timeout
-                if (timeout > 0L) {
-                    Future<?> timeoutTask =
-                        port.schedule(readTimeoutTask, timeout, unit);
-                    ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
-                }
+                pending = true;
                 return result;
             }
-
-            // data available
-            enableReading();
-
-            // result type is Long or Integer
-            if (isScatteringRead) {
-                result = (CompletedFuture<V,A>)CompletedFuture
-                    .withResult(this, Long.valueOf(n), attachment);
-            } else {
-                result = (CompletedFuture<V,A>)CompletedFuture
-                    .withResult(this, Integer.valueOf(n), attachment);
-            }
         } catch (Throwable x) {
-            enableReading();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            result = CompletedFuture.withFailure(this, x, attachment);
+            exc = x;
         } finally {
+            if (!pending)
+                enableReading();
             end();
         }
 
-        if (invokeDirect) {
-            Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+        Number result = (exc != null) ? null : (isScatteringRead) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // read completed immediately
+        if (handler != null) {
+            if (invokeDirect) {
+                Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+            }
+            return null;
         } else {
-            Invoker.invokeIndirectly(handler, result);
+            return CompletedFuture.withResult((V)result, exc);
         }
-        return result;
     }
 
     // -- write --
 
-    private void finishWrite(PendingFuture<Number,Object> result,
-                             boolean invokeDirect)
-    {
-        PendingFuture<Number,Object> pending = null;
+    private void finishWrite(boolean mayInvokeDirect) {
+        int n = -1;
+        Throwable exc = null;
+
+        // copy fields as we can't access them after reading is re-enabled.
+        boolean gathering = this.isGatheringWrite;
+        CompletionHandler<Number,Object> handler = this.writeHandler;
+        Object att = this.writeAttachment;
+        PendingFuture<Number,Object> future = this.writeFuture;
+        Future<?> timer = this.writeTimer;
+
         try {
             begin();
 
-            ByteBuffer[] srcs = writeBuffers;
-            int n;
-            if (srcs.length == 1) {
-                n = IOUtil.write(fd, srcs[0], -1, nd, null);
+            if (gathering) {
+                n = (int)IOUtil.write(fd, writeBuffers, nd);
             } else {
-                n = (int)IOUtil.write(fd, srcs, nd);
+                n = IOUtil.write(fd, writeBuffer, -1, nd, null);
             }
             if (n == IOStatus.UNAVAILABLE) {
                 // spurious wakeup, is this possible?
-                pending = result;
+                synchronized (updateLock) {
+                    writePending = true;
+                }
                 return;
             }
 
-            // allow buffer(s) to be GC'ed.
-            writeBuffers = null;
+            // allow objects to be GC'ed.
+            this.writeBuffer = null;
+            this.writeBuffers = null;
+            this.writeAttachment = null;
 
             // allow another write to be initiated
-            boolean wasGatheringWrite = gatheringWrite;
             enableWriting();
 
-            // result is a Long or Integer
-            if (wasGatheringWrite) {
-                result.setResult(Long.valueOf(n));
-            } else {
-                result.setResult(Integer.valueOf(n));
-            }
-
         } catch (Throwable x) {
             enableWriting();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            result.setFailure(x);
+            exc = x;
         } finally {
-            // restart poll in case of concurrent read
-            synchronized (this) {
-                if (pending != null)
-                    this.pendingWrite = pending;
+            // restart poll in case of concurrent write
+            synchronized (updateLock) {
                 updateEvents();
             }
             end();
         }
-        if (invokeDirect) {
-            Invoker.invoke(result.handler(), result);
+
+        // cancel the associated timer
+        if (timer != null)
+            timer.cancel(false);
+
+        // create result
+        Number result = (exc != null) ? null : (gathering) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // invoke handler or set result
+        if (handler == null) {
+            future.setResult(result, exc);
         } else {
-            Invoker.invokeIndirectly(result.handler(), result);
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, result, exc);
+            }
         }
     }
 
     private Runnable writeTimeoutTask = new Runnable() {
         public void run() {
-            PendingFuture<Number,Object> result = grabPendingWrite();
-            if (result == null)
-                return;     // already completed
+            CompletionHandler<Number,Object> handler = null;
+            Object att = null;
+            PendingFuture<Number,Object> future = null;
+
+            synchronized (updateLock) {
+                if (!writePending)
+                    return;
+                writePending = false;
+                handler = writeHandler;
+                att = writeAttachment;
+                future = writeFuture;
+            }
 
             // kill further writing before releasing waiters
             enableWriting(true);
 
-            // set completed and invoke handler
-            result.setFailure(new InterruptedByTimeoutException());
-            Invoker.invokeIndirectly(result.handler(), result);
+            // invoke handler or set result
+            Exception exc = new InterruptedByTimeoutException();
+            if (handler != null) {
+                Invoker.invokeIndirectly(UnixAsynchronousSocketChannelImpl.this,
+                    handler, att, null, exc);
+            } else {
+                future.setFailure(exc);
+            }
         }
     };
 
@@ -596,8 +655,9 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
-                                             boolean isGatheringWrite,
+    <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+                                             ByteBuffer src,
+                                             ByteBuffer[] srcs,
                                              long timeout,
                                              TimeUnit unit,
                                              A attachment,
@@ -607,66 +667,72 @@
             Invoker.getGroupAndInvokeCount();
         boolean invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
         boolean attemptWrite = (handler == null) || invokeDirect ||
-            !port.isFixedThreadPool();  // okay to attempt read with user thread pool
+            !port.isFixedThreadPool();  // okay to attempt write with user thread pool
 
-        AbstractFuture<V,A> result;
+        int n = IOStatus.UNAVAILABLE;
+        Throwable exc = null;
+        boolean pending = false;
+
         try {
             begin();
 
-            int n;
             if (attemptWrite) {
                 if (isGatheringWrite) {
                     n = (int)IOUtil.write(fd, srcs, nd);
                 } else {
-                    n = IOUtil.write(fd, srcs[0], -1, nd, null);
+                    n = IOUtil.write(fd, src, -1, nd, null);
                 }
-            } else {
-                n = IOStatus.UNAVAILABLE;
             }
 
             if (n == IOStatus.UNAVAILABLE) {
-                result = new PendingFuture<V,A>(this, handler, attachment, OpType.WRITE);
-
-                // update evetns so that read will complete asynchronously
+                PendingFuture<V,A> result = null;
                 synchronized (updateLock) {
+                    this.isGatheringWrite = isGatheringWrite;
+                    this.writeBuffer = src;
                     this.writeBuffers = srcs;
-                    this.gatheringWrite = isGatheringWrite;
-                    this.pendingWrite = (PendingFuture<Number,Object>)result;
+                    if (handler == null) {
+                        this.writeHandler = null;
+                        result = new PendingFuture<V,A>(this, OpType.WRITE);
+                        this.writeFuture = (PendingFuture<Number,Object>)result;
+                        this.writeAttachment = null;
+                    } else {
+                        this.writeHandler = (CompletionHandler<Number,Object>)handler;
+                        this.writeAttachment = attachment;
+                        this.writeFuture = null;
+                    }
+                    if (timeout > 0L) {
+                        this.writeTimer = port.schedule(writeTimeoutTask, timeout, unit);
+                    }
+                    this.writePending = true;
                     updateEvents();
                 }
-
-                // schedule timeout
-                if (timeout > 0L) {
-                    Future<?> timeoutTask =
-                        port.schedule(writeTimeoutTask, timeout, unit);
-                    ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
-                }
+                pending = true;
                 return result;
             }
-
-            // data available
-            enableWriting();
-            if (isGatheringWrite) {
-                result = (CompletedFuture<V,A>)CompletedFuture
-                    .withResult(this, Long.valueOf(n), attachment);
-            } else {
-                result = (CompletedFuture<V,A>)CompletedFuture
-                    .withResult(this, Integer.valueOf(n), attachment);
-            }
         } catch (Throwable x) {
-            enableWriting();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
-            result = CompletedFuture.withFailure(this, x, attachment);
+            exc = x;
         } finally {
+            if (!pending)
+                enableWriting();
             end();
         }
-        if (invokeDirect) {
-            Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+
+        Number result = (exc != null) ? null : (isGatheringWrite) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // write completed immediately
+        if (handler != null) {
+            if (invokeDirect) {
+                Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+            }
+            return null;
         } else {
-            Invoker.invokeIndirectly(handler, result);
+            return CompletedFuture.withResult((V)result, exc);
         }
-        return result;
     }
 
     // -- Native methods --
--- a/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/solaris/classes/sun/nio/fs/UnixPath.java	Tue Sep 01 13:03:09 2009 -0700
@@ -65,9 +65,6 @@
     // array of offsets of elements in path (created lazily)
     private volatile int[] offsets;
 
-    // file permissions (created lazily)
-    private volatile FilePermission[] perms;
-
     UnixPath(UnixFileSystem fs, byte[] path) {
         this.fs = fs;
         this.path = path;
@@ -768,45 +765,23 @@
         }
     }
 
-    // create file permissions used for read and write checks
-    private void checkReadOrWrite(boolean checkRead) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm == null)
-            return;
-        if (perms == null) {
-            synchronized (this) {
-                if (perms == null) {
-                    FilePermission[] p = new FilePermission[2];
-                    String pathForPermCheck = getPathForPermissionCheck();
-                    p[0] = new FilePermission(pathForPermCheck,
-                        SecurityConstants.FILE_READ_ACTION);
-                    p[1] = new FilePermission(pathForPermCheck,
-                        SecurityConstants.FILE_WRITE_ACTION);
-                    perms = p;
-                }
-            }
-        }
-        if (checkRead) {
-            sm.checkPermission(perms[0]);
-        } else {
-            sm.checkPermission(perms[1]);
-        }
-    }
 
     void checkRead() {
-        checkReadOrWrite(true);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkRead(getPathForPermissionCheck());
     }
 
     void checkWrite() {
-        checkReadOrWrite(false);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkWrite(getPathForPermissionCheck());
     }
 
     void checkDelete() {
         SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            // permission not cached
+        if (sm != null)
             sm.checkDelete(getPathForPermissionCheck());
-        }
     }
 
     @Override
--- a/src/windows/classes/sun/nio/ch/Iocp.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/ch/Iocp.java	Tue Sep 01 13:03:09 2009 -0700
@@ -34,6 +34,8 @@
 import java.util.concurrent.*;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
 import sun.misc.Unsafe;
 
 /**
@@ -44,6 +46,7 @@
 class Iocp extends AsynchronousChannelGroupImpl {
     private static final Unsafe unsafe = Unsafe.getUnsafe();
     private static final long INVALID_HANDLE_VALUE  = -1L;
+    private static final boolean supportsThreadAgnosticIo;
 
     // maps completion key to channel
     private final ReadWriteLock keyToChannelLock = new ReentrantReadWriteLock();
@@ -87,6 +90,13 @@
         <V,A> PendingFuture<V,A> getByOverlapped(long overlapped);
     }
 
+    /**
+     * Indicates if this operating system supports thread agnostic I/O.
+     */
+    static boolean supportsThreadAgnosticIo() {
+        return supportsThreadAgnosticIo;
+    }
+
     // release all resources
     void implClose() {
         synchronized (this) {
@@ -216,8 +226,9 @@
             } while ((key == 0) || keyToChannel.containsKey(key));
 
             // associate with I/O completion port
-            if (handle != 0L)
+            if (handle != 0L) {
                 createIoCompletionPort(handle, port, key, 0);
+            }
 
             // setup mapping
             keyToChannel.put(key, ch);
@@ -282,7 +293,7 @@
         /**
          * Invoked if the I/O operation completes successfully.
          */
-        public void completed(int bytesTransferred);
+        public void completed(int bytesTransferred, boolean canInvokeDirect);
 
         /**
          * Invoked if the I/O operation fails.
@@ -305,6 +316,7 @@
         public void run() {
             Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
                 Invoker.getGroupAndInvokeCount();
+            boolean canInvokeDirect = (myGroupAndInvokeCount != null);
             CompletionStatus ioResult = new CompletionStatus();
             boolean replaceMe = false;
 
@@ -382,7 +394,7 @@
                     ResultHandler rh = (ResultHandler)result.getContext();
                     replaceMe = true; // (if error/exception then replace thread)
                     if (error == 0) {
-                        rh.completed(ioResult.bytesTransferred());
+                        rh.completed(ioResult.bytesTransferred(), canInvokeDirect);
                     } else {
                         rh.failed(error, translateErrorToIOException(error));
                     }
@@ -433,5 +445,11 @@
     static {
         Util.load();
         initIDs();
+
+        // thread agnostic I/O on Vista/2008 or newer
+        String osversion = AccessController.doPrivileged(
+            new GetPropertyAction("os.version"));
+        String vers[] = osversion.split("\\.");
+        supportsThreadAgnosticIo = Integer.parseInt(vers[0]) >= 6;
     }
 }
--- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -146,10 +146,12 @@
         // waits until all I/O operations have completed
         ioCache.close();
 
-        // disassociate from port and shutdown thread pool if not default
+        // disassociate from port
         iocp.disassociate(completionKey);
+
+        // for the non-default group close the port
         if (!isDefaultIocp)
-            iocp.shutdown();
+            iocp.detachFromThreadPool();
     }
 
     @Override
@@ -258,14 +260,18 @@
             }
 
             // invoke completion handler
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         @Override
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             // release waiters and invoke completion handler
             result.setResult(fli);
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         @Override
@@ -279,16 +285,16 @@
             } else {
                 result.setFailure(new AsynchronousCloseException());
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
     }
 
     @Override
-    public <A> Future<FileLock> lock(long position,
-                                     long size,
-                                     boolean shared,
-                                     A attachment,
-                                     CompletionHandler<FileLock,? super A> handler)
+    <A> Future<FileLock> implLock(final long position,
+                                  final long size,
+                                  final boolean shared,
+                                  A attachment,
+                                  final CompletionHandler<FileLock,? super A> handler)
     {
         if (shared && !reading)
             throw new NonReadableChannelException();
@@ -298,10 +304,11 @@
         // add to lock table
         FileLockImpl fli = addToFileLockTable(position, size, shared);
         if (fli == null) {
-            CompletedFuture<FileLock,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
         }
 
         // create Future and task that will be invoked to acquire lock
@@ -310,13 +317,20 @@
         LockTask lockTask = new LockTask<A>(position, fli, result);
         result.setContext(lockTask);
 
-        // initiate I/O (can only be done from thread in thread pool)
-        try {
-            Invoker.invokeOnThreadInThreadPool(this, lockTask);
-        } catch (ShutdownChannelGroupException e) {
-            // rollback
-            removeFromFileLockTable(fli);
-            throw e;
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            lockTask.run();
+        } else {
+            boolean executed = false;
+            try {
+                Invoker.invokeOnThreadInThreadPool(this, lockTask);
+                executed = true;
+            } finally {
+                if (!executed) {
+                    // rollback
+                    removeFromFileLockTable(fli);
+                }
+            }
         }
         return result;
     }
@@ -461,14 +475,14 @@
             releaseBufferIfSubstituted();
 
             // invoke completion handler
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
          * Executed when the I/O has completed
          */
         @Override
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             updatePosition(bytesTransferred);
 
             // return direct buffer to cache if substituted
@@ -476,14 +490,18 @@
 
             // release waiters and invoke completion handler
             result.setResult(bytesTransferred);
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         @Override
         public void failed(int error, IOException x) {
             // if EOF detected asynchronously then it is reported as error
             if (error == ERROR_HANDLE_EOF) {
-                completed(-1);
+                completed(-1, false);
             } else {
                 // return direct buffer to cache if substituted
                 releaseBufferIfSubstituted();
@@ -494,16 +512,16 @@
                 } else {
                     result.setFailure(new AsynchronousCloseException());
                 }
-                Invoker.invoke(result.handler(), result);
+                Invoker.invoke(result);
             }
         }
     }
 
     @Override
-    public <A> Future<Integer> read(ByteBuffer dst,
-                                    long position,
-                                    A attachment,
-                                    CompletionHandler<Integer,? super A> handler)
+    <A> Future<Integer> implRead(ByteBuffer dst,
+                                 long position,
+                                 A attachment,
+                                 CompletionHandler<Integer,? super A> handler)
     {
         if (!reading)
             throw new NonReadableChannelException();
@@ -514,10 +532,11 @@
 
         // check if channel is closed
         if (!isOpen()) {
-            CompletedFuture<Integer,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
         }
 
         int pos = dst.position();
@@ -527,10 +546,10 @@
 
         // no space remaining
         if (rem == 0) {
-            CompletedFuture<Integer,A> result =
-                CompletedFuture.withResult(this, 0, attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            if (handler == null)
+                return CompletedFuture.withResult(0);
+            Invoker.invoke(this, handler, attachment, 0, null);
+            return null;
         }
 
         // create Future and task that initiates read
@@ -539,8 +558,12 @@
         ReadTask readTask = new ReadTask<A>(dst, pos, rem, position, result);
         result.setContext(readTask);
 
-        // initiate I/O (can only be done from thread in thread pool)
-        Invoker.invokeOnThreadInThreadPool(this, readTask);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            readTask.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, readTask);
+        }
         return result;
     }
 
@@ -639,14 +662,14 @@
             }
 
             // invoke completion handler
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
          * Executed when the I/O has completed
          */
         @Override
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             updatePosition(bytesTransferred);
 
             // return direct buffer to cache if substituted
@@ -654,7 +677,11 @@
 
             // release waiters and invoke completion handler
             result.setResult(bytesTransferred);
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         @Override
@@ -668,15 +695,14 @@
             } else {
                 result.setFailure(new AsynchronousCloseException());
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
     }
 
-    @Override
-    public <A> Future<Integer> write(ByteBuffer src,
-                                     long position,
-                                     A attachment,
-                                     CompletionHandler<Integer,? super A> handler)
+    <A> Future<Integer> implWrite(ByteBuffer src,
+                                  long position,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler)
     {
         if (!writing)
             throw new NonWritableChannelException();
@@ -685,10 +711,11 @@
 
         // check if channel is closed
         if (!isOpen()) {
-            CompletedFuture<Integer,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+           Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
         }
 
         int pos = src.position();
@@ -698,10 +725,10 @@
 
         // nothing to write
         if (rem == 0) {
-            CompletedFuture<Integer,A> result =
-                CompletedFuture.withResult(this, 0, attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            if (handler == null)
+                return CompletedFuture.withResult(0);
+            Invoker.invoke(this, handler, attachment, 0, null);
+            return null;
         }
 
         // create Future and task to initiate write
@@ -710,8 +737,12 @@
         WriteTask writeTask = new WriteTask<A>(src, pos, rem, position, result);
         result.setContext(writeTask);
 
-        // initiate I/O (can only be done from thread in thread pool)
-        Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            writeTask.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        }
         return result;
     }
 
--- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -113,14 +113,14 @@
     /**
      * Task to initiate accept operation and to handle result.
      */
-    private class AcceptTask<A> implements Runnable, Iocp.ResultHandler {
+    private class AcceptTask implements Runnable, Iocp.ResultHandler {
         private final WindowsAsynchronousSocketChannelImpl channel;
         private final AccessControlContext acc;
-        private final PendingFuture<AsynchronousSocketChannel,A> result;
+        private final PendingFuture<AsynchronousSocketChannel,Object> result;
 
         AcceptTask(WindowsAsynchronousSocketChannelImpl channel,
                    AccessControlContext acc,
-                   PendingFuture<AsynchronousSocketChannel,A> result)
+                   PendingFuture<AsynchronousSocketChannel,Object> result)
         {
             this.channel = channel;
             this.acc = acc;
@@ -222,14 +222,14 @@
             }
 
             // invoke completion handler
-            Invoker.invokeIndirectly(result.handler(), result);
+            Invoker.invokeIndirectly(result);
         }
 
         /**
          * Executed when the I/O has completed
          */
         @Override
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             try {
                 // connection accept after group has shutdown
                 if (iocp.isShutdown()) {
@@ -269,7 +269,7 @@
             }
 
             // invoke handler (but not directly)
-            Invoker.invokeIndirectly(result.handler(), result);
+            Invoker.invokeIndirectly(result);
         }
 
         @Override
@@ -283,19 +283,20 @@
             } else {
                 result.setFailure(new AsynchronousCloseException());
             }
-            Invoker.invokeIndirectly(result.handler(), result);
+            Invoker.invokeIndirectly(result);
         }
     }
 
     @Override
-    public <A> Future<AsynchronousSocketChannel> accept(A attachment,
-        final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    Future<AsynchronousSocketChannel> implAccept(Object attachment,
+        final CompletionHandler<AsynchronousSocketChannel,Object> handler)
     {
         if (!isOpen()) {
-            CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invokeIndirectly(handler, result);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invokeIndirectly(this, handler, attachment, null, exc);
+            return null;
         }
         if (isAcceptKilled())
             throw new RuntimeException("Accept not allowed due to cancellation");
@@ -319,10 +320,10 @@
             end();
         }
         if (ioe != null) {
-            CompletedFuture<AsynchronousSocketChannel,A> result =
-                CompletedFuture.withFailure(this, ioe, attachment);
-            Invoker.invokeIndirectly(handler, result);
-            return result;
+            if (handler == null)
+                return CompletedFuture.withFailure(ioe);
+            Invoker.invokeIndirectly(this, handler, attachment, null, ioe);
+            return null;
         }
 
         // need calling context when there is security manager as
@@ -331,20 +332,21 @@
         AccessControlContext acc = (System.getSecurityManager() == null) ?
             null : AccessController.getContext();
 
-        PendingFuture<AsynchronousSocketChannel,A> result =
-            new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
-        AcceptTask task = new AcceptTask<A>(ch, acc, result);
+        PendingFuture<AsynchronousSocketChannel,Object> result =
+            new PendingFuture<AsynchronousSocketChannel,Object>(this, handler, attachment);
+        AcceptTask task = new AcceptTask(ch, acc, result);
         result.setContext(task);
 
         // check and set flag to prevent concurrent accepting
         if (!accepting.compareAndSet(false, true))
             throw new AcceptPendingException();
 
-        // initiate accept. As I/O operations are tied to the initiating thread
-        // then it will only be invoked direcly if this thread is in the thread
-        // pool. If this thread is not in the thread pool when a task is
-        // submitted to initiate the accept.
-        Invoker.invokeOnThreadInThreadPool(this, task);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            task.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, task);
+        }
         return result;
     }
 
--- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Tue Sep 01 13:03:09 2009 -0700
@@ -250,14 +250,14 @@
                 closeChannel();
                 result.setFailure(toIOException(exc));
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
          * Invoked by handler thread when connection established.
          */
         @Override
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             Throwable exc = null;
             try {
                 begin();
@@ -276,7 +276,11 @@
                 result.setFailure(toIOException(exc));
             }
 
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         /**
@@ -290,20 +294,21 @@
             } else {
                 result.setFailure(new AsynchronousCloseException());
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
     }
 
     @Override
-    public <A> Future<Void> connect(SocketAddress remote,
-                                    A attachment,
-                                    CompletionHandler<Void,? super A> handler)
+    <A> Future<Void> implConnect(SocketAddress remote,
+                                 A attachment,
+                                 CompletionHandler<Void,? super A> handler)
     {
         if (!isOpen()) {
-            CompletedFuture<Void,A> result = CompletedFuture
-                .withFailure(this, new ClosedChannelException(), attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            Throwable exc = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(exc);
+            Invoker.invoke(this, handler, attachment, null, exc);
+            return null;
         }
 
         InetSocketAddress isa = Net.checkAddress(remote);
@@ -337,10 +342,10 @@
             try {
                 close();
             } catch (IOException ignore) { }
-            CompletedFuture<Void,A> result = CompletedFuture
-                .withFailure(this, bindException, attachment);
-            Invoker.invoke(handler, result);
-            return result;
+            if (handler == null)
+                return CompletedFuture.withFailure(bindException);
+            Invoker.invoke(this, handler, attachment, null, bindException);
+            return null;
         }
 
         // setup task
@@ -349,8 +354,12 @@
         ConnectTask task = new ConnectTask<A>(isa, result);
         result.setContext(task);
 
-        // initiate I/O (can only be done from thread in thread pool)
-        Invoker.invokeOnThreadInThreadPool(this, task);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            task.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, task);
+        }
         return result;
     }
 
@@ -514,7 +523,7 @@
             }
 
             // invoke completion handler
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
@@ -522,7 +531,7 @@
          */
         @Override
         @SuppressWarnings("unchecked")
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             if (bytesTransferred == 0) {
                 bytesTransferred = -1;  // EOF
             } else {
@@ -543,7 +552,11 @@
                     result.setResult((V)Integer.valueOf(bytesTransferred));
                 }
             }
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         @Override
@@ -561,7 +574,7 @@
                 enableReading();
                 result.setFailure(x);
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
@@ -579,13 +592,14 @@
             }
 
             // invoke handler without any locks
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
     }
 
     @Override
-    <V extends Number,A> Future<V> readImpl(ByteBuffer[] bufs,
-                                            boolean scatteringRead,
+    <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+                                            ByteBuffer dst,
+                                            ByteBuffer[] dsts,
                                             long timeout,
                                             TimeUnit unit,
                                             A attachment,
@@ -594,7 +608,14 @@
         // setup task
         PendingFuture<V,A> result =
             new PendingFuture<V,A>(this, handler, attachment);
-        final ReadTask readTask = new ReadTask<V,A>(bufs, scatteringRead, result);
+        ByteBuffer[] bufs;
+        if (isScatteringRead) {
+            bufs = dsts;
+        } else {
+            bufs = new ByteBuffer[1];
+            bufs[0] = dst;
+        }
+        final ReadTask readTask = new ReadTask<V,A>(bufs, isScatteringRead, result);
         result.setContext(readTask);
 
         // schedule timeout
@@ -607,8 +628,12 @@
             result.setTimeoutTask(timeoutTask);
         }
 
-        // initiate I/O (can only be done from thread in thread pool)
-        Invoker.invokeOnThreadInThreadPool(this, readTask);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            readTask.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, readTask);
+        }
         return result;
     }
 
@@ -710,7 +735,7 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
+        //@SuppressWarnings("unchecked")
         public void run() {
             long overlapped = 0L;
             boolean prepared = false;
@@ -759,7 +784,7 @@
             }
 
             // invoke completion handler
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
@@ -767,7 +792,7 @@
          */
         @Override
         @SuppressWarnings("unchecked")
-        public void completed(int bytesTransferred) {
+        public void completed(int bytesTransferred, boolean canInvokeDirect) {
             updateBuffers(bytesTransferred);
 
             // return direct buffer to cache if substituted
@@ -784,7 +809,11 @@
                     result.setResult((V)Integer.valueOf(bytesTransferred));
                 }
             }
-            Invoker.invoke(result.handler(), result);
+            if (canInvokeDirect) {
+                Invoker.invokeUnchecked(result);
+            } else {
+                Invoker.invoke(result);
+            }
         }
 
         @Override
@@ -802,7 +831,7 @@
                 enableWriting();
                 result.setFailure(x);
             }
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
 
         /**
@@ -820,13 +849,14 @@
             }
 
             // invoke handler without any locks
-            Invoker.invoke(result.handler(), result);
+            Invoker.invoke(result);
         }
     }
 
     @Override
-    <V extends Number,A> Future<V> writeImpl(ByteBuffer[] bufs,
-                                             boolean gatheringWrite,
+    <V extends Number,A> Future<V> implWrite(boolean gatheringWrite,
+                                             ByteBuffer src,
+                                             ByteBuffer[] srcs,
                                              long timeout,
                                              TimeUnit unit,
                                              A attachment,
@@ -835,6 +865,13 @@
         // setup task
         PendingFuture<V,A> result =
             new PendingFuture<V,A>(this, handler, attachment);
+        ByteBuffer[] bufs;
+        if (gatheringWrite) {
+            bufs = srcs;
+        } else {
+            bufs = new ByteBuffer[1];
+            bufs[0] = src;
+        }
         final WriteTask writeTask = new WriteTask<V,A>(bufs, gatheringWrite, result);
         result.setContext(writeTask);
 
@@ -849,7 +886,12 @@
         }
 
         // initiate I/O (can only be done from thread in thread pool)
-        Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        // initiate I/O
+        if (Iocp.supportsThreadAgnosticIo()) {
+            writeTask.run();
+        } else {
+            Invoker.invokeOnThreadInThreadPool(this, writeTask);
+        }
         return result;
     }
 
--- a/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Tue Sep 01 13:03:09 2009 -0700
@@ -46,6 +46,7 @@
 
         @Override
         public WindowsFileAttributes readAttributes() throws IOException {
+            file.checkRead();
             try {
                 return WindowsFileAttributes.get(file, followLinks);
             } catch (WindowsException x) {
--- a/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Tue Sep 01 13:03:09 2009 -0700
@@ -246,8 +246,8 @@
         long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME);
         long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
             + (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
-        int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ?
-            + unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
+        int reparseTag = isReparsePoint(fileAttrs) ?
+            unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
         return new WindowsFileAttributes(fileAttrs,
                                          creationTime,
                                          lastAccessTime,
@@ -275,7 +275,7 @@
             int reparseTag = 0;
             int fileAttrs = unsafe
                 .getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
-            if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
+            if (isReparsePoint(fileAttrs)) {
                 int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
                 NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size);
                 try {
@@ -311,7 +311,7 @@
                 // just return the attributes
                 int fileAttrs = unsafe
                     .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
-                if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+                if (!isReparsePoint(fileAttrs))
                     return fromFileAttributeData(address, 0);
             } catch (WindowsException x) {
                 if (x.lastError() != ERROR_SHARING_VIOLATION)
@@ -358,7 +358,7 @@
     }
 
     /**
-     * Returns true if the attribtues are of the same file - both files must
+     * Returns true if the attributes are of the same file - both files must
      * be open.
      */
     static boolean isSameFile(WindowsFileAttributes attrs1,
@@ -370,6 +370,13 @@
                (attrs1.fileIndexLow == attrs2.fileIndexLow);
     }
 
+    /**
+     * Returns true if the attributes are of a file with a reparse point.
+     */
+    static boolean isReparsePoint(int attributes) {
+        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+    }
+
     // package-private
     int attributes() {
         return fileAttrs;
@@ -420,7 +427,7 @@
 
     // package private
     boolean isReparsePoint() {
-        return (fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+        return isReparsePoint(fileAttrs);
     }
 
     boolean isDirectoryLink() {
--- a/src/windows/classes/sun/nio/fs/WindowsFileSystem.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/fs/WindowsFileSystem.java	Tue Sep 01 13:03:09 2009 -0700
@@ -283,25 +283,15 @@
             }
         }
 
-        // match in uppercase
-        StringBuilder sb = new StringBuilder(expr.length());
-        for (int i=0; i<expr.length(); i++) {
-            sb.append(Character.toUpperCase(expr.charAt(i)));
-        }
-        expr = sb.toString();
+        // match in unicode_case_insensitive
+        final Pattern pattern = Pattern.compile(expr,
+            Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
 
         // return matcher
-        final Pattern pattern = Pattern.compile(expr);
         return new PathMatcher() {
             @Override
             public boolean matches(Path path) {
-                // match in uppercase
-                String s = path.toString();
-                StringBuilder sb = new StringBuilder(s.length());
-                for (int i=0; i<s.length(); i++) {
-                    sb.append( Character.toUpperCase(s.charAt(i)) );
-                }
-                return pattern.matcher(sb).matches();
+                return pattern.matcher(path.toString()).matches();
             }
         };
     }
--- a/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Tue Sep 01 13:03:09 2009 -0700
@@ -63,6 +63,30 @@
     }
 
     /**
+     * Returns the final path (all symbolic links resolved) or null if this
+     * operation is not supported.
+     */
+    private static String getFinalPath(WindowsPath input) throws IOException {
+        long h = 0;
+        try {
+            h = input.openForReadAttributeAccess(true);
+        } catch (WindowsException x) {
+            x.rethrowAsIOException(input);
+        }
+        try {
+            return stripPrefix(GetFinalPathNameByHandle(h));
+        } catch (WindowsException x) {
+            // ERROR_INVALID_LEVEL is the error returned when not supported
+            // (a sym link to file on FAT32 or Samba server for example)
+            if (x.lastError() != ERROR_INVALID_LEVEL)
+                x.rethrowAsIOException(input);
+        } finally {
+            CloseHandle(h);
+        }
+        return null;
+    }
+
+    /**
      * Returns the final path of a given path as a String. This should be used
      * prior to calling Win32 system calls that do not follow links.
      */
@@ -70,7 +94,6 @@
         throws IOException
     {
         WindowsFileSystem fs = input.getFileSystem();
-
         try {
             // if not following links then don't need final path
             if (!followLinks || !fs.supportsLinks())
@@ -84,25 +107,10 @@
             x.rethrowAsIOException(input);
         }
 
-        // The file is a symbolic link so we open it and try to get the
-        // normalized path. This should succeed on NTFS but may fail if there
-        // is a link to a non-NFTS file system.
-        long h = 0;
-        try {
-            h = input.openForReadAttributeAccess(true);
-        } catch (WindowsException x) {
-            x.rethrowAsIOException(input);
-        }
-        try {
-            return stripPrefix(GetFinalPathNameByHandle(h));
-        } catch (WindowsException x) {
-            // ERROR_INVALID_LEVEL is the error returned when not supported by
-            // the file system
-            if (x.lastError() != ERROR_INVALID_LEVEL)
-                x.rethrowAsIOException(input);
-        } finally {
-            CloseHandle(h);
-        }
+        // The file is a symbolic link so attempt to get the final path
+        String result = getFinalPath(input);
+        if (result != null)
+            return result;
 
         // Fallback: read target of link, resolve against parent, and repeat
         // until file is not a link.
@@ -149,31 +157,9 @@
         throws IOException
     {
         WindowsFileSystem fs = input.getFileSystem();
-        if (!fs.supportsLinks())
+        if (resolveLinks && !fs.supportsLinks())
             resolveLinks = false;
 
-        // On Vista use GetFinalPathNameByHandle. This should succeed on NTFS
-        // but may fail if there is a link to a non-NFTS file system.
-        if (resolveLinks) {
-            long h = 0;
-            try {
-                h = input.openForReadAttributeAccess(true);
-            } catch (WindowsException x) {
-                x.rethrowAsIOException(input);
-            }
-            try {
-                return stripPrefix(GetFinalPathNameByHandle(h));
-            } catch (WindowsException x) {
-                if (x.lastError() != ERROR_INVALID_LEVEL)
-                    x.rethrowAsIOException(input);
-            } finally {
-                CloseHandle(h);
-            }
-        }
-
-        // Not resolving links or we are on Windows Vista (or newer) with a
-        // link to non-NFTS file system.
-
         // Start with absolute path
         String path = null;
         try {
@@ -183,15 +169,12 @@
         }
 
         // Collapse "." and ".."
-        try {
-            path = GetFullPathName(path);
-        } catch (WindowsException x) {
-            x.rethrowAsIOException(input);
-        }
-
-        // eliminate all symbolic links
-        if (resolveLinks) {
-            path = resolveAllLinks(WindowsPath.createFromNormalizedPath(fs, path));
+        if (path.indexOf('.') >= 0) {
+            try {
+                path = GetFullPathName(path);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(input);
+            }
         }
 
         // string builder to build up components of path
@@ -229,12 +212,15 @@
             throw new AssertionError("path type not recognized");
         }
 
-        // check root directory exists
-        try {
-            FirstFile fileData = FindFirstFile(sb.toString() + "*");
-            FindClose(fileData.handle());
-        } catch (WindowsException x) {
-            x.rethrowAsIOException(path);
+        // if the result is only a root component then we simply check it exists
+        if (start >= path.length()) {
+            String result = sb.toString();
+            try {
+                GetFileAttributes(result);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(path);
+            }
+            return result;
         }
 
         // iterate through each component to get its actual name in the
@@ -246,13 +232,28 @@
             String search = sb.toString() + path.substring(curr, end);
             try {
                 FirstFile fileData = FindFirstFile(addLongPathPrefixIfNeeded(search));
-                try {
-                    sb.append(fileData.name());
-                    if (next != -1) {
-                        sb.append('\\');
+                FindClose(fileData.handle());
+
+                // if a reparse point is encountered then we must return the
+                // final path.
+                if (resolveLinks &&
+                    WindowsFileAttributes.isReparsePoint(fileData.attributes()))
+                {
+                    String result = getFinalPath(input);
+                    if (result == null) {
+                        // Fallback to slow path, usually because there is a sym
+                        // link to a file system that doesn't support sym links.
+                        WindowsPath resolved = resolveAllLinks(
+                            WindowsPath.createFromNormalizedPath(fs, path));
+                        result = getRealPath(resolved, false);
                     }
-                } finally {
-                    FindClose(fileData.handle());
+                    return result;
+                }
+
+                // add the name to the result
+                sb.append(fileData.name());
+                if (next != -1) {
+                    sb.append('\\');
                 }
             } catch (WindowsException e) {
                 e.rethrowAsIOException(path);
@@ -342,7 +343,7 @@
     /**
      * Resolve all symbolic-links in a given absolute and normalized path
      */
-    private static String resolveAllLinks(WindowsPath path)
+    private static WindowsPath resolveAllLinks(WindowsPath path)
         throws IOException
     {
         assert path.isAbsolute();
@@ -401,7 +402,7 @@
             }
         }
 
-        return path.toString();
+        return path;
     }
 
     /**
--- a/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Tue Sep 01 13:03:09 2009 -0700
@@ -180,10 +180,12 @@
     static class FirstFile {
         private long handle;
         private String name;
+        private int attributes;
 
         private FirstFile() { }
         public long handle()    { return handle; }
         public String name()    { return name; }
+        public int attributes() { return attributes; }
     }
     private static native void FindFirstFile0(long lpFileName, FirstFile obj)
         throws WindowsException;
--- a/src/windows/native/java/io/WinNTFileSystem_md.c	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/native/java/io/WinNTFileSystem_md.c	Tue Sep 01 13:03:09 2009 -0700
@@ -51,13 +51,25 @@
     jfieldID path;
 } ids;
 
+/**
+ * GetFinalPathNameByHandle is available on Windows Vista and newer
+ */
+typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
+static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
+
 JNIEXPORT void JNICALL
 Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
 {
+    HANDLE handle;
     jclass fileClass = (*env)->FindClass(env, "java/io/File");
     if (!fileClass) return;
     ids.path =
              (*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
+    handle = LoadLibrary("kernel32");
+    if (handle != NULL) {
+        GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)
+            GetProcAddress(handle, "GetFinalPathNameByHandleW");
+    }
 }
 
 /* -- Path operations -- */
@@ -65,6 +77,138 @@
 extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
 extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
 
+/**
+ * Retrieves the fully resolved (final) path for the given path or NULL
+ * if the function fails.
+ */
+static WCHAR* getFinalPath(const WCHAR *path)
+{
+    HANDLE h;
+    WCHAR *result;
+    DWORD error;
+
+    /* Need Windows Vista or newer to get the final path */
+    if (GetFinalPathNameByHandle_func == NULL)
+        return NULL;
+
+    h = CreateFileW(path,
+                    FILE_READ_ATTRIBUTES,
+                    FILE_SHARE_DELETE |
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    NULL,
+                    OPEN_EXISTING,
+                    FILE_FLAG_BACKUP_SEMANTICS,
+                    NULL);
+    if (h == INVALID_HANDLE_VALUE)
+        return NULL;
+
+    /**
+     * Allocate a buffer for the resolved path. For a long path we may need
+     * to allocate a larger buffer.
+     */
+    result = (WCHAR*)malloc(MAX_PATH * sizeof(WCHAR));
+    if (result != NULL) {
+        DWORD len = (*GetFinalPathNameByHandle_func)(h, result, MAX_PATH, 0);
+        if (len >= MAX_PATH) {
+            /* retry with a buffer of the right size */
+            result = (WCHAR*)realloc(result, (len+1) * sizeof(WCHAR));
+            if (result != NULL) {
+                len = (*GetFinalPathNameByHandle_func)(h, result, len, 0);
+            } else {
+                len = 0;
+            }
+        }
+        if (len > 0) {
+            /**
+             * Strip prefix (should be \\?\ or \\?\UNC)
+             */
+            if (result[0] == L'\\' && result[1] == L'\\' &&
+                result[2] == L'?' && result[3] == L'\\')
+            {
+                int isUnc = (result[4] == L'U' &&
+                             result[5] == L'N' &&
+                             result[6] == L'C');
+                int prefixLen = (isUnc) ? 7 : 4;
+                /* actual result length (includes terminator) */
+                int resultLen = len - prefixLen + (isUnc ? 1 : 0) + 1;
+
+                /* copy result without prefix into new buffer */
+                WCHAR *tmp = (WCHAR*)malloc(resultLen * sizeof(WCHAR));
+                if (tmp == NULL) {
+                    len = 0;
+                } else {
+                    WCHAR *p = result;
+                    p += prefixLen;
+                    if (isUnc) {
+                        WCHAR *p2 = tmp;
+                        p2[0] = L'\\';
+                        p2++;
+                        wcscpy(p2, p);
+                    } else {
+                        wcscpy(tmp, p);
+                    }
+                    free(result);
+                    result = tmp;
+                }
+            }
+        }
+
+        /* unable to get final path */
+        if (len == 0 && result != NULL) {
+            free(result);
+            result = NULL;
+        }
+    }
+
+    error = GetLastError();
+    if (CloseHandle(h))
+        SetLastError(error);
+    return result;
+}
+
+/**
+ * Retrieves file information for the specified file. If the file is
+ * symbolic link then the information on fully resolved target is
+ * returned.
+ */
+static BOOL getFileInformation(const WCHAR *path,
+                               BY_HANDLE_FILE_INFORMATION *finfo)
+{
+    BOOL result;
+    DWORD error;
+    HANDLE h = CreateFileW(path,
+                           FILE_READ_ATTRIBUTES,
+                           FILE_SHARE_DELETE |
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL,
+                           OPEN_EXISTING,
+                           FILE_FLAG_BACKUP_SEMANTICS,
+                           NULL);
+    if (h == INVALID_HANDLE_VALUE)
+        return FALSE;
+    result = GetFileInformationByHandle(h, finfo);
+    error = GetLastError();
+    if (CloseHandle(h))
+        SetLastError(error);
+    return result;
+}
+
+/**
+ * If the given attributes are the attributes of a reparse point, then
+ * read and return the attributes of the final target.
+ */
+DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
+{
+    if ((a != INVALID_FILE_ATTRIBUTES) &&
+        ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+    {
+        BY_HANDLE_FILE_INFORMATION finfo;
+        BOOL res = getFileInformation(path, &finfo);
+        a = (res) ? finfo.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
+    }
+    return a;
+}
+
 JNIEXPORT jstring JNICALL
 Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
                                            jstring pathname)
@@ -202,12 +346,15 @@
         return rv;
     if (!isReservedDeviceNameW(pathbuf)) {
         if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
-            rv = (java_io_FileSystem_BA_EXISTS
-                  | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                     ? java_io_FileSystem_BA_DIRECTORY
-                     : java_io_FileSystem_BA_REGULAR)
-                  | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
-                     ? java_io_FileSystem_BA_HIDDEN : 0));
+            DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
+            if (a != INVALID_FILE_ATTRIBUTES) {
+                rv = (java_io_FileSystem_BA_EXISTS
+                    | ((a & FILE_ATTRIBUTE_DIRECTORY)
+                        ? java_io_FileSystem_BA_DIRECTORY
+                        : java_io_FileSystem_BA_REGULAR)
+                    | ((a & FILE_ATTRIBUTE_HIDDEN)
+                        ? java_io_FileSystem_BA_HIDDEN : 0));
+            }
         } else { /* pagefile.sys is a special case */
             if (GetLastError() == ERROR_SHARING_VIOLATION) {
                 rv = java_io_FileSystem_BA_EXISTS;
@@ -234,6 +381,7 @@
     if (pathbuf == NULL)
         return JNI_FALSE;
     attr = GetFileAttributesW(pathbuf);
+    attr = getFinalAttributesIfReparsePoint(pathbuf, attr);
     free(pathbuf);
     if (attr == INVALID_FILE_ATTRIBUTES)
         return JNI_FALSE;
@@ -272,6 +420,20 @@
     if (pathbuf == NULL)
         return JNI_FALSE;
     a = GetFileAttributesW(pathbuf);
+
+    /* if reparse point, get final target */
+    if ((a != INVALID_FILE_ATTRIBUTES) &&
+        ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+    {
+        WCHAR *fp = getFinalPath(pathbuf);
+        if (fp == NULL) {
+            a = INVALID_FILE_ATTRIBUTES;
+        } else {
+            free(pathbuf);
+            pathbuf = fp;
+            a = GetFileAttributesW(pathbuf);
+        }
+    }
     if (a != INVALID_FILE_ATTRIBUTES) {
         if (enable)
             a =  a & ~FILE_ATTRIBUTE_READONLY;
@@ -305,7 +467,7 @@
                     /* Open existing or fail */
                     OPEN_EXISTING,
                     /* Backup semantics for directories */
-                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+                    FILE_FLAG_BACKUP_SEMANTICS,
                     /* No template file */
                     NULL);
     if (h != INVALID_HANDLE_VALUE) {
@@ -332,7 +494,16 @@
     if (GetFileAttributesExW(pathbuf,
                              GetFileExInfoStandard,
                              &wfad)) {
-        rv = wfad.nFileSizeHigh * ((jlong)MAXDWORD + 1) + wfad.nFileSizeLow;
+        if ((wfad.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
+            rv = wfad.nFileSizeHigh * ((jlong)MAXDWORD + 1) + wfad.nFileSizeLow;
+        } else {
+            /* file is a reparse point so read attributes of final target */
+            BY_HANDLE_FILE_INFORMATION finfo;
+            if (getFileInformation(pathbuf, &finfo)) {
+                rv = finfo.nFileSizeHigh * ((jlong)MAXDWORD + 1) +
+                    finfo.nFileSizeLow;
+            }
+        }
     } else {
         if (GetLastError() == ERROR_SHARING_VIOLATION) {
             /* The error is "share violation", which means the file/dir
@@ -360,31 +531,29 @@
     if (pathbuf == NULL)
         return JNI_FALSE;
     h = CreateFileW(
-        pathbuf,                             /* Wide char path name */
-        GENERIC_READ | GENERIC_WRITE,  /* Read and write permission */
+        pathbuf,                              /* Wide char path name */
+        GENERIC_READ | GENERIC_WRITE,         /* Read and write permission */
         FILE_SHARE_READ | FILE_SHARE_WRITE,   /* File sharing flags */
-        NULL,                                /* Security attributes */
-        CREATE_NEW,                         /* creation disposition */
-        FILE_ATTRIBUTE_NORMAL,              /* flags and attributes */
+        NULL,                                 /* Security attributes */
+        CREATE_NEW,                           /* creation disposition */
+        FILE_ATTRIBUTE_NORMAL |
+            FILE_FLAG_OPEN_REPARSE_POINT,     /* flags and attributes */
         NULL);
 
     if (h == INVALID_HANDLE_VALUE) {
         DWORD error = GetLastError();
         if ((error != ERROR_FILE_EXISTS) && (error != ERROR_ALREADY_EXISTS)) {
-
-            // If a directory by the named path already exists,
-            // return false (behavior of solaris and linux) instead of
-            // throwing an exception
-            DWORD fattr = GetFileAttributesW(pathbuf);
-            if ((fattr == INVALID_FILE_ATTRIBUTES) ||
-                    (fattr & ~FILE_ATTRIBUTE_DIRECTORY)) {
+            // return false rather than throwing an exception when there is
+            // an existing file.
+            DWORD a = GetFileAttributesW(pathbuf);
+            if (a == INVALID_FILE_ATTRIBUTES) {
                 SetLastError(error);
                 JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
             }
          }
          free(pathbuf);
          return JNI_FALSE;
-    }
+        }
     free(pathbuf);
     CloseHandle(h);
     return JNI_TRUE;
@@ -396,9 +565,9 @@
     /* Returns 0 on success */
     DWORD a;
 
-    SetFileAttributesW(path, 0);
+    SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
     a = GetFileAttributesW(path);
-    if (a == ((DWORD)-1)) {
+    if (a == INVALID_FILE_ATTRIBUTES) {
         return 1;
     } else if (a & FILE_ATTRIBUTE_DIRECTORY) {
         return !RemoveDirectoryW(path);
@@ -578,8 +747,13 @@
     HANDLE h;
     if (pathbuf == NULL)
         return JNI_FALSE;
-    h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
-                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
+    h = CreateFileW(pathbuf,
+                    FILE_WRITE_ATTRIBUTES,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    NULL,
+                    OPEN_EXISTING,
+                    FILE_FLAG_BACKUP_SEMANTICS,
+                    0);
     if (h != INVALID_HANDLE_VALUE) {
         LARGE_INTEGER modTime;
         FILETIME t;
@@ -607,6 +781,21 @@
     if (pathbuf == NULL)
         return JNI_FALSE;
     a = GetFileAttributesW(pathbuf);
+
+    /* if reparse point, get final target */
+    if ((a != INVALID_FILE_ATTRIBUTES) &&
+        ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+    {
+        WCHAR *fp = getFinalPath(pathbuf);
+        if (fp == NULL) {
+            a = INVALID_FILE_ATTRIBUTES;
+        } else {
+            free(pathbuf);
+            pathbuf = fp;
+            a = GetFileAttributesW(pathbuf);
+        }
+    }
+
     if (a != INVALID_FILE_ATTRIBUTES) {
         if (SetFileAttributesW(pathbuf, a | FILE_ATTRIBUTE_READONLY))
         rv = JNI_TRUE;
--- a/src/windows/native/sun/nio/ch/Iocp.c	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/native/sun/nio/ch/Iocp.c	Tue Sep 01 13:03:09 2009 -0700
@@ -58,6 +58,16 @@
     completionStatus_overlapped = (*env)->GetFieldID(env, clazz, "overlapped", "J");
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Iocp_osMajorVersion(JNIEnv* env, jclass this)
+{
+    OSVERSIONINFOEX ver;
+    ver.dwOSVersionInfoSize = sizeof(ver);
+    GetVersionEx((OSVERSIONINFO *) &ver);
+    return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) ?
+        (jint)(ver.dwMajorVersion) : (jint)0;
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this,
     jlong handle, jlong existingPort, jint completionKey, jint concurrency)
--- a/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Mon Aug 24 17:26:09 2009 -0700
+++ b/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Tue Sep 01 13:03:09 2009 -0700
@@ -48,6 +48,7 @@
  */
 static jfieldID findFirst_handle;
 static jfieldID findFirst_name;
+static jfieldID findFirst_attributes;
 
 static jfieldID findStream_handle;
 static jfieldID findStream_name;
@@ -134,6 +135,7 @@
     }
     findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
     findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
+    findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I");
 
     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream");
     if (clazz == NULL) {
@@ -371,6 +373,7 @@
             return;
         (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
         (*env)->SetObjectField(env, obj, findFirst_name, name);
+        (*env)->SetIntField(env, obj, findFirst_attributes, data.dwFileAttributes);
     } else {
         throwWindowsException(env, GetLastError());
     }
@@ -387,7 +390,7 @@
     if (handle == INVALID_HANDLE_VALUE) {
         throwWindowsException(env, GetLastError());
     }
-        return ptr_to_jlong(handle);
+    return ptr_to_jlong(handle);
 }
 
 JNIEXPORT jstring JNICALL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/security/auth/callback/TextCallbackHandler/Password.java	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6825240
+ * @summary Password.readPassword() echos the input when System.Console is null
+ * @ignore run these by hand
+ */
+
+import com.sun.security.auth.callback.TextCallbackHandler;
+import javax.security.auth.callback.*;
+
+public class Password {
+   public static void main(String args[]) throws Exception {
+        TextCallbackHandler h = new TextCallbackHandler();
+        PasswordCallback nc = new PasswordCallback("Invisible: ", false);
+        PasswordCallback nc2 = new PasswordCallback("Visible: ", true);
+
+        System.out.println("Two passwords will be prompted for. The first one " +
+                "should have echo off, the second one on. Otherwise, this test fails");
+        Callback[] callbacks = { nc, nc2 };
+        h.handle(callbacks);
+        System.out.println("You input " + new String(nc.getPassword()) +
+                " and " + new String(nc2.getPassword()));
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/io/File/SymLinks.java	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6595866
+ * @summary Test java.io.File operations with sym links
+ */
+
+import java.io.*;
+import java.nio.file.Path;
+import java.nio.file.attribute.*;
+import static java.nio.file.LinkOption.*;
+
+public class SymLinks {
+    final static PrintStream out = System.out;
+
+    final static File top = new File(System.getProperty("test.dir", "."));
+
+    // files used by the test
+
+    final static File file              = new File(top, "foofile");
+    final static File link2file         = new File(top, "link2file");
+    final static File link2link2file    = new File(top, "link2link2file");
+
+    final static File dir               = new File(top, "foodir");
+    final static File link2dir          = new File(top, "link2dir");
+    final static File link2link2dir     = new File(top, "link2link2dir");
+
+    final static File link2nobody       = new File(top, "link2nobody");
+    final static File link2link2nobody  = new File(top, "link2link2nobody");
+
+    /**
+     * Setup files, directories, and sym links used by test.
+     */
+    static void setup() throws IOException {
+        // link2link2file -> link2file -> foofile
+        FileOutputStream fos = new FileOutputStream(file);
+        try {
+            fos.write(new byte[16*1024]);
+        } finally {
+            fos.close();
+        }
+        mklink(link2file, file);
+        mklink(link2link2file, link2file);
+
+        // link2link2dir -> link2dir -> dir
+        assertTrue(dir.mkdir());
+        mklink(link2dir, dir);
+        mklink(link2link2dir, link2dir);
+
+        // link2link2nobody -> link2nobody -> <does-not-exist>
+        mklink(link2nobody, new File(top, "DoesNotExist"));
+        mklink(link2link2nobody, link2nobody);
+    }
+
+    /**
+     * Remove files, directories, and sym links used by test.
+     */
+    static void cleanup() throws IOException {
+        if (file != null)
+            file.delete();
+        if (link2file != null)
+            link2file.toPath().deleteIfExists();
+        if (link2link2file != null)
+            link2link2file.toPath().deleteIfExists();
+        if (dir != null)
+            dir.delete();
+        if (link2dir != null)
+            link2dir.toPath().deleteIfExists();
+        if (link2link2dir != null)
+            link2link2dir.toPath().deleteIfExists();
+        if (link2nobody != null)
+            link2nobody.toPath().deleteIfExists();
+        if (link2link2nobody != null)
+            link2link2nobody.toPath().deleteIfExists();
+    }
+
+    /**
+     * Creates a sym link source->target
+     */
+    static void mklink(File source, File target) throws IOException {
+        source.toPath().createSymbolicLink(target.toPath());
+    }
+
+    /**
+     * Returns true if the "link" exists and is a sym link.
+     */
+    static boolean isSymLink(File link) {
+         try {
+            BasicFileAttributes attrs =
+                Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
+            return attrs.isSymbolicLink();
+         } catch (IOException x) {
+             return false;
+         }
+    }
+
+    /**
+     * Returns the last modified time of a sym link.
+     */
+    static long lastModifiedOfSymLink(File link) throws IOException {
+        BasicFileAttributes attrs =
+            Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
+        assertTrue(attrs.isSymbolicLink());
+        return attrs.lastModifiedTime().toMillis();
+    }
+
+    /**
+     * Returns true if sym links are supported on the file system where
+     * "dir" exists.
+     */
+    static boolean supportsSymLinks(File dir) {
+        Path link = dir.toPath().resolve("link");
+        Path target = dir.toPath().resolve("target");
+        try {
+            link.createSymbolicLink(target);
+            link.delete();
+            return true;
+        } catch (UnsupportedOperationException x) {
+            return false;
+        } catch (IOException x) {
+            return false;
+        }
+    }
+
+    static void assertTrue(boolean v) {
+        if (!v) throw new RuntimeException("Test failed");
+    }
+
+    static void assertFalse(boolean v) {
+        assertTrue(!v);
+    }
+
+    static void header(String h) {
+        out.println();
+        out.println();
+        out.println("-- " + h + " --");
+    }
+
+    /**
+     * Tests go here.
+     */
+    static void go() throws IOException {
+
+        // check setup
+        assertTrue(file.isFile());
+        assertTrue(isSymLink(link2file));
+        assertTrue(isSymLink(link2link2file));
+        assertTrue(dir.isDirectory());
+        assertTrue(isSymLink(link2dir));
+        assertTrue(isSymLink(link2link2dir));
+        assertTrue(isSymLink(link2nobody));
+        assertTrue(isSymLink(link2link2nobody));
+
+        header("createNewFile");
+
+        assertFalse(file.createNewFile());
+        assertFalse(link2file.createNewFile());
+        assertFalse(link2link2file.createNewFile());
+        assertFalse(dir.createNewFile());
+        assertFalse(link2dir.createNewFile());
+        assertFalse(link2link2dir.createNewFile());
+        assertFalse(link2nobody.createNewFile());
+        assertFalse(link2link2nobody.createNewFile());
+
+        header("mkdir");
+
+        assertFalse(file.mkdir());
+        assertFalse(link2file.mkdir());
+        assertFalse(link2link2file.mkdir());
+        assertFalse(dir.mkdir());
+        assertFalse(link2dir.mkdir());
+        assertFalse(link2link2dir.mkdir());
+        assertFalse(link2nobody.mkdir());
+        assertFalse(link2link2nobody.mkdir());
+
+        header("delete");
+
+        File link = new File(top, "mylink");
+        try {
+            mklink(link, file);
+            assertTrue(link.delete());
+            assertTrue(!isSymLink(link));
+            assertTrue(file.exists());
+
+            mklink(link, link2file);
+            assertTrue(link.delete());
+            assertTrue(!isSymLink(link));
+            assertTrue(link2file.exists());
+
+            mklink(link, dir);
+            assertTrue(link.delete());
+            assertTrue(!isSymLink(link));
+            assertTrue(dir.exists());
+
+            mklink(link, link2dir);
+            assertTrue(link.delete());
+            assertTrue(!isSymLink(link));
+            assertTrue(link2dir.exists());
+
+            mklink(link, link2nobody);
+            assertTrue(link.delete());
+            assertTrue(!isSymLink(link));
+            assertTrue(isSymLink(link2nobody));
+
+        } finally {
+            link.toPath().deleteIfExists();
+        }
+
+        header("renameTo");
+
+        File newlink = new File(top, "newlink");
+        assertTrue(link2file.renameTo(newlink));
+        try {
+            assertTrue(file.exists());
+            assertTrue(isSymLink(newlink));
+            assertTrue(!isSymLink(link2file));
+        } finally {
+            newlink.renameTo(link2file);  // restore link
+        }
+
+        assertTrue(link2dir.renameTo(newlink));
+        try {
+            assertTrue(dir.exists());
+            assertTrue(isSymLink(newlink));
+            assertTrue(!isSymLink(link2dir));
+        } finally {
+            newlink.renameTo(link2dir);  // restore link
+        }
+
+        header("list");
+
+        final String name = "entry";
+        File entry = new File(dir, name);
+        try {
+            assertTrue(dir.list().length == 0);   // directory should be empty
+            assertTrue(link2dir.list().length == 0);
+            assertTrue(link2link2dir.list().length == 0);
+
+            assertTrue(entry.createNewFile());
+            assertTrue(dir.list().length == 1);
+            assertTrue(dir.list()[0].equals(name));
+
+            // access directory by following links
+            assertTrue(link2dir.list().length == 1);
+            assertTrue(link2dir.list()[0].equals(name));
+            assertTrue(link2link2dir.list().length == 1);
+            assertTrue(link2link2dir.list()[0].equals(name));
+
+            // files that are not directories
+            assertTrue(link2file.list() == null);
+            assertTrue(link2nobody.list() == null);
+
+        } finally {
+            entry.delete();
+        }
+
+        header("isXXX");
+
+        assertTrue(file.isFile());
+        assertTrue(link2file.isFile());
+        assertTrue(link2link2file.isFile());
+
+        assertTrue(dir.isDirectory());
+        assertTrue(link2dir.isDirectory());
+        assertTrue(link2link2dir.isDirectory());
+
+        // on Windows we test with the DOS hidden attribute set
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            DosFileAttributeView view = file.toPath()
+                .getFileAttributeView(DosFileAttributeView.class);
+            view.setHidden(true);
+            try {
+                assertTrue(file.isHidden());
+                assertTrue(link2file.isHidden());
+                assertTrue(link2link2file.isHidden());
+            } finally {
+                view.setHidden(false);
+            }
+            assertFalse(file.isHidden());
+            assertFalse(link2file.isHidden());
+            assertFalse(link2link2file.isHidden());
+        }
+
+        header("length");
+
+        long len = file.length();
+        assertTrue(len > 0L);
+        // these tests should follow links
+        assertTrue(link2file.length() == len);
+        assertTrue(link2link2file.length() == len);
+        assertTrue(link2nobody.length() == 0L);
+
+        header("lastModified / setLastModified");
+
+        // need time to diff between link and file
+        long origLastModified = file.lastModified();
+        assertTrue(origLastModified != 0L);
+        try { Thread.sleep(2000); } catch (InterruptedException x) { }
+        file.setLastModified(System.currentTimeMillis());
+
+        long lastModified = file.lastModified();
+        assertTrue(lastModified != origLastModified);
+        assertTrue(lastModifiedOfSymLink(link2file) != lastModified);
+        assertTrue(lastModifiedOfSymLink(link2link2file) != lastModified);
+        assertTrue(link2file.lastModified() == lastModified);
+        assertTrue(link2link2file.lastModified() == lastModified);
+        assertTrue(link2nobody.lastModified() == 0L);
+
+        origLastModified = dir.lastModified();
+        assertTrue(origLastModified != 0L);
+        dir.setLastModified(0L);
+        assertTrue(dir.lastModified() == 0L);
+        assertTrue(link2dir.lastModified() == 0L);
+        assertTrue(link2link2dir.lastModified() == 0L);
+        dir.setLastModified(origLastModified);
+
+        header("setXXX / canXXX");
+
+        assertTrue(file.canRead());
+        assertTrue(file.canWrite());
+        assertTrue(link2file.canRead());
+        assertTrue(link2file.canWrite());
+        assertTrue(link2link2file.canRead());
+        assertTrue(link2link2file.canWrite());
+
+        if (file.setReadOnly()) {
+            assertFalse(file.canWrite());
+            assertFalse(link2file.canWrite());
+            assertFalse(link2link2file.canWrite());
+
+            assertTrue(file.setWritable(true));             // make writable
+            assertTrue(file.canWrite());
+            assertTrue(link2file.canWrite());
+            assertTrue(link2link2file.canWrite());
+
+            assertTrue(link2file.setReadOnly());            // make read only
+            assertFalse(file.canWrite());
+            assertFalse(link2file.canWrite());
+            assertFalse(link2link2file.canWrite());
+
+            assertTrue(link2link2file.setWritable(true));   // make writable
+            assertTrue(file.canWrite());
+            assertTrue(link2file.canWrite());
+            assertTrue(link2link2file.canWrite());
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (supportsSymLinks(top)) {
+            try {
+                setup();
+                go();
+            } finally {
+                cleanup();
+            }
+        }
+    }
+
+}
--- a/test/java/lang/String/Split.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/lang/String/Split.java	Tue Sep 01 13:03:09 2009 -0700
@@ -23,14 +23,18 @@
 
 /**
  * @test
+ * @bug 6840246
  * @summary test String.split()
  */
+import java.util.Arrays;
+import java.util.Random;
 import java.util.regex.*;
 
 public class Split {
 
     public static void main(String[] args) throws Exception {
         String source = "0123456789";
+
         for (int limit=-2; limit<3; limit++) {
             for (int x=0; x<10; x++) {
                 String[] result = source.split(Integer.toString(x), limit);
@@ -80,5 +84,48 @@
             throw new RuntimeException("String.split failure 8");
         if (!result[0].equals(source))
             throw new RuntimeException("String.split failure 9");
+
+        // check fastpath of String.split()
+        source = "0123456789abcdefgABCDEFG";
+        Random r = new Random();
+
+        for (boolean doEscape: new boolean[] {false, true}) {
+            for (int cp = 0; cp < 0x11000; cp++) {
+                Pattern p = null;
+                String regex = new String(Character.toChars(cp));
+                if (doEscape)
+                    regex = "\\" + regex;
+                try {
+                    p = Pattern.compile(regex);
+                } catch (PatternSyntaxException pse) {
+                    // illegal syntax
+                    try {
+                        "abc".split(regex);
+                    } catch (PatternSyntaxException pse0) {
+                        continue;
+                    }
+                    throw new RuntimeException("String.split failure 11");
+                }
+                int off = r.nextInt(source.length());
+                String[] srcStrs = new String[] {
+                    "",
+                    source,
+                    regex + source,
+                    source + regex,
+                    source.substring(0, 3)
+                        + regex + source.substring(3, 9)
+                        + regex + source.substring(9, 15)
+                        + regex + source.substring(15),
+                    source.substring(0, off) + regex + source.substring(off)
+                };
+                for (String src: srcStrs) {
+                    for (int limit=-2; limit<3; limit++) {
+                        if (!Arrays.equals(src.split(regex, limit),
+                                           p.split(src, limit)))
+                            throw new RuntimeException("String.split failure 12");
+                    }
+                }
+            }
+        }
     }
 }
--- a/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousChannelGroup
  */
 
@@ -50,8 +50,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
 
         int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
@@ -97,9 +95,6 @@
                         System.out.println("Read failed (expected)");
                         latch.countDown();
                     }
-                    public void cancelled(Void att) {
-                        throw new RuntimeException();
-                    }
                 });
 
                 // close channel or shutdown group
@@ -122,9 +117,6 @@
             public void failed(Throwable exc, Void att) {
                 throw new RuntimeException(exc);
             }
-            public void cancelled(Void att) {
-                throw new RuntimeException();
-            }
         });
 
         latch.await();
--- a/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousChannelGroup
  */
 
@@ -90,14 +90,10 @@
                     }
                     public void failed(Throwable exc, Void att) {
                     }
-                    public void cancelled(Void att) {
-                    }
                 });
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
         SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
@@ -141,9 +137,6 @@
             public void failed(Throwable exc, Integer groupId) {
                 fail(exc.getMessage());
             }
-            public void cancelled(Integer groupId) {
-                fail("I/O operation was cancelled");
-            }
         });
 
         // wait until
--- a/test/java/nio/channels/AsynchronousChannelGroup/Restart.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Restart.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousChannelGroup
  * @build Restart
  * @run main/othervm -XX:-UseVMInterruptibleIO Restart
@@ -111,8 +111,6 @@
                 }
                 public void failed(Throwable exc, Void att) {
                 }
-                public void cancelled(Void att) {
-                }
             });
 
             // establish loopback connection which should cause completion
--- a/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousChannelGroup
  */
 
@@ -52,8 +52,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         System.out.println("Listener created.");
 
@@ -97,8 +95,6 @@
                     }
                     public void failed(Throwable exc, AsynchronousSocketChannel ch) {
                     }
-                    public void cancelled(AsynchronousSocketChannel ch) {
-                    }
                 });
         }
         System.out.println("All read operations outstanding.");
--- a/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4527345
+ * @bug 4527345 6842687
  * @summary Unit test for AsynchronousDatagramChannel
  */
 
@@ -72,8 +72,6 @@
             }
             public void failed (Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         Thread.sleep(2000);
         sender.send(ByteBuffer.wrap(msg), sa);
@@ -88,8 +86,6 @@
             public void failed (Throwable exc, Void att) {
                 exception.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
         Throwable result;
         while ((result = exception.get()) == null) {
@@ -107,8 +103,6 @@
             public void failed (Throwable exc, Void att) {
                 exception.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
         ch.close();
         while ((result = exception.get()) == null) {
@@ -162,8 +156,6 @@
             }
             public void failed (Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         Thread.sleep(2000);
         sender.send(ByteBuffer.wrap(msg), sa);
@@ -178,8 +170,6 @@
             public void failed (Throwable exc, Void att) {
                 exception.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
         Throwable result;
         while ((result = exception.get()) == null) {
@@ -197,8 +187,6 @@
             public void failed (Throwable exc, Void att) {
                 exception.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
         ch.close();
         while ((result = exception.get()) == null) {
@@ -246,8 +234,6 @@
             }
             public void failed (Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         l2.await(5, TimeUnit.SECONDS);
 
@@ -272,8 +258,6 @@
                     throw new RuntimeException(exc);
                 }
             }
-            public void cancelled(Void att) {
-            }
         });
         l3.await(5, TimeUnit.SECONDS);
 
@@ -323,8 +307,6 @@
             }
             public void failed (Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
         l2.await(5, TimeUnit.SECONDS);
 
@@ -340,7 +322,7 @@
         reader.close();
     }
 
-    static void cancelAndCheck(Future<?> result, CountDownLatch latch)
+    static void cancelAndCheck(Future<?> result)
         throws InterruptedException
     {
         boolean cancelled = result.cancel(false);
@@ -356,37 +338,22 @@
         } catch (ExecutionException e) {
             throw new RuntimeException("Should not fail");
         }
-
-        // make sure that completion handler is invoked
-        latch.await();
     }
 
     // basic cancel tests
     static void doCancelTests() throws Exception {
         InetAddress lh = InetAddress.getLocalHost();
 
-        // timed and non-timed receive
+        // receive
         for (int i=0; i<2; i++) {
             AsynchronousDatagramChannel ch =
                 AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
-            final CountDownLatch latch = new CountDownLatch(1);
-            long timeout = (i == 0) ? 0L : 60L;
-            Future<SocketAddress> remote = ch
-                .receive(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, (Void)null,
-                    new CompletionHandler<SocketAddress,Void>() {
-                        public void completed(SocketAddress source, Void att) {
-                        }
-                        public void failed (Throwable exc, Void att) {
-                        }
-                        public void cancelled(Void att) {
-                            latch.countDown();
-                        }
-                    });
-            cancelAndCheck(remote, latch);
+            Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100));
+            cancelAndCheck(remote);
             ch.close();
         }
 
-        // timed and non-timed read
+        // read
         for (int i=0; i<2; i++) {
             AsynchronousDatagramChannel ch =
                 AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
@@ -394,18 +361,8 @@
                 ((InetSocketAddress)(ch.getLocalAddress())).getPort()));
             final CountDownLatch latch = new CountDownLatch(1);
             long timeout = (i == 0) ? 0L : 60L;
-            Future<Integer> result = ch
-                .read(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, (Void)null,
-                    new CompletionHandler<Integer,Void>() {
-                        public void completed(Integer bytesRead, Void att) {
-                        }
-                        public void failed (Throwable exc, Void att) {
-                        }
-                        public void cancelled(Void att) {
-                            latch.countDown();
-                        }
-                    });
-            cancelAndCheck(result, latch);
+            Future<Integer> result = ch.read(ByteBuffer.allocate(100));
+            cancelAndCheck(result);
             ch.close();
         }
     }
--- a/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272 6822643 6830721
+ * @bug 4607272 6822643 6830721 6842687
  * @summary Unit test for AsynchronousFileChannel
  */
 
@@ -195,8 +195,6 @@
                     }
                     public void failed(Throwable exc, Void att) {
                     }
-                    public void cancelled(Void att) {
-                    }
                 });
                 throw new RuntimeException("OverlappingFileLockException expected");
             } catch (OverlappingFileLockException x) {
@@ -229,8 +227,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
 
         // wait for handler to complete
@@ -318,8 +314,6 @@
                         }
                         public void failed(Throwable exc, Void att) {
                         }
-                        public void cancelled(Void att) {
-                        }
                     });
                     await(latch);
 
@@ -338,8 +332,41 @@
                 }
             } finally {
                 ch.close();
+                executor.shutdown();
             }
         }
+
+
+        // test sharing a thread pool between many channels
+        ExecutorService executor = Executors
+            .newFixedThreadPool(1+rand.nextInt(10), threadFactory);
+        final int n = 50 + rand.nextInt(50);
+        AsynchronousFileChannel[] channels = new AsynchronousFileChannel[n];
+        try {
+            for (int i=0; i<n; i++) {
+                Set<StandardOpenOption> opts = EnumSet.of(WRITE);
+                channels[i] = AsynchronousFileChannel.open(file, opts, executor);
+                final CountDownLatch latch = new CountDownLatch(1);
+                channels[i].write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
+                    public void completed(Integer result, Void att) {
+                        latch.countDown();
+                    }
+                    public void failed(Throwable exc, Void att) {
+                    }
+                });
+                await(latch);
+
+                // close ~half the channels
+                if (rand.nextBoolean())
+                    channels[i].close();
+            }
+        } finally {
+            // close remaining channels
+            for (int i=0; i<n; i++) {
+                if (channels[i] != null) channels[i].close();
+            }
+            executor.shutdown();
+        }
     }
 
     // exercise asynchronous close
@@ -409,17 +436,7 @@
                 .open(file, WRITE, SYNC);
 
             // start write operation
-            final CountDownLatch latch = new CountDownLatch(1);
-            Future<Integer> res = ch.write(genBuffer(), 0L, (Void)null,
-                new CompletionHandler<Integer,Void>() {
-                    public void completed(Integer result, Void att) {
-                    }
-                    public void failed(Throwable exc, Void att) {
-                    }
-                    public void cancelled(Void att) {
-                        latch.countDown();
-                    }
-            });
+            Future<Integer> res = ch.write(genBuffer(), 0L);
 
             // cancel operation
             boolean cancelled = res.cancel(mayInterruptIfRunning);
@@ -456,10 +473,6 @@
                 throw new RuntimeException(x);
             }
 
-            // check that cancelled method is invoked
-            if (cancelled)
-                await(latch);
-
             ch.close();
         }
     }
@@ -547,8 +560,6 @@
             }
             public void failed(Throwable exc, Long position) {
             }
-            public void cancelled(Long position) {
-            }
         });
 
         // wait for writes to complete
@@ -574,8 +585,6 @@
             }
             public void failed(Throwable exc, Long position) {
             }
-            public void cancelled(Long position) {
-            }
         });
 
         // wait for reads to complete
--- a/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for java.nio.channels.AsynchronousFileChannel
  * @build CustomThreadPool MyThreadFactory
  * @run main/othervm -Djava.nio.channels.DefaultThreadPool.threadFactory=MyThreadFactory CustomThreadPool
@@ -51,8 +51,6 @@
                 }
                 public void failed(Throwable exc, AtomicReference<Thread> invoker) {
                 }
-                public void cancelled(AtomicReference<Thread> invoker) {
-                }
             });
         Thread t;
         while ((t = invoker.get()) == null) {
--- a/test/java/nio/channels/AsynchronousFileChannel/Lock.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousFileChannel/Lock.java	Tue Sep 01 13:03:09 2009 -0700
@@ -23,7 +23,7 @@
 
 
 /* @test
- * @bug 4607272 6814948
+ * @bug 4607272 6814948 6842687
  * @summary Unit test for AsynchronousFileChannel#lock method
  */
 
@@ -97,7 +97,7 @@
         slave.lock(0, 10, false);
 
         // this VM acquires lock on non-overlapping range
-        fl = ch.lock(10, 10, false, null, null).get();
+        fl = ch.lock(10, 10, false).get();
         fl.release();
 
         // done
--- a/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousServerSocketChannel
  * @run main/timeout=180 Basic
  */
@@ -104,8 +104,6 @@
             public void failed(Throwable exc, Void att) {
                 exception.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
 
         // check AcceptPendingException
--- a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4607272
+ * @bug 4607272 6842687
  * @summary Unit test for AsynchronousSocketChannel
  * @run main/timeout=600 Basic
  */
@@ -187,8 +187,6 @@
             public void failed(Throwable exc, Void att) {
                 connectException.set(exc);
             }
-            public void cancelled(Void att) {
-            }
         });
         while (connectException.get() == null) {
             Thread.sleep(100);
@@ -289,8 +287,6 @@
             public void failed(Throwable x, AsynchronousSocketChannel ch) {
                 writeException.set(x);
             }
-            public void cancelled(AsynchronousSocketChannel ch) {
-            }
         });
 
         // give time for socket buffer to fill up.
@@ -330,18 +326,8 @@
             SocketChannel peer = server.accept();
 
             // start read operation
-            final CountDownLatch latch = new CountDownLatch(1);
             ByteBuffer buf = ByteBuffer.allocate(1);
-            Future<Integer> res = ch.read(buf, (Void)null,
-                new CompletionHandler<Integer,Void>() {
-                    public void completed(Integer result, Void att) {
-                    }
-                    public void failed(Throwable exc, Void att) {
-                    }
-                    public void cancelled(Void att) {
-                        latch.countDown();
-                    }
-            });
+            Future<Integer> res = ch.read(buf);
 
             // cancel operation
             boolean cancelled = res.cancel(mayInterruptIfRunning);
@@ -362,8 +348,11 @@
             } catch (CancellationException x) {
             }
 
-            // check that completion handler executed.
-            latch.await();
+            // check that the cancel doesn't impact writing to the channel
+            if (!mayInterruptIfRunning) {
+                buf = ByteBuffer.wrap("a".getBytes());
+                ch.write(buf).get();
+            }
 
             ch.close();
             peer.close();
@@ -408,8 +397,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
 
         latch.await();
@@ -460,8 +447,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
 
         // trickle the writing
@@ -507,26 +492,24 @@
         }
 
         // scattering read that completes ascynhronously
-        final CountDownLatch latch = new CountDownLatch(1);
+        final CountDownLatch l1 = new CountDownLatch(1);
         ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
             new CompletionHandler<Long,Void>() {
                 public void completed(Long result, Void att) {
                     long n = result;
                     if (n <= 0)
                         throw new RuntimeException("No bytes read");
-                    latch.countDown();
+                    l1.countDown();
                 }
                 public void failed(Throwable exc, Void att) {
                 }
-                public void cancelled(Void att) {
-                }
         });
 
         // write some bytes
         sc.write(genBuffer());
 
         // read should now complete
-        latch.await();
+        l1.await();
 
         // write more bytes
         sc.write(genBuffer());
@@ -535,10 +518,20 @@
         for (int i=0; i<dsts.length; i++) {
             dsts[i].rewind();
         }
-        long n = ch
-            .read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null, null).get();
-        if (n <= 0)
-            throw new RuntimeException("No bytes read");
+
+        final CountDownLatch l2 = new CountDownLatch(1);
+        ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
+            new CompletionHandler<Long,Void>() {
+                public void completed(Long result, Void att) {
+                    long n = result;
+                    if (n <= 0)
+                        throw new RuntimeException("No bytes read");
+                    l2.countDown();
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+        });
+        l2.await();
 
         ch.close();
         sc.close();
@@ -574,8 +567,6 @@
             }
             public void failed(Throwable exc, Void att) {
             }
-            public void cancelled(Void att) {
-            }
         });
 
         // read to EOF or buffer full
@@ -613,19 +604,29 @@
         ch.connect(server.address()).get();
         SocketChannel sc = server.accept();
 
+        // number of bytes written
+        final AtomicLong bytesWritten = new AtomicLong(0);
+
         // write buffers (should complete immediately)
         ByteBuffer[] srcs = genBuffers(1);
-        long n = ch
-            .write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null, null).get();
-        if (n <= 0)
-            throw new RuntimeException("No bytes written");
+        final CountDownLatch l1 = new CountDownLatch(1);
+        ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null,
+            new CompletionHandler<Long,Void>() {
+                public void completed(Long result, Void att) {
+                    long n = result;
+                    if (n <= 0)
+                        throw new RuntimeException("No bytes read");
+                    bytesWritten.addAndGet(n);
+                    l1.countDown();
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+        });
+        l1.await();
 
         // set to true to signal that no more buffers should be written
         final AtomicBoolean continueWriting = new AtomicBoolean(true);
 
-        // number of bytes written
-        final AtomicLong bytesWritten = new AtomicLong(n);
-
         // write until socket buffer is full so as to create the conditions
         // for when a write does not complete immediately
         srcs = genBuffers(1);
@@ -644,8 +645,6 @@
                 }
                 public void failed(Throwable exc, Void att) {
                 }
-                public void cancelled(Void att) {
-                }
         });
 
         // give time for socket buffer to fill up.
@@ -658,7 +657,7 @@
         ByteBuffer buf = ByteBuffer.allocateDirect(4096);
         long total = 0L;
         do {
-            n = sc.read(buf);
+            int n = sc.read(buf);
             if (n <= 0)
                 throw new RuntimeException("No bytes read");
             buf.rewind();
@@ -714,15 +713,27 @@
 
         System.out.println("-- timeout when reading --");
 
+        ByteBuffer dst = ByteBuffer.allocate(512);
+
+        final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
+
         // this read should timeout
-        ByteBuffer dst = ByteBuffer.allocate(512);
-        try {
-            ch.read(dst, 3, TimeUnit.SECONDS, (Void)null, null).get();
-            throw new RuntimeException("Read did not timeout");
-        } catch (ExecutionException x) {
-            if (!(x.getCause() instanceof InterruptedByTimeoutException))
-                throw new RuntimeException("InterruptedByTimeoutException expected");
+        ch.read(dst, 3, TimeUnit.SECONDS, (Void)null,
+            new CompletionHandler<Integer,Void>()
+        {
+            public void completed(Integer result, Void att) {
+                throw new RuntimeException("Should not complete");
+            }
+            public void failed(Throwable exc, Void att) {
+                readException.set(exc);
+            }
+        });
+        // wait for exception
+        while (readException.get() == null) {
+            Thread.sleep(100);
         }
+        if (!(readException.get() instanceof InterruptedByTimeoutException))
+            throw new RuntimeException("InterruptedByTimeoutException expected");
 
         // after a timeout then further reading should throw unspecified runtime exception
         boolean exceptionThrown = false;
@@ -752,8 +763,6 @@
             public void failed(Throwable exc, AsynchronousSocketChannel ch) {
                 writeException.set(exc);
             }
-            public void cancelled(AsynchronousSocketChannel ch) {
-            }
         });
 
         // wait for exception
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6842687
+ * @summary Unit test for AsynchronousSocketChannel/AsynchronousServerSocketChannel
+ */
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Initiates I/O operation on a thread that terminates before the I/O completes.
+ */
+
+public class DieBeforeComplete {
+
+    public static void main(String[] args) throws Exception {
+        final AsynchronousServerSocketChannel listener =
+                AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+
+        InetAddress lh = InetAddress.getLocalHost();
+        int port = ((InetSocketAddress) (listener.getLocalAddress())).getPort();
+        final SocketAddress sa = new InetSocketAddress(lh, port);
+
+        // -- accept --
+
+        // initiate accept in a thread that dies before connection is established
+        Future<AsynchronousSocketChannel> r1 =
+                initiateAndDie(new Task<AsynchronousSocketChannel>() {
+            public Future<AsynchronousSocketChannel> run() {
+                return listener.accept();
+            }});
+
+        // establish and accept connection
+        SocketChannel peer = SocketChannel.open(sa);
+        final AsynchronousSocketChannel channel = r1.get();
+
+        // --- read --
+
+        // initiate read in a thread that dies befores bytes are available
+        final ByteBuffer dst = ByteBuffer.allocate(100);
+        Future<Integer> r2 = initiateAndDie(new Task<Integer>() {
+            public Future<Integer> run() {
+                return channel.read(dst);
+            }});
+
+        // send bytes
+        peer.write(ByteBuffer.wrap("hello".getBytes()));
+        int nread = r2.get();
+        if (nread <= 0)
+            throw new RuntimeException("Should have read at least one byte");
+
+        // -- write --
+
+        // initiate writes in threads that dies
+        boolean completedImmediately;
+        Future<Integer> r3;
+        do {
+            final ByteBuffer src = ByteBuffer.wrap(new byte[10000]);
+            r3 = initiateAndDie(new Task<Integer>() {
+                public Future<Integer> run() {
+                    return channel.write(src);
+                }});
+            try {
+                int nsent = r3.get(5, TimeUnit.SECONDS);
+                if (nsent <= 0)
+                    throw new RuntimeException("Should have wrote at least one byte");
+                completedImmediately = true;
+            } catch (TimeoutException x) {
+                completedImmediately = false;
+            }
+        } while (completedImmediately);
+
+        // drain connection
+        peer.configureBlocking(false);
+        ByteBuffer src = ByteBuffer.allocateDirect(10000);
+        do {
+            src.clear();
+            nread = peer.read(src);
+            if (nread == 0) {
+                Thread.sleep(100);
+                nread = peer.read(src);
+            }
+        } while (nread > 0);
+
+        // write should complete now
+        int nsent = r3.get();
+        if (nsent <= 0)
+            throw new RuntimeException("Should have wrote at least one byte");
+    }
+
+    static interface Task<T> {
+        Future<T> run();
+    }
+
+    static <T> Future<T> initiateAndDie(final Task<T> task) {
+        final AtomicReference<Future<T>> result = new AtomicReference<Future<T>>();
+        Runnable r = new Runnable() {
+            public void run() {
+                result.set(task.run());
+            }
+        };
+        Thread t = new Thread(r);
+        t.start();
+        while (t.isAlive()) {
+            try {
+                t.join();
+            } catch (InterruptedException x) {
+            }
+        }
+        return result.get();
+    }
+}
--- a/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 6834246
+ * @bug 6834246 6842687
  * @summary Stress test connections through the loopback interface
  */
 
@@ -114,8 +114,6 @@
                     exc.printStackTrace();
                     closeUnchecked(channel);
                 }
-                public void cancelled(Void att) {
-                }
             });
         }
 
@@ -156,8 +154,6 @@
                     exc.printStackTrace();
                     closeUnchecked(channel);
                 }
-                public void cancelled(Void att) {
-                }
             });
         }
 
--- a/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java	Mon Aug 24 17:26:09 2009 -0700
+++ b/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java	Tue Sep 01 13:03:09 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 6543863
+ * @bug 6543863 6842687
  * @summary Try to cause a deadlock between (Asynchronous)FileChannel.close
  *   and FileLock.release
  */
@@ -56,7 +56,7 @@
         AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE);
         for (int i=0; i<LOCK_COUNT; i++) {
             try {
-                locks[i] = ch.lock(i, 1, true, null, null).get();
+                locks[i] = ch.lock(i, 1, true).get();
             } catch (InterruptedException x) {
                 throw new RuntimeException(x);
             } catch (ExecutionException x) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/file/Path/CheckPermissions.java	Tue Sep 01 13:03:09 2009 -0700
@@ -0,0 +1,695 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6866804
+ * @summary Unit test for java.nio.file.Path
+ * @library ..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.channels.SeekableByteChannel;
+import java.security.Permission;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Checks each method that accesses the file system does the right permission
+ * check when there is a security manager set.
+ */
+
+public class CheckPermissions {
+
+    static class Checks {
+        private List<Permission> permissionsChecked = new ArrayList<Permission>();
+        private Set<String>  propertiesChecked = new HashSet<String>();
+        private List<String> readsChecked   = new ArrayList<String>();
+        private List<String> writesChecked  = new ArrayList<String>();
+        private List<String> deletesChecked = new ArrayList<String>();
+        private List<String> execsChecked   = new ArrayList<String>();
+
+        List<Permission> permissionsChecked()  { return permissionsChecked; }
+        Set<String> propertiesChecked()        { return propertiesChecked; }
+        List<String> readsChecked()            { return readsChecked; }
+        List<String> writesChecked()           { return writesChecked; }
+        List<String> deletesChecked()          { return deletesChecked; }
+        List<String> execsChecked()            { return execsChecked; }
+    }
+
+    static ThreadLocal<Checks> myChecks =
+        new ThreadLocal<Checks>() {
+            @Override protected Checks initialValue() {
+                return null;
+            }
+        };
+
+    static void prepare() {
+        myChecks.set(new Checks());
+    }
+
+    static void assertCheckPermission(Class<? extends Permission> type,
+                                      String name)
+    {
+        for (Permission perm: myChecks.get().permissionsChecked()) {
+            if (type.isInstance(perm) && perm.getName().equals(name))
+                return;
+        }
+        throw new RuntimeException(type.getName() + "\"" + name + "\") not checked");
+    }
+
+    static void assertCheckPropertyAccess(String key) {
+        if (!myChecks.get().propertiesChecked().contains(key))
+            throw new RuntimeException("Property " + key + " not checked");
+    }
+
+    static void assertChecked(Path file, List<String> list) {
+        String s = file.toString();
+        for (String f: list) {
+            if (f.endsWith(s))
+                return;
+        }
+        throw new RuntimeException("Access not checked");
+    }
+
+    static void assertCheckRead(Path file) {
+        assertChecked(file, myChecks.get().readsChecked());
+    }
+
+    static void assertCheckWrite(Path file) {
+        assertChecked(file, myChecks.get().writesChecked());
+    }
+
+    static void assertCheckDelete(Path file) {
+        assertChecked(file, myChecks.get().deletesChecked());
+    }
+
+    static void assertCheckExec(Path file) {
+        assertChecked(file, myChecks.get().execsChecked());
+    }
+
+    static class LoggingSecurityManager extends SecurityManager {
+        static void install() {
+            System.setSecurityManager(new LoggingSecurityManager());
+        }
+
+        @Override
+        public void checkPermission(Permission perm) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.permissionsChecked().add(perm);
+        }
+
+        @Override
+        public void checkPropertyAccess(String key) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.propertiesChecked().add(key);
+        }
+
+        @Override
+        public void checkRead(String file) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.readsChecked().add(file);
+        }
+
+        @Override
+        public void checkWrite(String file) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.writesChecked().add(file);
+        }
+
+        @Override
+        public void checkDelete(String file) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.deletesChecked().add(file);
+        }
+
+        @Override
+        public void checkExec(String file) {
+            Checks checks = myChecks.get();
+            if (checks != null)
+                checks.execsChecked().add(file);
+        }
+    }
+
+    static void testBasicFileAttributeView(BasicFileAttributeView view, Path file)
+        throws IOException
+    {
+        prepare();
+        view.readAttributes();
+        assertCheckRead(file);
+
+        prepare();
+        FileTime now = FileTime.fromMillis(System.currentTimeMillis());
+        view.setTimes(null, now, now);
+        assertCheckWrite(file);
+    }
+
+    static void testPosixFileAttributeView(PosixFileAttributeView view, Path file)
+        throws IOException
+    {
+        prepare();
+        PosixFileAttributes attrs = view.readAttributes();
+        assertCheckRead(file);
+        assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+        prepare();
+        view.setPermissions(attrs.permissions());
+        assertCheckWrite(file);
+        assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+        prepare();
+        view.setOwner(attrs.owner());
+        assertCheckWrite(file);
+        assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+        prepare();
+        view.setOwner(attrs.owner());
+        assertCheckWrite(file);
+        assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+    }
+
+    public static void main(String[] args) throws IOException {
+        Path dir = Paths.get(System.getProperty("test.src", "."));
+        Path file = dir.resolve("file1234").createFile();
+        try {
+            LoggingSecurityManager.install();
+
+            // -- checkAccess --
+
+            prepare();
+            file.checkAccess();
+            assertCheckRead(file);
+
+            prepare();
+            file.checkAccess(AccessMode.READ);
+            assertCheckRead(file);
+
+            prepare();
+            file.checkAccess(AccessMode.WRITE);
+            assertCheckWrite(file);
+
+            prepare();
+            try {
+                file.checkAccess(AccessMode.EXECUTE);
+            } catch (AccessDeniedException x) { }
+            assertCheckExec(file);
+
+            prepare();
+            try {
+                file.checkAccess(AccessMode.READ, AccessMode.WRITE, AccessMode.EXECUTE);
+            } catch (AccessDeniedException x) { }
+            assertCheckRead(file);
+            assertCheckWrite(file);
+            assertCheckExec(file);
+
+            // -- copyTo --
+
+            Path target = dir.resolve("target1234");
+            prepare();
+            file.copyTo(target);
+            try {
+                assertCheckRead(file);
+                assertCheckWrite(target);
+            } finally {
+                target.delete();
+            }
+
+            if (TestUtil.supportsLinks(dir)) {
+                Path link = dir.resolve("link1234").createSymbolicLink(file);
+                try {
+                    prepare();
+                    link.copyTo(target, LinkOption.NOFOLLOW_LINKS);
+                    try {
+                        assertCheckRead(link);
+                        assertCheckWrite(target);
+                        assertCheckPermission(LinkPermission.class, "symbolic");
+                    } finally {
+                        target.delete();
+                    }
+                } finally {
+                    link.delete();
+                }
+            }
+
+            // -- createDirectory --
+
+            Path subdir = dir.resolve("subdir1234");
+            prepare();
+            subdir.createDirectory();
+            try {
+                assertCheckWrite(subdir);
+            } finally {
+                subdir.delete();
+            }
+
+            // -- createFile --
+
+            Path fileToCreate = dir.resolve("file7890");
+            prepare();
+            try {
+                fileToCreate.createFile();
+                assertCheckWrite(fileToCreate);
+            } finally {
+                fileToCreate.delete();
+            }
+
+            // -- createSymbolicLink --
+
+            if (TestUtil.supportsLinks(dir)) {
+                prepare();
+                Path link = dir.resolve("link1234").createSymbolicLink(file);
+                try {
+                    assertCheckWrite(link);
+                    assertCheckPermission(LinkPermission.class, "symbolic");
+                } finally {
+                    link.delete();
+                }
+            }
+
+            // -- delete/deleteIfExists --
+
+            Path fileToDelete = dir.resolve("file7890");
+
+            fileToDelete.createFile();
+            prepare();
+            fileToDelete.delete();
+            assertCheckDelete(fileToDelete);
+
+            fileToDelete.createFile();
+            prepare();
+            fileToDelete.deleteIfExists();
+            assertCheckDelete(fileToDelete);
+
+            // -- exists/notExists --
+
+            prepare();
+            file.exists();
+            assertCheckRead(file);
+
+            prepare();
+            file.notExists();
+            assertCheckRead(file);
+
+            // -- getFileStore --
+
+            prepare();
+            file.getFileStore();
+            assertCheckRead(file);
+            assertCheckPermission(RuntimePermission.class, "getFileStoreAttributes");
+
+            // -- isSameFile --
+
+            prepare();
+            file.isSameFile(dir);
+            assertCheckRead(file);
+            assertCheckRead(dir);
+
+            // -- moveTo --
+
+            Path target2 = dir.resolve("target1234");
+            prepare();
+            file.moveTo(target2);
+            try {
+                assertCheckWrite(file);
+                assertCheckWrite(target2);
+            } finally {
+                // restore file
+                target2.moveTo(file);
+            }
+
+            // -- newByteChannel --
+
+            SeekableByteChannel sbc;
+
+            prepare();
+            sbc = file.newByteChannel();
+            try {
+                assertCheckRead(file);
+            } finally {
+                sbc.close();
+            }
+            prepare();
+            sbc = file.newByteChannel(StandardOpenOption.WRITE);
+            try {
+                assertCheckWrite(file);
+            } finally {
+                sbc.close();
+            }
+            prepare();
+            sbc = file.newByteChannel(StandardOpenOption.READ, StandardOpenOption.WRITE);
+            try {
+                assertCheckRead(file);
+                assertCheckWrite(file);
+            } finally {
+                sbc.close();
+            }
+
+            prepare();
+            sbc = file.newByteChannel(StandardOpenOption.DELETE_ON_CLOSE);
+            try {
+                assertCheckRead(file);
+                assertCheckDelete(file);
+            } finally {
+                sbc.close();
+            }
+            file.createFile(); // restore file
+
+
+            // -- newInputStream/newOutptuStream --
+
+            prepare();
+            InputStream in = file.newInputStream();
+            try {
+                assertCheckRead(file);
+            } finally {
+                in.close();
+            }
+            prepare();
+            OutputStream out = file.newOutputStream();
+            try {
+                assertCheckWrite(file);
+            } finally {
+                out.close();
+            }
+
+            // -- newDirectoryStream --
+
+            prepare();
+            DirectoryStream<Path> stream = dir.newDirectoryStream();
+            try {
+                assertCheckRead(dir);
+
+                if (stream instanceof SecureDirectoryStream<?>) {
+                    Path entry;
+                    SecureDirectoryStream<Path> sds =
+                        (SecureDirectoryStream<Path>)stream;
+
+                    // newByteChannel
+                    entry = file.getName();
+                    prepare();
+                    sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.READ));
+                    try {
+                        assertCheckRead(file);
+                    } finally {
+                        sbc.close();
+                    }
+                    prepare();
+                    sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.WRITE));
+                    try {
+                        assertCheckWrite(file);
+                    } finally {
+                        sbc.close();
+                    }
+
+                    // deleteFile
+                    entry = file.getName();
+                    prepare();
+                    sds.deleteFile(entry);
+                    assertCheckDelete(file);
+                    dir.resolve(entry).createFile();  // restore file
+
+                    // deleteDirectory
+                    entry = Paths.get("subdir1234");
+                    dir.resolve(entry).createDirectory();
+                    prepare();
+                    sds.deleteDirectory(entry);
+                    assertCheckDelete(dir.resolve(entry));
+
+                    // move
+                    entry = Paths.get("tempname1234");
+                    prepare();
+                    sds.move(file.getName(), sds, entry);
+                    assertCheckWrite(file);
+                    assertCheckWrite(dir.resolve(entry));
+                    sds.move(entry, sds, file.getName());  // restore file
+
+                    // newDirectoryStream
+                    entry = Paths.get("subdir1234");
+                    dir.resolve(entry).createDirectory();
+                    try {
+                        prepare();
+                        sds.newDirectoryStream(entry).close();
+                        assertCheckRead(dir.resolve(entry));
+                    } finally {
+                        dir.resolve(entry).delete();
+                    }
+
+                    // getFileAttributeView to access attributes of directory
+                    testBasicFileAttributeView(sds
+                        .getFileAttributeView(BasicFileAttributeView.class), dir);
+                    testPosixFileAttributeView(sds
+                        .getFileAttributeView(PosixFileAttributeView.class), dir);
+
+                    // getFileAttributeView to access attributes of entry
+                    entry = file.getName();
+                    testBasicFileAttributeView(sds
+                        .getFileAttributeView(entry, BasicFileAttributeView.class), file);
+                    testPosixFileAttributeView(sds
+                        .getFileAttributeView(entry, PosixFileAttributeView.class), file);
+
+                } else {
+                    System.out.println("SecureDirectoryStream not tested");
+                }
+
+            } finally {
+                stream.close();
+            }
+
+            // -- toAbsolutePath --
+
+            prepare();
+            file.getName().toAbsolutePath();
+            assertCheckPropertyAccess("user.dir");
+
+            // -- toRealPath --
+
+            prepare();
+            file.toRealPath(true);
+            assertCheckRead(file);
+
+            prepare();
+            file.toRealPath(false);
+            assertCheckRead(file);
+
+            prepare();
+            Paths.get(".").toRealPath(true);
+            assertCheckPropertyAccess("user.dir");
+
+            prepare();
+            Paths.get(".").toRealPath(false);
+            assertCheckPropertyAccess("user.dir");
+
+            // -- register --
+
+            WatchService watcher = FileSystems.getDefault().newWatchService();
+            try {
+                prepare();
+                dir.register(watcher, StandardWatchEventKind.ENTRY_DELETE);
+                assertCheckRead(dir);
+            } finally {
+                watcher.close();
+            }
+
+            // -- getAttribute/setAttribute/readAttributes --
+
+            prepare();
+            file.getAttribute("size");
+            assertCheckRead(file);
+
+            prepare();
+            file.setAttribute("lastModifiedTime",
+                FileTime.fromMillis(System.currentTimeMillis()));
+            assertCheckWrite(file);
+
+            prepare();
+            file.readAttributes("*");
+            assertCheckRead(file);
+
+            // -- BasicFileAttributeView --
+            testBasicFileAttributeView(file
+                .getFileAttributeView(BasicFileAttributeView.class), file);
+
+            // -- PosixFileAttributeView --
+
+            {
+                PosixFileAttributeView view =
+                    file.getFileAttributeView(PosixFileAttributeView.class);
+                if (view != null &&
+                    file.getFileStore().supportsFileAttributeView(PosixFileAttributeView.class))
+                {
+                    testPosixFileAttributeView(view, file);
+                } else {
+                    System.out.println("PosixFileAttributeView not tested");
+                }
+            }
+
+            // -- DosFileAttributeView --
+
+            {
+                DosFileAttributeView view =
+                    file.getFileAttributeView(DosFileAttributeView.class);
+                if (view != null &&
+                    file.getFileStore().supportsFileAttributeView(DosFileAttributeView.class))
+                {
+                    prepare();
+                    view.readAttributes();
+                    assertCheckRead(file);
+
+                    prepare();
+                    view.setArchive(false);
+                    assertCheckWrite(file);
+
+                    prepare();
+                    view.setHidden(false);
+                    assertCheckWrite(file);
+
+                    prepare();
+                    view.setReadOnly(false);
+                    assertCheckWrite(file);
+
+                    prepare();
+                    view.setSystem(false);
+                    assertCheckWrite(file);
+                } else {
+                    System.out.println("DosFileAttributeView not tested");
+                }
+            }
+
+            // -- FileOwnerAttributeView --
+
+            {
+                FileOwnerAttributeView view =
+                    file.getFileAttributeView(FileOwnerAttributeView.class);
+                if (view != null &&
+                    file.getFileStore().supportsFileAttributeView(FileOwnerAttributeView.class))
+                {
+                    prepare();
+                    UserPrincipal owner = view.getOwner();
+                    assertCheckRead(file);
+                    assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+                    prepare();
+                    view.setOwner(owner);
+                    assertCheckWrite(file);
+                    assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+                } else {
+                    System.out.println("FileOwnerAttributeView not tested");
+                }
+            }
+
+            // -- UserDefinedFileAttributeView --
+
+            {
+                UserDefinedFileAttributeView view =
+                    file.getFileAttributeView(UserDefinedFileAttributeView.class);
+                if (view != null &&
+                    file.getFileStore().supportsFileAttributeView(UserDefinedFileAttributeView.class))
+                {
+                    prepare();
+                    view.write("test", ByteBuffer.wrap(new byte[100]));
+                    assertCheckWrite(file);
+                    assertCheckPermission(RuntimePermission.class,
+                                               "accessUserDefinedAttributes");
+
+                    prepare();
+                    view.read("test", ByteBuffer.allocate(100));
+                    assertCheckRead(file);
+                    assertCheckPermission(RuntimePermission.class,
+                                               "accessUserDefinedAttributes");
+
+                    prepare();
+                    view.size("test");
+                    assertCheckRead(file);
+                    assertCheckPermission(RuntimePermission.class,
+                                               "accessUserDefinedAttributes");
+
+                    prepare();
+                    view.list();
+                    assertCheckRead(file);
+                    assertCheckPermission(RuntimePermission.class,
+                                               "accessUserDefinedAttributes");
+
+                    prepare();
+                    view.delete("test");
+                    assertCheckWrite(file);
+                    assertCheckPermission(RuntimePermission.class,
+                                               "accessUserDefinedAttributes");
+                } else {
+                    System.out.println("UserDefinedFileAttributeView not tested");
+                }
+            }
+
+            // -- AclFileAttributeView --
+            {
+                AclFileAttributeView view =
+                    file.getFileAttributeView(AclFileAttributeView.class);
+                if (view != null &&
+                    file.getFileStore().supportsFileAttributeView(AclFileAttributeView.class))
+                {
+                    prepare();
+                    List<AclEntry> acl = view.getAcl();
+                    assertCheckRead(file);
+                    assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+                    prepare();
+                    view.setAcl(acl);
+                    assertCheckWrite(file);
+                    assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+                } else {
+                    System.out.println("AclFileAttributeView not tested");
+                }
+            }
+
+            // -- UserPrincipalLookupService
+
+            UserPrincipalLookupService lookupService =
+                FileSystems.getDefault().getUserPrincipalLookupService();
+            UserPrincipal owner = Attributes.getOwner(file);
+
+            prepare();
+            lookupService.lookupPrincipalByName(owner.getName());
+            assertCheckPermission(RuntimePermission.class,
+                                       "lookupUserInformation");
+
+            try {
+                UserPrincipal group = Attributes.readPosixFileAttributes(file).group();
+                prepare();
+                lookupService.lookupPrincipalByGroupName(group.getName());
+                assertCheckPermission(RuntimePermission.class,
+                                           "lookupUserInformation");
+            } catch (UnsupportedOperationException ignore) {
+                System.out.println("lookupPrincipalByGroupName not tested");
+            }
+
+