changeset 13116:d937975320cc

Merge
author ihse
date Thu, 11 Jun 2015 00:51:11 +0200
parents 474db9ef5ee7 046fd17bb9a0
children 60387e5d6822
files src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java src/java.base/share/classes/sun/nio/cs/AbstractCharsetProvider.java src/java.base/share/classes/sun/security/ssl/EngineArgs.java src/java.base/share/classes/sun/security/ssl/EngineInputRecord.java src/java.base/share/classes/sun/security/ssl/EngineOutputRecord.java src/java.base/share/classes/sun/security/ssl/EngineWriter.java src/java.base/share/classes/sun/security/ssl/KerberosClientKeyExchange.java src/java.base/share/classes/sun/security/ssl/Krb5Helper.java src/java.base/share/classes/sun/security/ssl/Krb5Proxy.java src/java.security.jgss/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java src/java.security.jgss/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java src/java.security.jgss/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java test/java/lang/Character/UnicodeBlock/NonOptimalMapSize.java
diffstat 382 files changed, 24672 insertions(+), 8385 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Jun 11 00:23:01 2015 +0200
+++ b/.hgtags	Thu Jun 11 00:51:11 2015 +0200
@@ -309,3 +309,4 @@
 7de8d036ad0980d988d1b9b4b4e6be555d9fbf98 jdk9-b64
 ed94f3e7ba6bbfec0772de6d24e39543e13f6d88 jdk9-b65
 4fbcca8ab812198c7fb747ea7b213b6e404f36e9 jdk9-b66
+1abd45df5480a04bff98fba1851d66a5230e67d4 jdk9-b67
--- a/make/mapfiles/libjava/mapfile-vers	Thu Jun 11 00:23:01 2015 +0200
+++ b/make/mapfiles/libjava/mapfile-vers	Thu Jun 11 00:51:11 2015 +0200
@@ -166,6 +166,16 @@
 		Java_java_lang_Package_getSystemPackage0;
 		Java_java_lang_Package_getSystemPackages0;
 		Java_java_lang_ProcessEnvironment_environ;
+		Java_java_lang_ProcessHandleImpl_getCurrentPid0;
+		Java_java_lang_ProcessHandleImpl_parent0;
+		Java_java_lang_ProcessHandleImpl_isAlive0;
+		Java_java_lang_ProcessHandleImpl_getProcessPids0;
+		Java_java_lang_ProcessHandleImpl_destroy0;
+		Java_java_lang_ProcessHandleImpl_waitForProcessExit0;
+		Java_java_lang_ProcessHandleImpl_00024Info_initIDs;
+		Java_java_lang_ProcessHandleImpl_00024Info_info0;
+		Java_java_lang_ProcessImpl_init;
+		Java_java_lang_ProcessImpl_forkAndExec;
 		Java_java_lang_reflect_Array_get;
 		Java_java_lang_reflect_Array_getBoolean;
 		Java_java_lang_reflect_Array_getByte;
@@ -214,10 +224,6 @@
 		Java_java_lang_Throwable_fillInStackTrace;
                 Java_java_lang_Throwable_getStackTraceDepth;
                 Java_java_lang_Throwable_getStackTraceElement;
-		Java_java_lang_ProcessImpl_init;
-		Java_java_lang_ProcessImpl_waitForProcessExit;
-		Java_java_lang_ProcessImpl_forkAndExec;
-		Java_java_lang_ProcessImpl_destroyProcess;
                 Java_java_nio_Bits_copyFromShortArray;
                 Java_java_nio_Bits_copyToShortArray;
                 Java_java_nio_Bits_copyFromIntArray;
@@ -277,7 +283,7 @@
 
                 Java_jdk_internal_jimage_concurrent_ConcurrentPReader_initIDs;
                 Java_jdk_internal_jimage_concurrent_ConcurrentPReader_pread;
-		
+
                 # ZipFile.c needs this one
 		throwFileNotFoundException;
                 # zip_util.c needs this one
--- a/make/mapfiles/libnet/mapfile-vers	Thu Jun 11 00:23:01 2015 +0200
+++ b/make/mapfiles/libnet/mapfile-vers	Thu Jun 11 00:51:11 2015 +0200
@@ -42,7 +42,7 @@
 		Java_java_net_Inet4Address_init;
 		Java_java_net_Inet6Address_init;
 		Java_java_net_PlainDatagramSocketImpl_setTTL;
-		Java_java_net_PlainDatagramSocketImpl_socketSetOption;
+		Java_java_net_PlainDatagramSocketImpl_socketSetOption0;
 		Java_java_net_PlainDatagramSocketImpl_bind0;
 		Java_java_net_PlainSocketImpl_socketAccept;
 		Java_java_net_DatagramPacket_init;
@@ -73,7 +73,7 @@
 		Java_java_net_SocketOutputStream_init;
 		Java_java_net_PlainDatagramSocketImpl_peek;
 		Java_java_net_PlainDatagramSocketImpl_peekData;
-		Java_java_net_PlainSocketImpl_socketSetOption;
+		Java_java_net_PlainSocketImpl_socketSetOption0;
 		Java_java_net_PlainSocketImpl_socketSendUrgentData;
 		Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate;
 		Java_java_net_PlainSocketImpl_socketGetOption;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "java_lang_ProcessHandleImpl.h"
+#include "java_lang_ProcessHandleImpl_Info.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/sysctl.h>
+
+/**
+ * Implementations of ProcessHandleImpl functions for MAC OS X;
+ * are NOT common to all Unix variants.
+ */
+
+static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid);
+static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
+
+/*
+ * Common Unix function to lookup the uid and return the user name.
+ */
+extern jstring uidToUser(JNIEnv* env, uid_t uid);
+
+/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
+static jfieldID ProcessHandleImpl_Info_commandID;
+
+/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
+static jfieldID ProcessHandleImpl_Info_argumentsID;
+
+/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
+static jfieldID ProcessHandleImpl_Info_totalTimeID;
+
+/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
+static jfieldID ProcessHandleImpl_Info_startTimeID;
+
+/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
+static jfieldID ProcessHandleImpl_Info_userID;
+
+/* static value for clock ticks per second. */
+static long clock_ticks_per_second;
+
+/**************************************************************
+ * Static method to initialize field IDs and the ticks per second rate.
+ *
+ * Class:     java_lang_ProcessHandleImpl_Info
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_initIDs
+  (JNIEnv *env, jclass clazz) {
+
+    CHECK_NULL(ProcessHandleImpl_Info_commandID =
+            (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
+    CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
+            (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
+    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
+            (*env)->GetFieldID(env, clazz, "totalTime", "J"));
+    CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
+            (*env)->GetFieldID(env, clazz, "startTime", "J"));
+    CHECK_NULL(ProcessHandleImpl_Info_userID =
+            (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
+    clock_ticks_per_second = sysconf(_SC_CLK_TCK);
+}
+
+/*
+ * Returns the parent pid of the requested pid.
+ *
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    parent0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_parent0
+(JNIEnv *env, jobject obj, jlong jpid) {
+    pid_t pid = (pid_t) jpid;
+    pid_t ppid = -1;
+
+    if (pid == getpid()) {
+        ppid = getppid();
+    } else {
+        const pid_t pid = (pid_t) jpid;
+        struct kinfo_proc kp;
+        size_t bufSize = sizeof kp;
+
+        // Read the process info for the specific pid
+        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+        if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
+            JNU_ThrowByNameWithLastError(env,
+                "java/lang/RuntimeException", "sysctl failed");
+            return -1;
+        }
+        ppid = (bufSize > 0 && kp.kp_proc.p_pid == pid) ? kp.kp_eproc.e_ppid : -1;
+    }
+    return (jlong) ppid;
+}
+
+/*
+ * Returns the children of the requested pid and optionally each parent.
+ *
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    getProcessPids0
+ * Signature: (J[J[J)I
+ *
+ * Use sysctl to accumulate any process whose parent pid is zero or matches.
+ * The resulting pids are stored into the array of longs.
+ * The number of pids is returned if they all fit.
+ * If the parentArray is non-null, store the parent pid.
+ * If the array is too short, excess pids are not stored and
+ * the desired length is returned.
+ */
+JNIEXPORT jint JNICALL Java_java_lang_ProcessHandleImpl_getProcessPids0
+(JNIEnv *env, jclass clazz, jlong jpid,
+    jlongArray jarray, jlongArray jparentArray)
+{
+    size_t count = 0;
+    jlong* pids = NULL;
+    jlong* ppids = NULL;
+    size_t parentArraySize = 0;
+    size_t arraySize = 0;
+    size_t bufSize = 0;
+    pid_t pid = (pid_t) jpid;
+
+    arraySize = (*env)->GetArrayLength(env, jarray);
+    JNU_CHECK_EXCEPTION_RETURN(env, -1);
+    if (jparentArray != NULL) {
+        parentArraySize = (*env)->GetArrayLength(env, jparentArray);
+        JNU_CHECK_EXCEPTION_RETURN(env, -1);
+
+        if (arraySize != parentArraySize) {
+            JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
+            return 0;
+        }
+    }
+
+    // Get buffer size needed to read all processes
+    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
+    if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) {
+        JNU_ThrowByNameWithLastError(env,
+            "java/lang/RuntimeException", "sysctl failed");
+        return -1;
+    }
+
+    // Allocate buffer big enough for all processes
+    void *buffer = malloc(bufSize);
+    if (buffer == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "malloc failed");
+        return -1;
+    }
+
+    // Read process info for all processes
+    if (sysctl(mib, 4, buffer, &bufSize, NULL, 0) < 0) {
+        JNU_ThrowByNameWithLastError(env,
+            "java/lang/RuntimeException", "sysctl failed");
+        free(buffer);
+        return -1;
+    }
+
+    do { // Block to break out of on Exception
+        struct kinfo_proc *kp = (struct kinfo_proc *) buffer;
+        unsigned long nentries = bufSize / sizeof (struct kinfo_proc);
+        long i;
+
+        pids = (*env)->GetLongArrayElements(env, jarray, NULL);
+        if (pids == NULL) {
+            break;
+        }
+        if (jparentArray != NULL) {
+            ppids  = (*env)->GetLongArrayElements(env, jparentArray, NULL);
+            if (ppids == NULL) {
+                break;
+            }
+        }
+
+        // Process each entry in the buffer
+        for (i = nentries; --i >= 0; ++kp) {
+            if (pid == 0 || kp->kp_eproc.e_ppid == pid) {
+                if (count < arraySize) {
+                    // Only store if it fits
+                    pids[count] = (jlong) kp->kp_proc.p_pid;
+                    if (ppids != NULL) {
+                        // Store the parentPid
+                        ppids[count] = (jlong) kp->kp_eproc.e_ppid;
+                    }
+                }
+                count++; // Count to tabulate size needed
+            }
+        }
+    } while (0);
+
+    if (pids != NULL) {
+        (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
+    }
+    if (ppids != NULL) {
+        (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
+    }
+
+    free(buffer);
+    // If more pids than array had size for; count will be greater than array size
+    return count;
+}
+
+/**************************************************************
+ * Implementation of ProcessHandleImpl_Info native methods.
+ */
+
+/*
+ * Fill in the Info object from the OS information about the process.
+ *
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    info0
+ * Signature: (J)I
+ */
+JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_info0
+  (JNIEnv *env, jobject jinfo, jlong jpid) {
+    pid_t pid = (pid_t) jpid;
+    getStatInfo(env, jinfo, pid);
+    getCmdlineInfo(env, jinfo, pid);
+}
+
+/**
+ * Read /proc/<pid>/stat and fill in the fields of the Info object.
+ * The executable name, plus the user, system, and start times are gathered.
+ */
+static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) {
+    jlong totalTime;                    // nanoseconds
+    unsigned long long startTime;       // microseconds
+
+    const pid_t pid = (pid_t) jpid;
+    struct kinfo_proc kp;
+    size_t bufSize = sizeof kp;
+
+    // Read the process info for the specific pid
+    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+
+    if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
+        if (errno == EINVAL) {
+            return;
+        } else {
+            JNU_ThrowByNameWithLastError(env,
+                "java/lang/RuntimeException", "sysctl failed");
+        }
+        return;
+    }
+
+    // Convert the UID to the username
+    jstring name = NULL;
+    CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid)));
+    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
+    JNU_CHECK_EXCEPTION(env);
+
+    startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
+                kp.kp_proc.p_starttime.tv_usec / 1000;
+
+    (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
+    JNU_CHECK_EXCEPTION(env);
+
+    // Get cputime if for current process
+    if (pid == getpid()) {
+        struct rusage usage;
+        if (getrusage(RUSAGE_SELF, &usage) != 0) {
+            return;
+        }
+        jlong microsecs =
+            usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
+            usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
+        totalTime = microsecs * 1000;
+        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
+        JNU_CHECK_EXCEPTION(env);
+    }
+}
+
+/**
+ * Construct the argument array by parsing the arguments from the sequence of arguments.
+ */
+static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs,
+                        const char *cp, const char *argsEnd) {
+    jstring str = NULL;
+    jobject argsArray;
+    int i;
+
+    if (nargs < 1) {
+        return 0;
+    }
+    // Create a String array for nargs-1 elements
+    CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env,
+            nargs - 1, JNU_ClassString(env), NULL)), -1);
+
+    for (i = 0; i < nargs - 1; i++) {
+        // skip to the next argument; omits arg[0]
+        cp += strnlen(cp, (argsEnd - cp)) + 1;
+
+        if (cp > argsEnd || *cp == '\0') {
+            return -2;  // Off the end pointer or an empty argument is an error
+        }
+
+        CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
+
+        (*env)->SetObjectArrayElement(env, argsArray, i, str);
+        JNU_CHECK_EXCEPTION_RETURN(env, -3);
+    }
+    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
+    JNU_CHECK_EXCEPTION_RETURN(env, -4);
+    return 0;
+}
+
+/**
+ * Retrieve the command and arguments for the process and store them
+ * into the Info object.
+ */
+static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+    int mib[3], maxargs, nargs, i;
+    size_t size;
+    char *args, *cp, *sp, *np;
+
+    // Get the maximum size of the arguments
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_ARGMAX;
+    size = sizeof(maxargs);
+    if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) {
+            JNU_ThrowByNameWithLastError(env,
+                    "java/lang/RuntimeException", "sysctl failed");
+        return;
+    }
+
+    // Allocate an args buffer and get the arguments
+    args = (char *)malloc(maxargs);
+    if (args == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "malloc failed");
+        return;
+    }
+
+    do {            // a block to break out of on error
+        char *argsEnd;
+        jstring str = NULL;
+
+        mib[0] = CTL_KERN;
+        mib[1] = KERN_PROCARGS2;
+        mib[2] = pid;
+        size = (size_t) maxargs;
+        if (sysctl(mib, 3, args, &size, NULL, 0) == -1) {
+            if (errno != EINVAL) {
+            JNU_ThrowByNameWithLastError(env,
+                    "java/lang/RuntimeException", "sysctl failed");
+            }
+            break;
+        }
+        memcpy(&nargs, args, sizeof(nargs));
+
+        cp = &args[sizeof(nargs)];      // Strings start after nargs
+        argsEnd = &args[size];
+
+        // Store the command executable path
+        if ((str = JNU_NewStringPlatform(env, cp)) == NULL) {
+            break;
+        }
+        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
+        if ((*env)->ExceptionCheck(env)) {
+            break;
+        }
+
+        // Skip trailing nulls after the executable path
+        for (cp = cp + strnlen(cp, argsEnd - cp); cp < argsEnd; cp++) {
+            if (*cp != '\0') {
+                break;
+            }
+        }
+
+        fillArgArray(env, jinfo, nargs, cp, argsEnd);
+    } while (0);
+    // Free the arg buffer
+    free(args);
+}
+
--- a/src/java.base/share/classes/java/io/InputStream.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/io/InputStream.java	Thu Jun 11 00:51:11 2015 +0200
@@ -25,6 +25,7 @@
 
 package java.io;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -50,7 +51,7 @@
     // use when skipping.
     private static final int MAX_SKIP_BUFFER_SIZE = 2048;
 
-    private static final int TRANSFER_BUFFER_SIZE = 8192;
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
 
     /**
      * Reads the next byte of data from the input stream. The value byte is
@@ -192,6 +193,128 @@
     }
 
     /**
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
+    /**
+     * Reads all remaining bytes from the input stream. This method blocks until
+     * all remaining bytes have been read and end of stream is detected, or an
+     * exception is thrown. This method does not close the input stream.
+     *
+     * <p> When this stream reaches end of stream, further invocations of this
+     * method will return an empty byte array.
+     *
+     * <p> Note that this method is intended for simple cases where it is
+     * convenient to read all bytes into a byte array. It is not intended for
+     * reading input streams with large amounts of data.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes have been read. Consequently the input
+     * stream may not be at end of stream and may be in an inconsistent state.
+     * It is strongly recommended that the stream be promptly closed if an I/O
+     * error occurs.
+     *
+     * @return a byte array containing the bytes read from this input stream
+     * @throws IOException if an I/O error occurs
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated. For example, if an array larger than {@code 2GB} would
+     *         be required to store the bytes.
+     *
+     * @since 1.9
+     */
+    public byte[] readAllBytes() throws IOException {
+        byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
+        int capacity = buf.length;
+        int nread = 0;
+        int n;
+        for (;;) {
+            // read to EOF which may read more or less than initial buffer size
+            while ((n = read(buf, nread, capacity - nread)) > 0)
+                nread += n;
+
+            // if the last call to read returned -1, then we're done
+            if (n < 0)
+                break;
+
+            // need to allocate a larger buffer
+            if (capacity <= MAX_BUFFER_SIZE - capacity) {
+                capacity = capacity << 1;
+            } else {
+                if (capacity == MAX_BUFFER_SIZE)
+                    throw new OutOfMemoryError("Required array size too large");
+                capacity = MAX_BUFFER_SIZE;
+            }
+            buf = Arrays.copyOf(buf, capacity);
+        }
+        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
+    }
+
+    /**
+     * Reads the requested number of bytes from the input stream into the given
+     * byte array. This method blocks until {@code len} bytes of input data have
+     * been read, end of stream is detected, or an exception is thrown. The
+     * number of bytes actually read, possibly zero, is returned. This method
+     * does not close the input stream.
+     *
+     * <p> In the case where end of stream is reached before {@code len} bytes
+     * have been read, then the actual number of bytes read will be returned.
+     * When this stream reaches end of stream, further invocations of this
+     * method will return zero.
+     *
+     * <p> If {@code len} is zero, then no bytes are read and {@code 0} is
+     * returned; otherwise, there is an attempt to read up to {@code len} bytes.
+     *
+     * <p> The first byte read is stored into element {@code b[off]}, the next
+     * one in to {@code b[off+1]}, and so on. The number of bytes read is, at
+     * most, equal to {@code len}. Let <i>k</i> be the number of bytes actually
+     * read; these bytes will be stored in elements {@code b[off]} through
+     * {@code b[off+}<i>k</i>{@code -1]}, leaving elements {@code b[off+}<i>k</i>
+     * {@code ]} through {@code b[off+len-1]} unaffected.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes of {@code b} have been updated with
+     * data from the input stream. Consequently the input stream and {@code b}
+     * may be in an inconsistent state. It is strongly recommended that the
+     * stream be promptly closed if an I/O error occurs.
+     *
+     * @param  b the byte array into which the data is read
+     * @param  off the start offset in {@code b} at which the data is written
+     * @param  len the maximum number of bytes to read
+     * @return the actual number of bytes read into the buffer
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if {@code b} is {@code null}
+     * @throws IndexOutOfBoundsException If {@code off} is negative, {@code len}
+     *         is negative, or {@code len} is greater than {@code b.length - off}
+     *
+     * @since 1.9
+     */
+    public int readNBytes(byte[] b, int off, int len) throws IOException {
+        Objects.requireNonNull(b);
+        if (off < 0 || len < 0 || len > b.length - off)
+            throw new IndexOutOfBoundsException();
+        int n = 0;
+        while (n < len) {
+            int count = read(b, off + n, len - n);
+            if (count < 0)
+                break;
+            n += count;
+        }
+        return n;
+    }
+
+    /**
      * Skips over and discards <code>n</code> bytes of data from this input
      * stream. The <code>skip</code> method may, for a variety of reasons, end
      * up skipping over some smaller number of bytes, possibly <code>0</code>.
@@ -396,9 +519,9 @@
     public long transferTo(OutputStream out) throws IOException {
         Objects.requireNonNull(out, "out");
         long transferred = 0;
-        byte[] buffer = new byte[TRANSFER_BUFFER_SIZE];
+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
         int read;
-        while ((read = this.read(buffer, 0, TRANSFER_BUFFER_SIZE)) >= 0) {
+        while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
             out.write(buffer, 0, read);
             transferred += read;
         }
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Jun 11 00:51:11 2015 +0200
@@ -253,9 +253,6 @@
     /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
     private boolean defaultDataEnd = false;
 
-    /** buffer for reading primitive field values */
-    private byte[] primVals;
-
     /** if true, invoke readObjectOverride() instead of readObject() */
     private final boolean enableOverride;
     /** if true, invoke resolveObject() */
@@ -500,7 +497,11 @@
         Object curObj = ctx.getObj();
         ObjectStreamClass curDesc = ctx.getDesc();
         bin.setBlockDataMode(false);
-        defaultReadFields(curObj, curDesc);
+        FieldValues vals = defaultReadFields(curObj, curDesc);
+        if (curObj != null) {
+            defaultCheckFieldValues(curObj, curDesc, vals);
+            defaultSetFieldValues(curObj, curDesc, vals);
+        }
         bin.setBlockDataMode(true);
         if (!curDesc.hasWriteObjectData()) {
             /*
@@ -1881,6 +1882,26 @@
         throws IOException
     {
         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
+        // Best effort Failure Atomicity; slotValues will be non-null if field
+        // values can be set after reading all field data in the hierarchy.
+        // Field values can only be set after reading all data if there are no
+        // user observable methods in the hierarchy, readObject(NoData). The
+        // top most Serializable class in the hierarchy can be skipped.
+        FieldValues[] slotValues = null;
+
+        boolean hasSpecialReadMethod = false;
+        for (int i = 1; i < slots.length; i++) {
+            ObjectStreamClass slotDesc = slots[i].desc;
+            if (slotDesc.hasReadObjectMethod()
+                  || slotDesc.hasReadObjectNoDataMethod()) {
+                hasSpecialReadMethod = true;
+                break;
+            }
+        }
+        // No special read methods, can store values and defer setting.
+        if (!hasSpecialReadMethod)
+            slotValues = new FieldValues[slots.length];
+
         for (int i = 0; i < slots.length; i++) {
             ObjectStreamClass slotDesc = slots[i].desc;
 
@@ -1917,7 +1938,13 @@
                      */
                     defaultDataEnd = false;
                 } else {
-                    defaultReadFields(obj, slotDesc);
+                    FieldValues vals = defaultReadFields(obj, slotDesc);
+                    if (slotValues != null) {
+                        slotValues[i] = vals;
+                    } else if (obj != null) {
+                        defaultCheckFieldValues(obj, slotDesc, vals);
+                        defaultSetFieldValues(obj, slotDesc, vals);
+                    }
                 }
                 if (slotDesc.hasWriteObjectData()) {
                     skipCustomData();
@@ -1933,6 +1960,19 @@
                 }
             }
         }
+
+        if (obj != null && slotValues != null) {
+            // Check that the non-primitive types are assignable for all slots
+            // before assigning.
+            for (int i = 0; i < slots.length; i++) {
+                if (slotValues[i] != null)
+                    defaultCheckFieldValues(obj, slots[i].desc, slotValues[i]);
+            }
+            for (int i = 0; i < slots.length; i++) {
+                if (slotValues[i] != null)
+                    defaultSetFieldValues(obj, slots[i].desc, slotValues[i]);
+            }
+        }
     }
 
     /**
@@ -1964,12 +2004,22 @@
         }
     }
 
+    private class FieldValues {
+        final byte[] primValues;
+        final Object[] objValues;
+
+        FieldValues(byte[] primValues, Object[] objValues) {
+            this.primValues = primValues;
+            this.objValues = objValues;
+        }
+    }
+
     /**
      * Reads in values of serializable fields declared by given class
-     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
-     * passHandle is set to obj's handle before this method is called.
+     * descriptor. Expects that passHandle is set to obj's handle before this
+     * method is called.
      */
-    private void defaultReadFields(Object obj, ObjectStreamClass desc)
+    private FieldValues defaultReadFields(Object obj, ObjectStreamClass desc)
         throws IOException
     {
         Class<?> cl = desc.forClass();
@@ -1977,22 +2027,19 @@
             throw new ClassCastException();
         }
 
+        byte[] primVals = null;
         int primDataSize = desc.getPrimDataSize();
         if (primDataSize > 0) {
-            if (primVals == null || primVals.length < primDataSize) {
-                primVals = new byte[primDataSize];
-            }
+            primVals = new byte[primDataSize];
             bin.readFully(primVals, 0, primDataSize, false);
-            if (obj != null) {
-                desc.setPrimFieldValues(obj, primVals);
-            }
         }
 
+        Object[] objVals = null;
         int numObjFields = desc.getNumObjFields();
         if (numObjFields > 0) {
             int objHandle = passHandle;
             ObjectStreamField[] fields = desc.getFields(false);
-            Object[] objVals = new Object[numObjFields];
+            objVals = new Object[numObjFields];
             int numPrimFields = fields.length - objVals.length;
             for (int i = 0; i < objVals.length; i++) {
                 ObjectStreamField f = fields[numPrimFields + i];
@@ -2001,11 +2048,30 @@
                     handles.markDependency(objHandle, passHandle);
                 }
             }
-            if (obj != null) {
-                desc.setObjFieldValues(obj, objVals);
-            }
             passHandle = objHandle;
         }
+
+        return new FieldValues(primVals, objVals);
+    }
+
+    /** Throws ClassCastException if any value is not assignable. */
+    private void defaultCheckFieldValues(Object obj, ObjectStreamClass desc,
+                                         FieldValues values) {
+        Object[] objectValues = values.objValues;
+        if (objectValues != null)
+            desc.checkObjFieldValueTypes(obj, objectValues);
+    }
+
+    /** Sets field values in obj. */
+    private void defaultSetFieldValues(Object obj, ObjectStreamClass desc,
+                                       FieldValues values) {
+        byte[] primValues = values.primValues;
+        Object[] objectValues = values.objValues;
+
+        if (primValues != null)
+            desc.setPrimFieldValues(obj, primValues);
+        if (objectValues != null)
+            desc.setObjFieldValues(obj, objectValues);
     }
 
     /**
--- a/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1253,6 +1253,15 @@
     }
 
     /**
+     * Checks that the given values, from array vals starting at offset 0,
+     * are assignable to the given serializable object fields.
+     * @throws ClassCastException if any value is not assignable
+     */
+    void checkObjFieldValueTypes(Object obj, Object[] vals) {
+        fieldRefl.checkObjectFieldValueTypes(obj, vals);
+    }
+
+    /**
      * Sets the serializable object fields of object obj using values from
      * array vals starting at offset 0.  It is the responsibility of the caller
      * to ensure that obj is of the proper type if non-null.
@@ -2070,6 +2079,15 @@
         }
 
         /**
+         * Checks that the given values, from array vals starting at offset 0,
+         * are assignable to the given serializable object fields.
+         * @throws ClassCastException if any value is not assignable
+         */
+        void checkObjectFieldValueTypes(Object obj, Object[] vals) {
+            setObjFieldValues(obj, vals, true);
+        }
+
+        /**
          * Sets the serializable object fields of object obj using values from
          * array vals starting at offset 0.  The caller is responsible for
          * ensuring that obj is of the proper type; however, attempts to set a
@@ -2077,6 +2095,10 @@
          * ClassCastException.
          */
         void setObjFieldValues(Object obj, Object[] vals) {
+            setObjFieldValues(obj, vals, false);
+        }
+
+        private void setObjFieldValues(Object obj, Object[] vals, boolean dryRun) {
             if (obj == null) {
                 throw new NullPointerException();
             }
@@ -2101,7 +2123,8 @@
                                 f.getType().getName() + " in instance of " +
                                 obj.getClass().getName());
                         }
-                        unsafe.putObject(obj, key, val);
+                        if (!dryRun)
+                            unsafe.putObject(obj, key, val);
                         break;
 
                     default:
--- a/src/java.base/share/classes/java/lang/Character.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/lang/Character.java	Thu Jun 11 00:51:11 2015 +0200
@@ -646,13 +646,11 @@
      */
     public static final class UnicodeBlock extends Subset {
         /**
-         * 510  - the expected number of enteties
+         * 510  - the expected number of entities
          * 0.75 - the default load factor of HashMap
          */
-        private static final int INITIAL_CAPACITY =
-                (int)(510 / 0.75f + 1.0f);
         private static Map<String, UnicodeBlock> map =
-                new HashMap<>(INITIAL_CAPACITY);
+                new HashMap<>((int)(510 / 0.75f + 1.0f));
 
         /**
          * Creates a UnicodeBlock with the given identifier name.
--- a/src/java.base/share/classes/java/lang/Process.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/lang/Process.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. 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
@@ -26,25 +26,31 @@
 package java.lang;
 
 import java.io.*;
+import java.lang.ProcessBuilder.Redirect;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
 
 /**
+ * {@code Process} provides control of native processes started by
+ * ProcessBuilder.start and Runtime.exec.
+ * The class provides methods for performing input from the process, performing
+ * output to the process, waiting for the process to complete,
+ * checking the exit status of the process, and destroying (killing)
+ * the process.
  * The {@link ProcessBuilder#start()} and
  * {@link Runtime#exec(String[],String[],File) Runtime.exec}
  * methods create a native process and return an instance of a
  * subclass of {@code Process} that can be used to control the process
- * and obtain information about it.  The class {@code Process}
- * provides methods for performing input from the process, performing
- * output to the process, waiting for the process to complete,
- * checking the exit status of the process, and destroying (killing)
- * the process.
+ * and obtain information about it.
  *
  * <p>The methods that create processes may not work well for special
  * processes on certain native platforms, such as native windowing
  * processes, daemon processes, Win16/DOS processes on Microsoft
  * Windows, or shell scripts.
  *
- * <p>By default, the created subprocess does not have its own terminal
+ * <p>By default, the created process does not have its own terminal
  * or console.  All its standard I/O (i.e. stdin, stdout, stderr)
  * operations will be redirected to the parent process, where they can
  * be accessed via the streams obtained using the methods
@@ -52,35 +58,49 @@
  * {@link #getInputStream()}, and
  * {@link #getErrorStream()}.
  * The parent process uses these streams to feed input to and get output
- * from the subprocess.  Because some native platforms only provide
+ * from the process.  Because some native platforms only provide
  * limited buffer size for standard input and output streams, failure
  * to promptly write the input stream or read the output stream of
- * the subprocess may cause the subprocess to block, or even deadlock.
+ * the process may cause the process to block, or even deadlock.
  *
  * <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
- * subprocess I/O can also be redirected</a>
+ * process I/O can also be redirected</a>
  * using methods of the {@link ProcessBuilder} class.
  *
- * <p>The subprocess is not killed when there are no more references to
- * the {@code Process} object, but rather the subprocess
+ * <p>The process is not killed when there are no more references to
+ * the {@code Process} object, but rather the process
  * continues executing asynchronously.
  *
- * <p>There is no requirement that a process represented by a {@code
+ * <p>There is no requirement that the process represented by a {@code
  * Process} object execute asynchronously or concurrently with respect
  * to the Java process that owns the {@code Process} object.
  *
  * <p>As of 1.5, {@link ProcessBuilder#start()} is the preferred way
  * to create a {@code Process}.
  *
+ * <p>Subclasses of Process should override the {@link #onExit()} and
+ * {@link #toHandle()} methods to provide a fully functional Process including the
+ * {@link #getPid() process id},
+ * {@link #info() information about the process},
+ * {@link #children() direct children}, and
+ * {@link #allChildren() direct and indirect children} of the process.
+ * Delegating to the underlying Process or ProcessHandle is typically
+ * easiest and most efficient.
+ *
  * @since   1.0
  */
 public abstract class Process {
     /**
+     * Default constructor for Process.
+     */
+    public Process() {}
+
+    /**
      * Returns the output stream connected to the normal input of the
-     * subprocess.  Output to the stream is piped into the standard
+     * process.  Output to the stream is piped into the standard
      * input of the process represented by this {@code Process} object.
      *
-     * <p>If the standard input of the subprocess has been redirected using
+     * <p>If the standard input of the process has been redirected using
      * {@link ProcessBuilder#redirectInput(Redirect)
      * ProcessBuilder.redirectInput}
      * then this method will return a
@@ -90,42 +110,42 @@
      * output stream to be buffered.
      *
      * @return the output stream connected to the normal input of the
-     *         subprocess
+     *         process
      */
     public abstract OutputStream getOutputStream();
 
     /**
      * Returns the input stream connected to the normal output of the
-     * subprocess.  The stream obtains data piped from the standard
+     * process.  The stream obtains data piped from the standard
      * output of the process represented by this {@code Process} object.
      *
-     * <p>If the standard output of the subprocess has been redirected using
+     * <p>If the standard output of the process has been redirected using
      * {@link ProcessBuilder#redirectOutput(Redirect)
      * ProcessBuilder.redirectOutput}
      * then this method will return a
      * <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
      *
-     * <p>Otherwise, if the standard error of the subprocess has been
+     * <p>Otherwise, if the standard error of the process has been
      * redirected using
      * {@link ProcessBuilder#redirectErrorStream(boolean)
      * ProcessBuilder.redirectErrorStream}
      * then the input stream returned by this method will receive the
-     * merged standard output and the standard error of the subprocess.
+     * merged standard output and the standard error of the process.
      *
      * <p>Implementation note: It is a good idea for the returned
      * input stream to be buffered.
      *
      * @return the input stream connected to the normal output of the
-     *         subprocess
+     *         process
      */
     public abstract InputStream getInputStream();
 
     /**
      * Returns the input stream connected to the error output of the
-     * subprocess.  The stream obtains data piped from the error output
+     * process.  The stream obtains data piped from the error output
      * of the process represented by this {@code Process} object.
      *
-     * <p>If the standard error of the subprocess has been redirected using
+     * <p>If the standard error of the process has been redirected using
      * {@link ProcessBuilder#redirectError(Redirect)
      * ProcessBuilder.redirectError} or
      * {@link ProcessBuilder#redirectErrorStream(boolean)
@@ -137,19 +157,19 @@
      * input stream to be buffered.
      *
      * @return the input stream connected to the error output of
-     *         the subprocess
+     *         the process
      */
     public abstract InputStream getErrorStream();
 
     /**
      * Causes the current thread to wait, if necessary, until the
      * process represented by this {@code Process} object has
-     * terminated.  This method returns immediately if the subprocess
-     * has already terminated.  If the subprocess has not yet
+     * terminated.  This method returns immediately if the process
+     * has already terminated.  If the process has not yet
      * terminated, the calling thread will be blocked until the
-     * subprocess exits.
+     * process exits.
      *
-     * @return the exit value of the subprocess represented by this
+     * @return the exit value of the process represented by this
      *         {@code Process} object.  By convention, the value
      *         {@code 0} indicates normal termination.
      * @throws InterruptedException if the current thread is
@@ -161,10 +181,10 @@
 
     /**
      * Causes the current thread to wait, if necessary, until the
-     * subprocess represented by this {@code Process} object has
+     * process represented by this {@code Process} object has
      * terminated, or the specified waiting time elapses.
      *
-     * <p>If the subprocess has already terminated then this method returns
+     * <p>If the process has already terminated then this method returns
      * immediately with the value {@code true}.  If the process has not
      * terminated and the timeout value is less than, or equal to, zero, then
      * this method returns immediately with the value {@code false}.
@@ -176,8 +196,8 @@
      *
      * @param timeout the maximum time to wait
      * @param unit the time unit of the {@code timeout} argument
-     * @return {@code true} if the subprocess has exited and {@code false} if
-     *         the waiting time elapsed before the subprocess has exited.
+     * @return {@code true} if the process has exited and {@code false} if
+     *         the waiting time elapsed before the process has exited.
      * @throws InterruptedException if the current thread is interrupted
      *         while waiting.
      * @throws NullPointerException if unit is null
@@ -204,41 +224,60 @@
     }
 
     /**
-     * Returns the exit value for the subprocess.
+     * Returns the exit value for the process.
      *
-     * @return the exit value of the subprocess represented by this
+     * @return the exit value of the process represented by this
      *         {@code Process} object.  By convention, the value
      *         {@code 0} indicates normal termination.
-     * @throws IllegalThreadStateException if the subprocess represented
+     * @throws IllegalThreadStateException if the process represented
      *         by this {@code Process} object has not yet terminated
      */
     public abstract int exitValue();
 
     /**
-     * Kills the subprocess. Whether the subprocess represented by this
-     * {@code Process} object is forcibly terminated or not is
+     * Kills the process.
+     * Whether the process represented by this {@code Process} object is
+     * {@link #supportsNormalTermination normally terminated} or not is
      * implementation dependent.
+     * Forcible process destruction is defined as the immediate termination of a
+     * process, whereas normal termination allows the process to shut down cleanly.
+     * If the process is not alive, no action is taken.
+     * <p>
+     * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
+     * {@link java.util.concurrent.CompletableFuture#complete completed}
+     * when the process has terminated.
      */
     public abstract void destroy();
 
     /**
-     * Kills the subprocess. The subprocess represented by this
+     * Kills the process forcibly. The process represented by this
      * {@code Process} object is forcibly terminated.
+     * Forcible process destruction is defined as the immediate termination of a
+     * process, whereas normal termination allows the process to shut down cleanly.
+     * If the process is not alive, no action is taken.
+     * <p>
+     * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
+     * {@link java.util.concurrent.CompletableFuture#complete completed}
+     * when the process has terminated.
+     * <p>
+     * Invoking this method on {@code Process} objects returned by
+     * {@link ProcessBuilder#start} and {@link Runtime#exec} forcibly terminate
+     * the process.
      *
-     * <p>The default implementation of this method invokes {@link #destroy}
-     * and so may not forcibly terminate the process. Concrete implementations
-     * of this class are strongly encouraged to override this method with a
-     * compliant implementation.  Invoking this method on {@code Process}
-     * objects returned by {@link ProcessBuilder#start} and
-     * {@link Runtime#exec} will forcibly terminate the process.
-     *
-     * <p>Note: The subprocess may not terminate immediately.
+     * @implSpec
+     * The default implementation of this method invokes {@link #destroy}
+     * and so may not forcibly terminate the process.
+     * @implNote
+     * Concrete implementations of this class are strongly encouraged to override
+     * this method with a compliant implementation.
+     * @apiNote
+     * The process may not terminate immediately.
      * i.e. {@code isAlive()} may return true for a brief period
      * after {@code destroyForcibly()} is called. This method
      * may be chained to {@code waitFor()} if needed.
      *
      * @return the {@code Process} object representing the
-     *         subprocess to be forcibly destroyed.
+     *         process forcibly destroyed
      * @since 1.8
      */
     public Process destroyForcibly() {
@@ -247,10 +286,36 @@
     }
 
     /**
-     * Tests whether the subprocess represented by this {@code Process} is
+     * Returns {@code true} if the implementation of {@link #destroy} is to
+     * normally terminate the process,
+     * Returns {@code false} if the implementation of {@code destroy}
+     * forcibly and immediately terminates the process.
+     * <p>
+     * Invoking this method on {@code Process} objects returned by
+     * {@link ProcessBuilder#start} and {@link Runtime#exec} return
+     * {@code true} or {@code false} depending on the platform implementation.
+     *
+     * @implSpec
+     * This implementation throws an instance of
+     * {@link java.lang.UnsupportedOperationException} and performs no other action.
+     *
+     * @return {@code true} if the implementation of {@link #destroy} is to
+     *         normally terminate the process;
+     *         otherwise, {@link #destroy} forcibly terminates the process
+     * @throws UnsupportedOperationException if the Process implementation
+     *         does not support this operation
+     * @since 1.9
+     */
+    public boolean supportsNormalTermination() {
+        throw new UnsupportedOperationException(this.getClass()
+                + ".supportsNormalTermination() not supported" );
+    }
+
+    /**
+     * Tests whether the process represented by this {@code Process} is
      * alive.
      *
-     * @return {@code true} if the subprocess represented by this
+     * @return {@code true} if the process represented by this
      *         {@code Process} object has not yet terminated.
      * @since 1.8
      */
@@ -264,16 +329,222 @@
     }
 
     /**
-     * Returns the native process id of the subprocess.
-     * The native process id is an identification number that the operating
+     * Returns the native process ID of the process.
+     * The native process ID is an identification number that the operating
      * system assigns to the process.
      *
-     * @return the native process id of the subprocess
+     * @implSpec
+     * The implementation of this method returns the process id as:
+     * {@link #toHandle toHandle().getPid()}.
+     *
+     * @return the native process id of the process
      * @throws UnsupportedOperationException if the Process implementation
-     *     does not support this operation
+     *         does not support this operation
      * @since 1.9
      */
     public long getPid() {
-        throw new UnsupportedOperationException();
+        return toHandle().getPid();
     }
+
+    /**
+     * Returns a {@code CompletableFuture<Process>} for the termination of the Process.
+     * The {@link java.util.concurrent.CompletableFuture} provides the ability
+     * to trigger dependent functions or actions that may be run synchronously
+     * or asynchronously upon process termination.
+     * When the process terminates the CompletableFuture is
+     * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
+     * of the exit status of the process.
+     * <p>
+     * Calling {@code onExit().get()} waits for the process to terminate and returns
+     * the Process. The future can be used to check if the process is
+     * {@link java.util.concurrent.CompletableFuture#isDone done} or to
+     * {@link java.util.concurrent.CompletableFuture#get() wait} for it to terminate.
+     * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
+     * the CompletableFuture does not affect the Process.
+     * <p>
+     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
+     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
+     * <p>
+     * Processes returned from {@link ProcessBuilder#start} override the
+     * default implementation to provide an efficient mechanism to wait
+     * for process exit.
+     * <p>
+     * @apiNote
+     * Using {@link #onExit() onExit} is an alternative to
+     * {@link #waitFor() waitFor} that enables both additional concurrency
+     * and convenient access to the result of the Process.
+     * Lambda expressions can be used to evaluate the result of the Process
+     * execution.
+     * If there is other processing to be done before the value is used
+     * then {@linkplain #onExit onExit} is a convenient mechanism to
+     * free the current thread and block only if and when the value is needed.
+     * <br>
+     * For example, launching a process to compare two files and get a boolean if they are identical:
+     * <pre> {@code   Process p = new ProcessBuilder("cmp", "f1", "f2").start();
+     *    Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
+     *    ...
+     *    if (identical.get()) { ... }
+     * }</pre>
+     *
+     * @implSpec
+     * This implementation executes {@link #waitFor()} in a separate thread
+     * repeatedly until it returns successfully. If the execution of
+     * {@code waitFor} is interrupted, the thread's interrupt status is preserved.
+     * <p>
+     * When {@link #waitFor()} returns successfully the CompletableFuture is
+     * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
+     * of the exit status of the process.
+     *
+     * This implementation may consume a lot of memory for thread stacks if a
+     * large number of processes are waited for concurrently.
+     * <p>
+     * External implementations should override this method and provide
+     * a more efficient implementation. For example, to delegate to the underlying
+     * process, it can do the following:
+     * <pre>{@code
+     *    public CompletableFuture<Process> onExit() {
+     *       return delegate.onExit().thenApply(p -> this);
+     *    }
+     * }</pre>
+     *
+     * @return a new {@code CompletableFuture<Process>} for the Process
+     *
+     * @since 1.9
+     */
+    public CompletableFuture<Process> onExit() {
+        return CompletableFuture.supplyAsync(this::waitForInternal);
+    }
+
+    /**
+     * Wait for the process to exit by calling {@code waitFor}.
+     * If the thread is interrupted, remember the interrupted state to
+     * be restored before returning. Use ForkJoinPool.ManagedBlocker
+     * so that the number of workers in case ForkJoinPool is used is
+     * compensated when the thread blocks in waitFor().
+     *
+     * @return the Process
+     */
+    private Process waitForInternal() {
+        boolean interrupted = false;
+        while (true) {
+            try {
+                ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
+                    @Override
+                    public boolean block() throws InterruptedException {
+                        waitFor();
+                        return true;
+                    }
+
+                    @Override
+                    public boolean isReleasable() {
+                        return !isAlive();
+                    }
+                });
+                break;
+            } catch (InterruptedException x) {
+                interrupted = true;
+            }
+        }
+        if (interrupted) {
+            Thread.currentThread().interrupt();
+        }
+        return this;
+    }
+
+    /**
+     * Returns a ProcessHandle for the Process.
+     *
+     * {@code Process} objects returned by {@link ProcessBuilder#start} and
+     * {@link Runtime#exec} implement {@code toHandle} as the equivalent of
+     * {@link ProcessHandle#of(long) ProcessHandle.of(pid)} including the
+     * check for a SecurityManager and {@code RuntimePermission("manageProcess")}.
+     *
+     * @implSpec
+     * This implementation throws an instance of
+     * {@link java.lang.UnsupportedOperationException} and performs no other action.
+     * Subclasses should override this method to provide a ProcessHandle for the
+     * process.  The methods {@link #getPid}, {@link #info}, {@link #children},
+     * and {@link #allChildren}, unless overridden, operate on the ProcessHandle.
+     *
+     * @return Returns a ProcessHandle for the Process
+     * @throws UnsupportedOperationException if the Process implementation
+     *         does not support this operation
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @since 1.9
+     */
+    public ProcessHandle toHandle() {
+        throw new UnsupportedOperationException(this.getClass()
+                + ".toHandle() not supported");
+    }
+
+    /**
+     * Returns a snapshot of information about the process.
+     *
+     * <p> An {@link ProcessHandle.Info} instance has various accessor methods
+     * that return information about the process, if the process is alive and
+     * the information is available, otherwise {@code null} is returned.
+     *
+     * @implSpec
+     * This implementation returns information about the process as:
+     * {@link #toHandle toHandle().info()}.
+     *
+     * @return a snapshot of information about the process, always non-null
+     * @throws UnsupportedOperationException if the Process implementation
+     *         does not support this operation
+     * @since 1.9
+     */
+    public ProcessHandle.Info info() {
+        return toHandle().info();
+    }
+
+    /**
+     * Returns a snapshot of the direct children of the process.
+     * A process that is {@link #isAlive not alive} has zero children.
+     * <p>
+     * <em>Note that processes are created and terminate asynchronously.
+     * There is no guarantee that a process is {@link #isAlive alive}.
+     * </em>
+     *
+     * @implSpec
+     * This implementation returns the direct children as:
+     * {@link #toHandle toHandle().children()}.
+     *
+     * @return a Stream of ProcessHandles for processes that are direct children
+     *         of the process
+     * @throws UnsupportedOperationException if the Process implementation
+     *         does not support this operation
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @since 1.9
+     */
+    public Stream<ProcessHandle> children() {
+        return toHandle().children();
+    }
+
+    /**
+     * Returns a snapshot of the direct and indirect children of the process.
+     * A process that is {@link #isAlive not alive} has zero children.
+     * <p>
+     * <em>Note that processes are created and terminate asynchronously.
+     * There is no guarantee that a process is {@link #isAlive alive}.
+     * </em>
+     *
+     * @implSpec
+     * This implementation returns all children as:
+     * {@link #toHandle toHandle().allChildren()}.
+     *
+     * @return a Stream of ProcessHandles for processes that are direct and
+     *         indirect children of the process
+     * @throws UnsupportedOperationException if the Process implementation
+     *         does not support this operation
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @since 1.9
+     */
+    public Stream<ProcessHandle> allChildren() {
+        return toHandle().allChildren();
+    }
+
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/ProcessHandle.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+
+/**
+ * ProcessHandle identifies and provides control of native processes. Each
+ * individual process can be monitored for liveness, list its children,
+ * get information about the process or destroy it.
+ * By comparison, {@link java.lang.Process Process} instances were started
+ * by the current process and additionally provide access to the process
+ * input, output, and error streams.
+ * <p>
+ * The native process ID is an identification number that the
+ * operating system assigns to the process.
+ * The range for process id values is dependent on the operating system.
+ * For example, an embedded system might use a 16-bit value.
+ * Status information about a process is retrieved from the native system
+ * and may change asynchronously; processes may be created or terminate
+ * spontaneously.
+ * The time between when a process terminates and the process id
+ * is reused for a new process is unpredictable.
+ * Race conditions can exist between checking the status of a process and
+ * acting upon it. When using ProcessHandles avoid assumptions
+ * about the liveness or identity of the underlying process.
+ * <p>
+ * Each ProcessHandle identifies and allows control of a process in the native
+ * system. ProcessHandles are returned from the factory methods {@link #current()},
+ * {@link #of(long)},
+ * {@link #children}, {@link #allChildren}, {@link #parent()} and
+ * {@link #allProcesses()}.
+ * <p>
+ * The {@link Process} instances created by {@link ProcessBuilder} can be queried
+ * for a ProcessHandle that provides information about the Process.
+ * ProcessHandle references should not be freely distributed.
+ *
+ * <p>
+ * A {@link java.util.concurrent.CompletableFuture} available from {@link #onExit}
+ * can be used to wait for process termination, and possibly trigger dependent
+ * actions.
+ * <p>
+ * The factory methods limit access to ProcessHandles using the
+ * SecurityManager checking the {@link RuntimePermission RuntimePermission("manageProcess")}.
+ * The ability to control processes is also restricted by the native system,
+ * ProcessHandle provides no more access to, or control over, the native process
+ * than would be allowed by a native application.
+ * <p>
+ * @implSpec
+ * In the case where ProcessHandles cannot be supported then the factory
+ * methods must consistently throw {@link java.lang.UnsupportedOperationException}.
+ * The methods of this class throw {@link java.lang.UnsupportedOperationException}
+ * if the operating system does not allow access to query or kill a process.
+ *
+ * @see Process
+ * @since 1.9
+ */
+public interface ProcessHandle extends Comparable<ProcessHandle> {
+
+    /**
+     * Returns the native process ID of the process. The native process ID is an
+     * identification number that the operating system assigns to the process.
+     *
+     * @return the native process ID of the process
+     * @throws UnsupportedOperationException if the implementation
+     *         does not support this operation
+     */
+    long getPid();
+
+    /**
+     * Returns an {@code Optional<ProcessHandle>} for an existing native process.
+     *
+     * @param pid a native process ID
+     * @return an {@code Optional<ProcessHandle>} of the PID for the process;
+     *         the {@code Optional} is empty if the process does not exist
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @throws UnsupportedOperationException if the implementation
+     *         does not support this operation
+     */
+    public static Optional<ProcessHandle> of(long pid) {
+        return ProcessHandleImpl.get(pid);
+    }
+
+    /**
+     * Returns a ProcessHandle for the current process. The ProcessHandle cannot be
+     * used to destroy the current process, use {@link System#exit System.exit} instead.
+     *
+     * @return a ProcessHandle for the current process
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @throws UnsupportedOperationException if the implementation
+     *         does not support this operation
+     */
+    public static ProcessHandle current() {
+        return ProcessHandleImpl.current();
+    }
+
+    /**
+     * Returns an {@code Optional<ProcessHandle>} for the parent process.
+     * Note that Processes in a zombie state usually don't have a parent.
+     *
+     * @return an {@code Optional<ProcessHandle>} of the parent process;
+     *         the {@code Optional} is empty if the child process does not have a parent
+     *         or if the parent is not available, possibly due to operating system limitations
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     */
+    Optional<ProcessHandle> parent();
+
+    /**
+     * Returns a snapshot of the current direct children of the process.
+     * A process that is {@link #isAlive not alive} has zero children.
+     * <p>
+     * <em>Note that processes are created and terminate asynchronously.
+     * There is no guarantee that a process is {@link #isAlive alive}.
+     * </em>
+     *
+     * @return a Stream of ProcessHandles for processes that are direct children
+     *         of the process
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     */
+    Stream<ProcessHandle> children();
+
+    /**
+     * Returns a snapshot of the current direct and indirect children of the process.
+     * A process that is {@link #isAlive not alive} has zero children.
+     * <p>
+     * <em>Note that processes are created and terminate asynchronously.
+     * There is no guarantee that a process is {@link #isAlive alive}.
+     * </em>
+     *
+     * @return a Stream of ProcessHandles for processes that are direct and
+     *         indirect children of the process
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     */
+    Stream<ProcessHandle> allChildren();
+
+    /**
+     * Returns a snapshot of all processes visible to the current process.
+     * <p>
+     * <em>Note that processes are created and terminate asynchronously. There
+     * is no guarantee that a process in the stream is alive or that no other
+     * processes may have been created since the inception of the snapshot.
+     * </em>
+     *
+     * @return a Stream of ProcessHandles for all processes
+     * @throws SecurityException if a security manager has been installed and
+     *         it denies RuntimePermission("manageProcess")
+     * @throws UnsupportedOperationException if the implementation
+     *         does not support this operation
+     */
+    static Stream<ProcessHandle> allProcesses() {
+        return ProcessHandleImpl.children(0);
+    }
+
+    /**
+     * Returns a snapshot of information about the process.
+     *
+     * <p> An {@code Info} instance has various accessor methods that return
+     * information about the process, if the process is alive and the
+     * information is available.
+     *
+     * @return a snapshot of information about the process, always non-null
+     */
+    Info info();
+
+    /**
+     * Information snapshot about the process.
+     * The attributes of a process vary by operating system and are not available
+     * in all implementations.  Information about processes is limited
+     * by the operating system privileges of the process making the request.
+     * The return types are {@code Optional<T>} allowing explicit tests
+     * and actions if the value is available.
+     * @since 1.9
+     */
+    public interface Info {
+        /**
+         * Returns the executable pathname of the process.
+         *
+         * @return an {@code Optional<String>} of the executable pathname
+         *         of the process
+         */
+        public Optional<String> command();
+
+        /**
+         * Returns an array of Strings of the arguments of the process.
+         *
+         * @return an {@code Optional<String[]>} of the arguments of the process
+         */
+        public Optional<String[]> arguments();
+
+        /**
+         * Returns the start time of the process.
+         *
+         * @return an {@code Optional<Instant>} of the start time of the process
+         */
+        public Optional<Instant> startInstant();
+
+        /**
+         * Returns the total cputime accumulated of the process.
+         *
+         * @return an {@code Optional<Duration>} for the accumulated total cputime
+         */
+        public Optional<Duration> totalCpuDuration();
+
+        /**
+         * Return the user of the process.
+         *
+         * @return an {@code Optional<String>} for the user of the process
+         */
+        public Optional<String> user();
+    }
+
+    /**
+     * Returns a {@code CompletableFuture<ProcessHandle>} for the termination
+     * of the process.
+     * The {@link java.util.concurrent.CompletableFuture} provides the ability
+     * to trigger dependent functions or actions that may be run synchronously
+     * or asynchronously upon process termination.
+     * When the process terminates the CompletableFuture is
+     * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
+     * of the exit status of the process.
+     * The {@code onExit} method can be called multiple times to invoke
+     * independent actions when the process exits.
+     * <p>
+     * Calling {@code onExit().get()} waits for the process to terminate and returns
+     * the ProcessHandle. The future can be used to check if the process is
+     * {@link java.util.concurrent.CompletableFuture#isDone done} or to
+     * {@link java.util.concurrent.Future#get() wait} for it to terminate.
+     * {@link java.util.concurrent.Future#cancel(boolean) Cancelling}
+     * the CompleteableFuture does not affect the Process.
+     * <p>
+     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
+     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
+     *
+     * @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle
+     *
+     * @throws IllegalStateException if the process is the current process
+     */
+    CompletableFuture<ProcessHandle> onExit();
+
+    /**
+     * Returns {@code true} if the implementation of {@link #destroy}
+     * normally terminates the process.
+     * Returns {@code false} if the implementation of {@code destroy}
+     * forcibly and immediately terminates the process.
+     *
+     * @return {@code true} if the implementation of {@link #destroy}
+     *         normally terminates the process;
+     *         otherwise, {@link #destroy} forcibly terminates the process
+     */
+    boolean supportsNormalTermination();
+
+    /**
+     * Requests the process to be killed.
+     * Whether the process represented by this {@code ProcessHandle} object is
+     * {@link #supportsNormalTermination normally terminated} or not is
+     * implementation dependent.
+     * Forcible process destruction is defined as the immediate termination of the
+     * process, whereas normal termination allows the process to shut down cleanly.
+     * If the process is not alive, no action is taken.
+     * The operating system access controls may prevent the process
+     * from being killed.
+     * <p>
+     * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
+     * {@link java.util.concurrent.CompletableFuture#complete completed}
+     * when the process has terminated.
+     * <p>
+     * Note: The process may not terminate immediately.
+     * For example, {@code isAlive()} may return true for a brief period
+     * after {@code destroy()} is called.
+     *
+     * @return {@code true} if termination was successfully requested,
+     *         otherwise {@code false}
+     * @throws IllegalStateException if the process is the current process
+     */
+    boolean destroy();
+
+    /**
+     * Requests the process to be killed forcibly.
+     * The process represented by this {@code ProcessHandle} object is
+     * forcibly terminated.
+     * Forcible process destruction is defined as the immediate termination of the
+     * process, whereas normal termination allows the process to shut down cleanly.
+     * If the process is not alive, no action is taken.
+     * The operating system access controls may prevent the process
+     * from being killed.
+     * <p>
+     * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
+     * {@link java.util.concurrent.CompletableFuture#complete completed}
+     * when the process has terminated.
+     * <p>
+     * Note: The process may not terminate immediately.
+     * For example, {@code isAlive()} may return true for a brief period
+     * after {@code destroyForcibly()} is called.
+     *
+     * @return {@code true} if termination was successfully requested,
+     *         otherwise {@code false}
+     * @throws IllegalStateException if the process is the current process
+     */
+    boolean destroyForcibly();
+
+    /**
+     * Tests whether the process represented by this {@code ProcessHandle} is alive.
+     * Process termination is implementation and operating system specific.
+     * The process is considered alive as long as the PID is valid.
+     *
+     * @return {@code true} if the process represented by this
+     *         {@code ProcessHandle} object has not yet terminated
+     */
+   boolean isAlive();
+
+    /**
+     * Compares this ProcessHandle with the specified ProcessHandle for order.
+     * The order is not specified, but is consistent with {@link Object#equals},
+     * which returns {@code true} if and only if two instances of ProcessHandle
+     * are of the same implementation and represent the same system process.
+     * Comparison is only supported among objects of same implementation.
+     * If attempt is made to mutually compare two different implementations
+     * of {@link ProcessHandle}s, {@link ClassCastException} is thrown.
+     *
+     * @param other the ProcessHandle to be compared
+     * @return a negative integer, zero, or a positive integer as this object
+     * is less than, equal to, or greater than the specified object.
+     * @throws NullPointerException if the specified object is null
+     * @throws ClassCastException if the specified object is not of same class
+     *         as this object
+     */
+    @Override
+    int compareTo(ProcessHandle other);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang;
+
+import java.security.PrivilegedAction;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import sun.misc.InnocuousThread;
+
+import static java.security.AccessController.doPrivileged;
+
+/**
+ * ProcessHandleImpl is the implementation of ProcessHandle.
+ *
+ * @see Process
+ * @since 1.9
+ */
+final class ProcessHandleImpl implements ProcessHandle {
+
+    /**
+     * The thread pool of "process reaper" daemon threads.
+     */
+    private static final Executor processReaperExecutor =
+            doPrivileged((PrivilegedAction<Executor>) () -> {
+
+                ThreadGroup tg = Thread.currentThread().getThreadGroup();
+                while (tg.getParent() != null) tg = tg.getParent();
+                ThreadGroup systemThreadGroup = tg;
+
+                ThreadFactory threadFactory = grimReaper -> {
+                    // Our thread stack requirement is quite modest.
+                    Thread t = new Thread(systemThreadGroup, grimReaper,
+                            "process reaper", 32768);
+                    t.setDaemon(true);
+                    // A small attempt (probably futile) to avoid priority inversion
+                    t.setPriority(Thread.MAX_PRIORITY);
+                    return t;
+                };
+
+                return Executors.newCachedThreadPool(threadFactory);
+            });
+
+    private static class ExitCompletion extends CompletableFuture<Integer> {
+        final boolean isReaping;
+
+        ExitCompletion(boolean isReaping) {
+            this.isReaping = isReaping;
+        }
+    }
+
+    private static final ConcurrentMap<Long, ExitCompletion>
+        completions = new ConcurrentHashMap<>();
+
+    /**
+     * Returns a CompletableFuture that completes with process exit status when
+     * the process completes.
+     *
+     * @param shouldReap true if the exit value should be reaped
+     */
+    static CompletableFuture<Integer> completion(long pid, boolean shouldReap) {
+        // check canonicalizing cache 1st
+        ExitCompletion completion = completions.get(pid);
+        // re-try until we get a completion that shouldReap => isReaping
+        while (completion == null || (shouldReap && !completion.isReaping)) {
+            ExitCompletion newCompletion = new ExitCompletion(shouldReap);
+            if (completion == null) {
+                completion = completions.putIfAbsent(pid, newCompletion);
+            } else {
+                completion = completions.replace(pid, completion, newCompletion)
+                    ? null : completions.get(pid);
+            }
+            if (completion == null) {
+                // newCompletion has just been installed successfully
+                completion = newCompletion;
+                // spawn a thread to wait for and deliver the exit value
+                processReaperExecutor.execute(() -> {
+                    int exitValue = waitForProcessExit0(pid, shouldReap);
+                    newCompletion.complete(exitValue);
+                    // remove from cache afterwards
+                    completions.remove(pid, newCompletion);
+                });
+            }
+        }
+        return completion;
+    }
+
+    @Override
+    public CompletableFuture<ProcessHandle> onExit() {
+        if (this.equals(current)) {
+            throw new IllegalStateException("onExit for current process not allowed");
+        }
+
+        return ProcessHandleImpl.completion(getPid(), false)
+                .handleAsync((exitStatus, unusedThrowable) -> this);
+    }
+
+    /**
+     * Wait for the process to exit, return the value.
+     * Conditionally reap the value if requested
+     * @param pid the processId
+     * @param reapvalue if true, the value is retrieved,
+     *                   else return the value and leave the process waitable
+     *
+     * @return the value or -1 if an error occurs
+     */
+    private static native int waitForProcessExit0(long pid, boolean reapvalue);
+
+    /**
+     * Cache the ProcessHandle of this process.
+     */
+    private static final ProcessHandleImpl current =
+            new ProcessHandleImpl(getCurrentPid0());
+
+    /**
+     * The pid of this ProcessHandle.
+     */
+    private final long pid;
+
+    /**
+     * Private constructor.  Instances are created by the {@code get(long)} factory.
+     * @param pid the pid for this instance
+     */
+    private ProcessHandleImpl(long pid) {
+        this.pid = pid;
+    }
+
+    /**
+     * Returns a ProcessHandle for an existing native process.
+     *
+     * @param pid the native process identifier
+     * @return The ProcessHandle for the pid if the process is alive;
+     *      or {@code null} if the process ID does not exist in the native system.
+     * @throws SecurityException if RuntimePermission("manageProcess") is not granted
+     */
+    static Optional<ProcessHandle> get(long pid) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("manageProcess"));
+        }
+        return Optional.ofNullable(isAlive0(pid) ? new ProcessHandleImpl(pid) : null);
+    }
+
+    /**
+     * Returns a ProcessHandle corresponding known to exist pid.
+     * Called from ProcessImpl, it does not perform a security check or check if the process is alive.
+     * @param pid of the known to exist process
+     * @return a ProcessHandle corresponding to an existing Process instance
+     */
+    static ProcessHandle getUnchecked(long pid) {
+        return new ProcessHandleImpl(pid);
+    }
+
+    /**
+     * Returns the native process ID.
+     * A {@code long} is used to be able to fit the system specific binary values
+     * for the process.
+     *
+     * @return the native process ID
+     */
+    @Override
+    public long getPid() {
+        return pid;
+    }
+
+    /**
+     * Returns the ProcessHandle for the current native process.
+     *
+     * @return The ProcessHandle for the OS process.
+     * @throws SecurityException if RuntimePermission("manageProcess") is not granted
+     */
+    public static ProcessHandleImpl current() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("manageProcess"));
+        }
+        return current;
+    }
+
+    /**
+     * Return the pid of the current process.
+     *
+     * @return the pid of the  current process
+     */
+    private static native long getCurrentPid0();
+
+    /**
+     * Returns a ProcessHandle for the parent process.
+     *
+     * @return a ProcessHandle of the parent process; {@code null} is returned
+     *         if the child process does not have a parent
+     * @throws SecurityException           if permission is not granted by the
+     *                                     security policy
+     */
+    static Optional<ProcessHandle> parent(long pid) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("manageProcess"));
+        }
+        long ppid = parent0(pid);
+        if (ppid <= 0) {
+            return Optional.empty();
+        }
+        return get(ppid);
+    }
+
+    /**
+     * Returns the parent of the native pid argument.
+     *
+     * @return the parent of the native pid; if any, otherwise -1
+     */
+    private static native long parent0(long pid);
+
+    /**
+     * Returns the number of pids filled in to the array.
+     * @param pid if {@code pid} equals zero, then all known processes are returned;
+     *      otherwise only direct child process pids are returned
+     * @param pids an allocated long array to receive the pids
+     * @param ppids an allocated long array to receive the parent pids; may be null
+     * @return if greater than or equals to zero is the number of pids in the array;
+     *      if greater than the length of the arrays, the arrays are too small
+     */
+    private static native int getProcessPids0(long pid, long[] pids, long[] ppids);
+
+    /**
+     * Destroy the process for this ProcessHandle.
+     * @param pid the processs ID to destroy
+     * @param force {@code true} if the process should be terminated forcibly;
+     *     else {@code false} for a normal termination
+     */
+    static void destroyProcess(long pid, boolean force) {
+        destroy0(pid, force);
+    }
+
+    private static native boolean destroy0(long pid, boolean forcibly);
+
+    @Override
+    public boolean destroy() {
+        if (this.equals(current)) {
+            throw new IllegalStateException("destroy of current process not allowed");
+        }
+        return destroy0(getPid(), false);
+    }
+
+    @Override
+    public boolean destroyForcibly() {
+        if (this.equals(current)) {
+            throw new IllegalStateException("destroy of current process not allowed");
+        }
+        return destroy0(getPid(), true);
+    }
+
+
+    @Override
+    public boolean supportsNormalTermination() {
+        return ProcessImpl.SUPPORTS_NORMAL_TERMINATION;
+    }
+
+    /**
+     * Tests whether the process represented by this {@code ProcessHandle} is alive.
+     *
+     * @return {@code true} if the process represented by this
+     * {@code ProcessHandle} object has not yet terminated.
+     * @since 1.9
+     */
+    @Override
+    public boolean isAlive() {
+        return isAlive0(pid);
+    }
+
+    /**
+     * Returns true or false depending on whether the pid is alive.
+     * This must not reap the exitValue like the isAlive method above.
+     *
+     * @param pid the pid to check
+     * @return true or false
+     */
+    private static native boolean isAlive0(long pid);
+
+    @Override
+    public Optional<ProcessHandle> parent() {
+        return parent(pid);
+    }
+
+    @Override
+    public Stream<ProcessHandle> children() {
+        return children(pid);
+    }
+
+    /**
+     * Returns a Stream of the children of a process or all processes.
+     *
+     * @param pid the pid of the process for which to find the children;
+     *            0 for all processes
+     * @return a stream of ProcessHandles
+     */
+    static Stream<ProcessHandle> children(long pid) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("manageProcess"));
+        }
+        int size = 100;
+        long[] childpids = null;
+        while (childpids == null || size > childpids.length) {
+            childpids = new long[size];
+            size = getProcessPids0(pid, childpids, null);
+        }
+        return Arrays.stream(childpids, 0, size).mapToObj((id) -> new ProcessHandleImpl(id));
+    }
+
+    @Override
+    public Stream<ProcessHandle> allChildren() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("manageProcess"));
+        }
+        int size = 100;
+        long[] pids = null;
+        long[] ppids = null;
+        while (pids == null || size > pids.length) {
+            pids = new long[size];
+            ppids = new long[size];
+            size = getProcessPids0(0, pids, ppids);
+        }
+
+        int next = 0;       // index of next process to check
+        int count = -1;     // count of subprocesses scanned
+        long ppid = pid;    // start looking for this parent
+        do {
+            // Scan from next to size looking for ppid
+            // if found, exchange it to index next
+            for (int i = next; i < size; i++) {
+                if (ppids[i] == ppid) {
+                    swap(pids, i, next);
+                    swap(ppids, i, next);
+                    next++;
+                }
+            }
+            ppid = pids[++count];   // pick up the next pid to scan for
+        } while (count < next);
+
+        return Arrays.stream(pids, 0, count).mapToObj((id) -> new ProcessHandleImpl(id));
+    }
+
+    // Swap two elements in an array
+    private static void swap(long[] array, int x, int y) {
+        long v = array[x];
+        array[x] = array[y];
+        array[y] = v;
+    }
+
+    @Override
+    public ProcessHandle.Info info() {
+        return ProcessHandleImpl.Info.info(pid);
+    }
+
+    @Override
+    public int compareTo(ProcessHandle other) {
+        return Long.compare(pid, ((ProcessHandleImpl) other).pid);
+    }
+
+    @Override
+    public String toString() {
+        return Long.toString(pid);
+    }
+
+    @Override
+    public int hashCode() {
+        return Long.hashCode(pid);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return (obj instanceof ProcessHandleImpl) &&
+            (pid == ((ProcessHandleImpl) obj).pid);
+    }
+
+    /**
+     * Implementation of ProcessHandle.Info.
+     * Information snapshot about a process.
+     * The attributes of a process vary by operating system and not available
+     * in all implementations.  Additionally, information about other processes
+     * is limited by the operating system privileges of the process making the request.
+     * If a value is not available, either a {@code null} or {@code -1} is stored.
+     * The accessor methods return {@code null} if the value is not available.
+     */
+    static class Info implements ProcessHandle.Info {
+        static {
+            initIDs();
+        }
+
+        /**
+         * Initialization of JNI fieldIDs.
+         */
+        private static native void initIDs();
+
+        /**
+         * Fill in this Info instance with information about the native process.
+         * If values are not available the native code does not modify the field.
+         * @param pid  of the native process
+         */
+        private native void info0(long pid);
+
+        String command;
+        String[] arguments;
+        long startTime;
+        long totalTime;
+        String user;
+
+        Info() {
+            command = null;
+            arguments = null;
+            startTime = -1L;
+            totalTime = -1L;
+            user = null;
+        }
+
+        /**
+         * Returns the Info object with the fields from the process.
+         * Whatever fields are provided by native are returned.
+         *
+         * @param pid the native process identifier
+         * @return ProcessHandle.Info non-null; individual fields may be null
+         *          or -1 if not available.
+         */
+        public static ProcessHandle.Info info(long pid) {
+            Info info = new Info();
+            info.info0(pid);
+            return info;
+        }
+
+        @Override
+        public Optional<String> command() {
+            return Optional.ofNullable(command);
+        }
+
+        @Override
+        public Optional<String[]> arguments() {
+            return Optional.ofNullable(arguments);
+        }
+
+        @Override
+        public Optional<Instant> startInstant() {
+            return (startTime > 0)
+                    ? Optional.of(Instant.ofEpochMilli(startTime))
+                    : Optional.empty();
+        }
+
+        @Override
+        public Optional<Duration> totalCpuDuration() {
+            return (totalTime != -1)
+                    ? Optional.of(Duration.ofNanos(totalTime))
+                    : Optional.empty();
+        }
+
+        @Override
+        public Optional<String> user() {
+            return Optional.ofNullable(user);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(60);
+            sb.append('[');
+            if (user != null) {
+                sb.append("user: ");
+                sb.append(user());
+            }
+            if (command != null) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append("cmd: ");
+                sb.append(command);
+            }
+            if (arguments != null && arguments.length > 0) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append("args: ");
+                sb.append(Arrays.toString(arguments));
+            }
+            if (startTime != -1) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append("startTime: ");
+                sb.append(startInstant());
+            }
+            if (totalTime != -1) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append("totalTime: ");
+                sb.append(totalCpuDuration().toString());
+            }
+            sb.append(']');
+            return sb.toString();
+        }
+    }
+}
--- a/src/java.base/share/classes/java/lang/RuntimePermission.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/lang/RuntimePermission.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
@@ -333,6 +333,12 @@
  *   "../../../technotes/guides/plugin/developer_guide/rsa_how.html#use">
  *   usePolicy Permission</a>.</td>
  * </tr>
+ * <tr>
+ *   <td>manageProcess</td>
+ *   <td>Native process termination and information about processes
+ *       {@link ProcessHandle}.</td>
+ *   <td>Allows code to identify and terminate processes that it did not create.</td>
+ * </tr>
  *
  * <tr>
  *   <td>localeServiceProvider</td>
--- a/src/java.base/share/classes/java/lang/String.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/lang/String.java	Thu Jun 11 00:51:11 2015 +0200
@@ -2247,8 +2247,29 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
-                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
+        String starget = target.toString();
+        String srepl = replacement.toString();
+        int j = indexOf(starget);
+        if (j < 0) {
+            return this;
+        }
+        int targLen = starget.length();
+        int targLen1 = Math.max(targLen, 1);
+        final char[] value = this.value;
+        final char[] replValue = srepl.value;
+        int newLenHint = value.length - targLen + replValue.length;
+        if (newLenHint < 0) {
+            throw new OutOfMemoryError();
+        }
+        StringBuilder sb = new StringBuilder(newLenHint);
+        int i = 0;
+        do {
+            sb.append(value, i, j - i)
+                    .append(replValue);
+            i = j + targLen;
+        } while (j < value.length && (j = indexOf(starget, j + targLen1)) > 0);
+
+        return sb.append(value, i, value.length - i).toString();
     }
 
     /**
--- a/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Jun 11 00:51:11 2015 +0200
@@ -312,11 +312,16 @@
             ret = socketGetOption(opt, null);
             return ret;
         case IP_TOS:
-            ret = socketGetOption(opt, null);
-            if (ret == -1) { // ipv6 tos
-                return trafficClass;
-            } else {
-                return ret;
+            try {
+                ret = socketGetOption(opt, null);
+                if (ret == -1) { // ipv6 tos
+                    return trafficClass;
+                } else {
+                    return ret;
+                }
+            } catch (SocketException se) {
+                    // TODO - should make better effort to read TOS or TCLASS
+                    return trafficClass; // ipv6 tos
             }
         case SO_KEEPALIVE:
             ret = socketGetOption(opt, null);
--- a/src/java.base/share/classes/java/net/DatagramSocket.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1184,7 +1184,14 @@
 
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.IP_TOS, tc);
+        try {
+            getImpl().setOption(SocketOptions.IP_TOS, tc);
+        } catch (SocketException se) {
+            // not supported if socket already connected
+            // Solaris returns error in such cases
+            if(!isConnected())
+                throw se;
+        }
     }
 
     /**
--- a/src/java.base/share/classes/java/net/Socket.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/net/Socket.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1380,7 +1380,14 @@
 
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.IP_TOS, tc);
+        try {
+            getImpl().setOption(SocketOptions.IP_TOS, tc);
+        } catch (SocketException se) {
+            // not supported if socket already connected
+            // Solaris returns error in such cases
+            if(!isConnected())
+                throw se;
+        }
     }
 
     /**
--- a/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. 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
@@ -156,6 +156,7 @@
      * @param offsetAfter  the offset at and after the transition, not null
      */
     ZoneOffsetTransition(LocalDateTime transition, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
+        assert transition.getNano() == 0;
         this.epochSecond = transition.toEpochSecond(offsetBefore);
         this.transition = transition;
         this.offsetBefore = offsetBefore;
@@ -250,7 +251,7 @@
      * @return the transition instant, not null
      */
     public Instant getInstant() {
-        return transition.toInstant(offsetBefore);
+        return Instant.ofEpochSecond(epochSecond);
     }
 
     /**
@@ -403,13 +404,7 @@
      */
     @Override
     public int compareTo(ZoneOffsetTransition transition) {
-        if (epochSecond < transition.epochSecond) {
-            return -1;
-        } else if (epochSecond > transition.epochSecond) {
-            return 1;
-        } else {
-            return this.getInstant().compareTo(transition.getInstant());
-        }
+        return Long.compare(epochSecond, transition.epochSecond);
     }
 
     //-----------------------------------------------------------------------
@@ -429,7 +424,6 @@
         if (other instanceof ZoneOffsetTransition) {
             ZoneOffsetTransition d = (ZoneOffsetTransition) other;
             return epochSecond == d.epochSecond &&
-                transition.equals(d.transition) &&
                 offsetBefore.equals(d.offsetBefore) && offsetAfter.equals(d.offsetAfter);
         }
         return false;
--- a/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. 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
@@ -167,6 +167,7 @@
      * @return the rule, not null
      * @throws IllegalArgumentException if the day of month indicator is invalid
      * @throws IllegalArgumentException if the end of day flag is true when the time is not midnight
+     * @throws IllegalArgumentException if {@code time.getNano()} returns non-zero value
      */
     public static ZoneOffsetTransitionRule of(
             Month month,
@@ -190,6 +191,9 @@
         if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
             throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
         }
+        if (time.getNano() != 0) {
+            throw new IllegalArgumentException("Time's nano-of-second must be zero");
+        }
         return new ZoneOffsetTransitionRule(month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefnition, standardOffset, offsetBefore, offsetAfter);
     }
 
@@ -220,6 +224,7 @@
             ZoneOffset standardOffset,
             ZoneOffset offsetBefore,
             ZoneOffset offsetAfter) {
+        assert time.getNano() == 0;
         this.month = month;
         this.dom = (byte) dayOfMonthIndicator;
         this.dow = dayOfWeek;
--- a/src/java.base/share/classes/java/util/Enumeration.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/util/Enumeration.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. 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
@@ -40,11 +40,14 @@
  * vector, the keys of a hashtable, and the values in a hashtable.
  * Enumerations are also used to specify the input streams to a
  * <code>SequenceInputStream</code>.
- * <p>
- * NOTE: The functionality of this interface is duplicated by the Iterator
- * interface.  In addition, Iterator adds an optional remove operation, and
- * has shorter method names.  New implementations should consider using
- * Iterator in preference to Enumeration.
+ *
+ * @apiNote
+ * The functionality of this interface is duplicated by the {@link Iterator}
+ * interface.  In addition, {@code Iterator} adds an optional remove operation,
+ * and has shorter method names.  New implementations should consider using
+ * {@code Iterator} in preference to {@code Enumeration}. It is possible to
+ * adapt an {@code Enumeration} to an {@code Iterator} by using the
+ * {@link #asIterator} method.
  *
  * @see     java.util.Iterator
  * @see     java.io.SequenceInputStream
@@ -76,4 +79,49 @@
      * @exception  NoSuchElementException  if no more elements exist.
      */
     E nextElement();
+
+    /**
+     * Returns an {@link Iterator} that traverses the remaining elements
+     * covered by this enumeration. Traversal is undefined if any methods
+     * are called on this enumeration after the call to {@code asIterator}.
+     *
+     * @apiNote
+     * This method is intended to help adapt code that produces
+     * {@code Enumeration} instances to code that consumes {@code Iterator}
+     * instances. For example, the {@link java.util.jar.JarFile#entries
+     * JarFile.entries()} method returns an {@code Enumeration<JarEntry>}.
+     * This can be turned into an {@code Iterator}, and then the
+     * {@code forEachRemaining()} method can be used:
+     *
+     * <pre>{@code
+     *     JarFile jarFile = ... ;
+     *     jarFile.entries().asIterator().forEachRemaining(entry -> { ... });
+     * }</pre>
+     *
+     * (Note that there is also a {@link java.util.jar.JarFile#stream
+     * JarFile.stream()} method that returns a {@code Stream} of entries,
+     * which may be more convenient in some cases.)
+     *
+     * @implSpec
+     * The default implementation returns an {@code Iterator} whose
+     * {@link Iterator#hasNext hasNext} method calls this Enumeration's
+     * {@code hasMoreElements} method, whose {@link Iterator#next next}
+     * method calls this Enumeration's {@code nextElement} method, and
+     * whose {@link Iterator#remove remove} method throws
+     * {@code UnsupportedOperationException}.
+     *
+     * @return an Iterator representing the remaining elements of this Enumeration
+     *
+     * @since 1.9
+     */
+    default Iterator<E> asIterator() {
+        return new Iterator<>() {
+            @Override public boolean hasNext() {
+                return hasMoreElements();
+            }
+            @Override public E next() {
+                return nextElement();
+            }
+        };
+    }
 }
--- a/src/java.base/share/classes/java/util/Iterator.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/java/util/Iterator.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
@@ -43,6 +43,10 @@
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
+ * @apiNote
+ * An {@link Enumeration} can be converted into an {@code Iterator} by
+ * using the {@link Enumeration#asIterator} method.
+ *
  * @param <E> the type of elements returned by this iterator
  *
  * @author  Josh Bloch
--- a/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. 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
@@ -28,7 +28,7 @@
 import java.util.List;
 
 /**
- * Extends the <code>SSLSession</code> interface to support additional
+ * Extends the {@code SSLSession} interface to support additional
  * session attributes.
  *
  * @since 1.7
@@ -39,8 +39,8 @@
      * is willing to use.
      * <p>
      * Note: this method is used to indicate to the peer which signature
-     * algorithms may be used for digital signatures in TLS 1.2. It is
-     * not meaningful for TLS versions prior to 1.2.
+     * algorithms may be used for digital signatures in TLS/DTLS 1.2. It is
+     * not meaningful for TLS/DTLS versions prior to 1.2.
      * <p>
      * The signature algorithm name must be a standard Java Security
      * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
@@ -52,7 +52,7 @@
      * Note: the local supported signature algorithms should conform to
      * the algorithm constraints specified by
      * {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
-     * method in <code>SSLParameters</code>.
+     * method in {@code SSLParameters}.
      *
      * @return An array of supported signature algorithms, in descending
      *     order of preference.  The return value is an empty array if
@@ -67,8 +67,8 @@
      * able to use.
      * <p>
      * Note: this method is used to indicate to the local side which signature
-     * algorithms may be used for digital signatures in TLS 1.2. It is
-     * not meaningful for TLS versions prior to 1.2.
+     * algorithms may be used for digital signatures in TLS/DTLS 1.2. It is
+     * not meaningful for TLS/DTLS versions prior to 1.2.
      * <p>
      * The signature algorithm name must be a standard Java Security
      * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
--- a/src/java.base/share/classes/javax/net/ssl/SNIServerName.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SNIServerName.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. 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
@@ -31,7 +31,7 @@
  * Instances of this class represent a server name in a Server Name
  * Indication (SNI) extension.
  * <P>
- * The SNI extension is a feature that extends the SSL/TLS protocols to
+ * The SNI extension is a feature that extends the SSL/TLS/DTLS protocols to
  * indicate what server name the client is attempting to connect to during
  * handshaking.  See section 3, "Server Name Indication", of <A
  * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
--- a/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
@@ -32,12 +32,12 @@
 /**
  * Instances of this class represent a secure socket protocol
  * implementation which acts as a factory for secure socket
- * factories or <code>SSLEngine</code>s. This class is initialized
+ * factories or {@code SSLEngine}s. This class is initialized
  * with an optional set of key and trust managers and source of
  * secure random bytes.
  *
  * <p> Every implementation of the Java platform is required to support the
- * following standard <code>SSLContext</code> protocol:
+ * following standard {@code SSLContext} protocol:
  * <ul>
  * <li><tt>TLSv1</tt></li>
  * </ul>
@@ -79,7 +79,7 @@
      * <p>If a default context was set using the {@link #setDefault
      * SSLContext.setDefault()} method, it is returned. Otherwise, the first
      * call of this method triggers the call
-     * <code>SSLContext.getInstance("Default")</code>.
+     * {@code SSLContext.getInstance("Default")}.
      * If successful, that object is made the default SSL context and returned.
      *
      * <p>The default context is immediately
@@ -106,8 +106,8 @@
      * @param context the SSLContext
      * @throws  NullPointerException if context is null
      * @throws  SecurityException if a security manager exists and its
-     *          <code>checkPermission</code> method does not allow
-     *          <code>SSLPermission("setDefaultSSLContext")</code>
+     *          {@code checkPermission} method does not allow
+     *          {@code SSLPermission("setDefaultSSLContext")}
      * @since 1.6
      */
     public static synchronized void setDefault(SSLContext context) {
@@ -122,7 +122,7 @@
     }
 
     /**
-     * Returns a <code>SSLContext</code> object that implements the
+     * Returns a {@code SSLContext} object that implements the
      * specified secure socket protocol.
      *
      * <p> This method traverses the list of registered security Providers,
@@ -141,7 +141,7 @@
      *          Documentation</a>
      *          for information about standard protocol names.
      *
-     * @return the new <code>SSLContext</code> object.
+     * @return the new {@code SSLContext} object.
      *
      * @exception NoSuchAlgorithmException if no Provider supports a
      *          SSLContextSpi implementation for the
@@ -159,7 +159,7 @@
     }
 
     /**
-     * Returns a <code>SSLContext</code> object that implements the
+     * Returns a {@code SSLContext} object that implements the
      * specified secure socket protocol.
      *
      * <p> A new SSLContext object encapsulating the
@@ -179,7 +179,7 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new <code>SSLContext</code> object.
+     * @return the new {@code SSLContext} object.
      *
      * @throws NoSuchAlgorithmException if a SSLContextSpi
      *          implementation for the specified protocol is not
@@ -202,7 +202,7 @@
     }
 
     /**
-     * Returns a <code>SSLContext</code> object that implements the
+     * Returns a {@code SSLContext} object that implements the
      * specified secure socket protocol.
      *
      * <p> A new SSLContext object encapsulating the
@@ -219,7 +219,7 @@
      *
      * @param provider an instance of the provider.
      *
-     * @return the new <code>SSLContext</code> object.
+     * @return the new {@code SSLContext} object.
      *
      * @throws NoSuchAlgorithmException if a SSLContextSpi
      *          implementation for the specified protocol is not available
@@ -239,22 +239,22 @@
     }
 
     /**
-     * Returns the protocol name of this <code>SSLContext</code> object.
+     * Returns the protocol name of this {@code SSLContext} object.
      *
      * <p>This is the same name that was specified in one of the
-     * <code>getInstance</code> calls that created this
-     * <code>SSLContext</code> object.
+     * {@code getInstance} calls that created this
+     * {@code SSLContext} object.
      *
-     * @return the protocol name of this <code>SSLContext</code> object.
+     * @return the protocol name of this {@code SSLContext} object.
      */
     public final String getProtocol() {
         return this.protocol;
     }
 
     /**
-     * Returns the provider of this <code>SSLContext</code> object.
+     * Returns the provider of this {@code SSLContext} object.
      *
-     * @return the provider of this <code>SSLContext</code> object
+     * @return the provider of this {@code SSLContext} object
      */
     public final Provider getProvider() {
         return this.provider;
@@ -283,31 +283,35 @@
     }
 
     /**
-     * Returns a <code>SocketFactory</code> object for this
+     * Returns a {@code SocketFactory} object for this
      * context.
      *
-     * @return the <code>SocketFactory</code> object
+     * @return the {@code SocketFactory} object
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
      * @throws IllegalStateException if the SSLContextImpl requires
-     *          initialization and the <code>init()</code> has not been called
+     *         initialization and the {@code init()} has not been called
      */
     public final SSLSocketFactory getSocketFactory() {
         return contextSpi.engineGetSocketFactory();
     }
 
     /**
-     * Returns a <code>ServerSocketFactory</code> object for
+     * Returns a {@code ServerSocketFactory} object for
      * this context.
      *
-     * @return the <code>ServerSocketFactory</code> object
+     * @return the {@code ServerSocketFactory} object
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
      * @throws IllegalStateException if the SSLContextImpl requires
-     *          initialization and the <code>init()</code> has not been called
+     *         initialization and the {@code init()} has not been called
      */
     public final SSLServerSocketFactory getServerSocketFactory() {
         return contextSpi.engineGetServerSocketFactory();
     }
 
     /**
-     * Creates a new <code>SSLEngine</code> using this context.
+     * Creates a new {@code SSLEngine} using this context.
      * <P>
      * Applications using this factory method are providing no hints
      * for an internal session reuse strategy. If hints are desired,
@@ -317,11 +321,11 @@
      * Some cipher suites (such as Kerberos) require remote hostname
      * information, in which case this factory method should not be used.
      *
-     * @return  the <code>SSLEngine</code> object
+     * @return  the {@code SSLEngine} object
      * @throws  UnsupportedOperationException if the underlying provider
      *          does not implement the operation.
      * @throws  IllegalStateException if the SSLContextImpl requires
-     *          initialization and the <code>init()</code> has not been called
+     *          initialization and the {@code init()} has not been called
      * @since   1.5
      */
     public final SSLEngine createSSLEngine() {
@@ -338,7 +342,7 @@
     }
 
     /**
-     * Creates a new <code>SSLEngine</code> using this context using
+     * Creates a new {@code SSLEngine} using this context using
      * advisory peer information.
      * <P>
      * Applications using this factory method are providing hints
@@ -349,11 +353,11 @@
      *
      * @param   peerHost the non-authoritative name of the host
      * @param   peerPort the non-authoritative port
-     * @return  the new <code>SSLEngine</code> object
+     * @return  the new {@code SSLEngine} object
      * @throws  UnsupportedOperationException if the underlying provider
      *          does not implement the operation.
      * @throws  IllegalStateException if the SSLContextImpl requires
-     *          initialization and the <code>init()</code> has not been called
+     *          initialization and the {@code init()} has not been called
      * @since   1.5
      */
     public final SSLEngine createSSLEngine(String peerHost, int peerPort) {
--- a/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
@@ -29,7 +29,7 @@
 
 /**
  * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
- * for the <code>SSLContext</code> class.
+ * for the {@code SSLContext} class.
  *
  * <p> All the abstract methods in this class must be implemented by each
  * cryptographic service provider who wishes to supply the implementation
@@ -52,31 +52,35 @@
         SecureRandom sr) throws KeyManagementException;
 
     /**
-     * Returns a <code>SocketFactory</code> object for this
+     * Returns a {@code SocketFactory} object for this
      * context.
      *
-     * @return the <code>SocketFactory</code> object
+     * @return the {@code SocketFactory} object
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
      * @throws IllegalStateException if the SSLContextImpl requires
-     *         initialization and the <code>engineInit()</code>
+     *         initialization and the {@code engineInit()}
      *         has not been called
      * @see javax.net.ssl.SSLContext#getSocketFactory()
      */
     protected abstract SSLSocketFactory engineGetSocketFactory();
 
     /**
-     * Returns a <code>ServerSocketFactory</code> object for
+     * Returns a {@code ServerSocketFactory} object for
      * this context.
      *
-     * @return the <code>ServerSocketFactory</code> object
+     * @return the {@code ServerSocketFactory} object
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
      * @throws IllegalStateException if the SSLContextImpl requires
-     *         initialization and the <code>engineInit()</code>
+     *         initialization and the {@code engineInit()}
      *         has not been called
      * @see javax.net.ssl.SSLContext#getServerSocketFactory()
      */
     protected abstract SSLServerSocketFactory engineGetServerSocketFactory();
 
     /**
-     * Creates a new <code>SSLEngine</code> using this context.
+     * Creates a new {@code SSLEngine} using this context.
      * <P>
      * Applications using this factory method are providing no hints
      * for an internal session reuse strategy. If hints are desired,
@@ -86,9 +90,9 @@
      * Some cipher suites (such as Kerberos) require remote hostname
      * information, in which case this factory method should not be used.
      *
-     * @return  the <code>SSLEngine</code> Object
+     * @return  the {@code SSLEngine} Object
      * @throws IllegalStateException if the SSLContextImpl requires
-     *         initialization and the <code>engineInit()</code>
+     *         initialization and the {@code engineInit()}
      *         has not been called
      *
      * @see     SSLContext#createSSLEngine()
@@ -98,7 +102,7 @@
     protected abstract SSLEngine engineCreateSSLEngine();
 
     /**
-     * Creates a <code>SSLEngine</code> using this context.
+     * Creates a {@code SSLEngine} using this context.
      * <P>
      * Applications using this factory method are providing hints
      * for an internal session reuse strategy.
@@ -108,9 +112,9 @@
      *
      * @param host the non-authoritative name of the host
      * @param port the non-authoritative port
-     * @return  the <code>SSLEngine</code> Object
+     * @return  the {@code SSLEngine} Object
      * @throws IllegalStateException if the SSLContextImpl requires
-     *         initialization and the <code>engineInit()</code>
+     *         initialization and the {@code engineInit()}
      *         has not been called
      *
      * @see     SSLContext#createSSLEngine(String, int)
@@ -120,19 +124,19 @@
     protected abstract SSLEngine engineCreateSSLEngine(String host, int port);
 
     /**
-     * Returns a server <code>SSLSessionContext</code> object for
+     * Returns a server {@code SSLSessionContext} object for
      * this context.
      *
-     * @return the <code>SSLSessionContext</code> object
+     * @return the {@code SSLSessionContext} object
      * @see javax.net.ssl.SSLContext#getServerSessionContext()
      */
     protected abstract SSLSessionContext engineGetServerSessionContext();
 
     /**
-     * Returns a client <code>SSLSessionContext</code> object for
+     * Returns a client {@code SSLSessionContext} object for
      * this context.
      *
-     * @return the <code>SSLSessionContext</code> object
+     * @return the {@code SSLSessionContext} object
      * @see javax.net.ssl.SSLContext#getClientSessionContext()
      */
     protected abstract SSLSessionContext engineGetClientSessionContext();
--- a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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,15 +37,15 @@
  * <P>
  * The secure communications modes include: <UL>
  *
- *      <LI> <em>Integrity Protection</em>.  SSL/TLS protects against
+ *      <LI> <em>Integrity Protection</em>.  SSL/TLS/DTLS protects against
  *      modification of messages by an active wiretapper.
  *
- *      <LI> <em>Authentication</em>.  In most modes, SSL/TLS provides
+ *      <LI> <em>Authentication</em>.  In most modes, SSL/TLS/DTLS provides
  *      peer authentication.  Servers are usually authenticated, and
  *      clients may be authenticated as requested by servers.
  *
  *      <LI> <em>Confidentiality (Privacy Protection)</em>.  In most
- *      modes, SSL/TLS encrypts data being sent between client and
+ *      modes, SSL/TLS/DTLS encrypts data being sent between client and
  *      server.  This protects the confidentiality of data, so that
  *      passive wiretappers won't see sensitive data such as financial
  *      information or personal information of many kinds.
@@ -65,19 +65,19 @@
  * handshaking has completed, you can access session attributes by
  * using the {@link #getSession()} method.
  * <P>
- * The <code>SSLSocket</code> class provides much of the same security
+ * The {@code SSLSocket} class provides much of the same security
  * functionality, but all of the inbound and outbound data is
  * automatically transported using the underlying {@link
  * java.net.Socket Socket}, which by design uses a blocking model.
  * While this is appropriate for many applications, this model does not
  * provide the scalability required by large servers.
  * <P>
- * The primary distinction of an <code>SSLEngine</code> is that it
+ * The primary distinction of an {@code SSLEngine} is that it
  * operates on inbound and outbound byte streams, independent of the
  * transport mechanism.  It is the responsibility of the
- * <code>SSLEngine</code> user to arrange for reliable I/O transport to
- * the peer.  By separating the SSL/TLS abstraction from the I/O
- * transport mechanism, the <code>SSLEngine</code> can be used for a
+ * {@code SSLEngine} user to arrange for reliable I/O transport to
+ * the peer.  By separating the SSL/TLS/DTLS abstraction from the I/O
+ * transport mechanism, the {@code SSLEngine} can be used for a
  * wide variety of I/O types, such as {@link
  * java.nio.channels.spi.AbstractSelectableChannel#configureBlocking(boolean)
  * non-blocking I/O (polling)}, {@link java.nio.channels.Selector
@@ -87,7 +87,7 @@
  * HREF="http://www.jcp.org/en/jsr/detail?id=203"> future asynchronous
  * I/O models </A>, and so on.
  * <P>
- * At a high level, the <code>SSLEngine</code> appears thus:
+ * At a high level, the {@code SSLEngine} appears thus:
  *
  * <pre>
  *                   app data
@@ -115,18 +115,18 @@
  * mechanism.  Inbound data is data which has been received from the
  * peer, and outbound data is destined for the peer.
  * <P>
- * (In the context of an <code>SSLEngine</code>, the term "handshake
+ * (In the context of an {@code SSLEngine}, the term "handshake
  * data" is taken to mean any data exchanged to establish and control a
- * secure connection.  Handshake data includes the SSL/TLS messages
+ * secure connection.  Handshake data includes the SSL/TLS/DTLS messages
  * "alert", "change_cipher_spec," and "handshake.")
  * <P>
- * There are five distinct phases to an <code>SSLEngine</code>.
+ * There are five distinct phases to an {@code SSLEngine}.
  *
  * <OL>
- *     <li> Creation - The <code>SSLEngine</code> has been created and
+ *     <li> Creation - The {@code SSLEngine} has been created and
  *     initialized, but has not yet been used.  During this phase, an
- *     application may set any <code>SSLEngine</code>-specific settings
- *     (enabled cipher suites, whether the <code>SSLEngine</code> should
+ *     application may set any {@code SSLEngine}-specific settings
+ *     (enabled cipher suites, whether the {@code SSLEngine} should
  *     handshake in client or server mode, and so on).  Once
  *     handshaking has begun, though, any new settings (except
  *     client/server mode, see below) will be used for
@@ -139,7 +139,7 @@
  *
  *     <li> Application Data - Once the communication parameters have
  *     been established and the handshake is complete, application data
- *     may flow through the <code>SSLEngine</code>.  Outbound
+ *     may flow through the {@code SSLEngine}.  Outbound
  *     application messages are encrypted and integrity protected,
  *     and inbound messages reverse the process.
  *
@@ -147,50 +147,50 @@
  *     the session at any time during the Application Data phase.  New
  *     handshaking data can be intermixed among the application data.
  *     Before starting the rehandshake phase, the application may
- *     reset the SSL/TLS communication parameters such as the list of
+ *     reset the SSL/TLS/DTLS communication parameters such as the list of
  *     enabled ciphersuites and whether to use client authentication,
  *     but can not change between client/server modes.  As before, once
- *     handshaking has begun, any new <code>SSLEngine</code>
+ *     handshaking has begun, any new {@code SSLEngine}
  *     configuration settings will not be used until the next
  *     handshake.
  *
  *     <li>  Closure - When the connection is no longer needed, the
- *     application should close the <code>SSLEngine</code> and should
+ *     application should close the {@code SSLEngine} and should
  *     send/receive any remaining messages to the peer before
  *     closing the underlying transport mechanism.  Once an engine is
- *     closed, it is not reusable:  a new <code>SSLEngine</code> must
+ *     closed, it is not reusable:  a new {@code SSLEngine} must
  *     be created.
  * </OL>
- * An <code>SSLEngine</code> is created by calling {@link
+ * An {@code SSLEngine} is created by calling {@link
  * SSLContext#createSSLEngine()} from an initialized
- * <code>SSLContext</code>.  Any configuration
+ * {@code SSLContext}.  Any configuration
  * parameters should be set before making the first call to
- * <code>wrap()</code>, <code>unwrap()</code>, or
- * <code>beginHandshake()</code>.  These methods all trigger the
+ * {@code wrap()}, {@code unwrap()}, or
+ * {@code beginHandshake()}.  These methods all trigger the
  * initial handshake.
  * <P>
  * Data moves through the engine by calling {@link #wrap(ByteBuffer,
  * ByteBuffer) wrap()} or {@link #unwrap(ByteBuffer, ByteBuffer)
  * unwrap()} on outbound or inbound data, respectively.  Depending on
- * the state of the <code>SSLEngine</code>, a <code>wrap()</code> call
+ * the state of the {@code SSLEngine}, a {@code wrap()} call
  * may consume application data from the source buffer and may produce
  * network data in the destination buffer.  The outbound data
  * may contain application and/or handshake data.  A call to
- * <code>unwrap()</code> will examine the source buffer and may
+ * {@code unwrap()} will examine the source buffer and may
  * advance the handshake if the data is handshaking information, or
  * may place application data in the destination buffer if the data
- * is application.  The state of the underlying SSL/TLS algorithm
+ * is application.  The state of the underlying SSL/TLS/DTLS algorithm
  * will determine when data is consumed and produced.
  * <P>
- * Calls to <code>wrap()</code> and <code>unwrap()</code> return an
- * <code>SSLEngineResult</code> which indicates the status of the
+ * Calls to {@code wrap()} and {@code unwrap()} return an
+ * {@code SSLEngineResult} which indicates the status of the
  * operation, and (optionally) how to interact with the engine to make
  * progress.
  * <P>
- * The <code>SSLEngine</code> produces/consumes complete SSL/TLS
+ * The {@code SSLEngine} produces/consumes complete SSL/TLS/DTLS
  * packets only, and does not store application data internally between
- * calls to <code>wrap()/unwrap()</code>.  Thus input and output
- * <code>ByteBuffer</code>s must be sized appropriately to hold the
+ * calls to {@code wrap()/unwrap()}.  Thus input and output
+ * {@code ByteBuffer}s must be sized appropriately to hold the
  * maximum record that can be produced.  Calls to {@link
  * SSLSession#getPacketBufferSize()} and {@link
  * SSLSession#getApplicationBufferSize()} should be used to determine
@@ -200,12 +200,12 @@
  * must determine (via {@link SSLEngineResult}) and correct the
  * problem, and then try the call again.
  * <P>
- * For example, <code>unwrap()</code> will return a {@link
+ * For example, {@code unwrap()} will return a {@link
  * SSLEngineResult.Status#BUFFER_OVERFLOW} result if the engine
  * determines that there is not enough destination buffer space available.
  * Applications should call {@link SSLSession#getApplicationBufferSize()}
  * and compare that value with the space available in the destination buffer,
- * enlarging the buffer if necessary.  Similarly, if <code>unwrap()</code>
+ * enlarging the buffer if necessary.  Similarly, if {@code unwrap()}
  * were to return a {@link SSLEngineResult.Status#BUFFER_UNDERFLOW}, the
  * application should call {@link SSLSession#getPacketBufferSize()} to ensure
  * that the source buffer has enough room to hold a record (enlarging if
@@ -241,8 +241,8 @@
  * }</pre>
  *
  * <P>
- * Unlike <code>SSLSocket</code>, all methods of SSLEngine are
- * non-blocking.  <code>SSLEngine</code> implementations may
+ * Unlike {@code SSLSocket}, all methods of SSLEngine are
+ * non-blocking.  {@code SSLEngine} implementations may
  * require the results of tasks that may take an extended period of
  * time to complete, or may even block.  For example, a TrustManager
  * may need to connect to a remote certificate validation service,
@@ -252,8 +252,8 @@
  * seemingly blocking.
  * <P>
  * For any operation which may potentially block, the
- * <code>SSLEngine</code> will create a {@link java.lang.Runnable}
- * delegated task.  When <code>SSLEngineResult</code> indicates that a
+ * {@code SSLEngine} will create a {@link java.lang.Runnable}
+ * delegated task.  When {@code SSLEngineResult} indicates that a
  * delegated task result is needed, the application must call {@link
  * #getDelegatedTask()} to obtain an outstanding delegated task and
  * call its {@link java.lang.Runnable#run() run()} method (possibly using
@@ -262,16 +262,16 @@
  * exist, and try the original operation again.
  * <P>
  * At the end of a communication session, applications should properly
- * close the SSL/TLS link.  The SSL/TLS protocols have closure handshake
- * messages, and these messages should be communicated to the peer
- * before releasing the <code>SSLEngine</code> and closing the
+ * close the SSL/TLS/DTLS link.  The SSL/TLS/DTLS protocols have closure
+ * handshake messages, and these messages should be communicated to the
+ * peer before releasing the {@code SSLEngine} and closing the
  * underlying transport mechanism.  A close can be initiated by one of:
  * an SSLException, an inbound closure handshake message, or one of the
  * close methods.  In all cases, closure handshake messages are
- * generated by the engine, and <code>wrap()</code> should be repeatedly
- * called until the resulting <code>SSLEngineResult</code>'s status
+ * generated by the engine, and {@code wrap()} should be repeatedly
+ * called until the resulting {@code SSLEngineResult}'s status
  * returns "CLOSED", or {@link #isOutboundDone()} returns true.  All
- * data obtained from the <code>wrap()</code> method should be sent to the
+ * data obtained from the {@code wrap()} method should be sent to the
  * peer.
  * <P>
  * {@link #closeOutbound()} is used to signal the engine that the
@@ -279,12 +279,12 @@
  * <P>
  * A peer will signal its intent to close by sending its own closure
  * handshake message.  After this message has been received and
- * processed by the local <code>SSLEngine</code>'s <code>unwrap()</code>
+ * processed by the local {@code SSLEngine}'s {@code unwrap()}
  * call, the application can detect the close by calling
- * <code>unwrap()</code> and looking for a <code>SSLEngineResult</code>
+ * {@code unwrap()} and looking for a {@code SSLEngineResult}
  * with status "CLOSED", or if {@link #isInboundDone()} returns true.
  * If for some reason the peer closes the communication link without
- * sending the proper SSL/TLS closure message, the application can
+ * sending the proper SSL/TLS/DTLS closure message, the application can
  * detect the end-of-stream and can signal the engine via {@link
  * #closeInbound()} that there will no more inbound messages to
  * process.  Some applications might choose to require orderly shutdown
@@ -315,16 +315,16 @@
  * and/or non-private (unencrypted) communications will such a
  * cipher suite be selected.
  * <P>
- * Each SSL/TLS connection must have one client and one server, thus
+ * Each SSL/TLS/DTLS connection must have one client and one server, thus
  * each endpoint must decide which role to assume.  This choice determines
  * who begins the handshaking process as well as which type of messages
  * should be sent by each party.  The method {@link
  * #setUseClientMode(boolean)} configures the mode.  Once the initial
- * handshaking has started, an <code>SSLEngine</code> can not switch
+ * handshaking has started, an {@code SSLEngine} can not switch
  * between client and server modes, even when performing renegotiations.
  * <P>
  * Applications might choose to process delegated tasks in different
- * threads.  When an <code>SSLEngine</code>
+ * threads.  When an {@code SSLEngine}
  * is created, the current {@link java.security.AccessControlContext}
  * is saved.  All future delegated tasks will be processed using this
  * context:  that is, all access control decisions will be made using the
@@ -336,10 +336,10 @@
  * There are two concurrency issues to be aware of:
  *
  * <OL>
- *      <li>The <code>wrap()</code> and <code>unwrap()</code> methods
+ *      <li>The {@code wrap()} and {@code unwrap()} methods
  *      may execute concurrently of each other.
  *
- *      <li> The SSL/TLS protocols employ ordered packets.
+ *      <li> The SSL/TLS/DTLS protocols employ ordered packets.
  *      Applications must take care to ensure that generated packets
  *      are delivered in sequence.  If packets arrive
  *      out-of-order, unexpected or fatal results may occur.
@@ -354,7 +354,7 @@
  *      </pre>
  *
  *      As a corollary, two threads must not attempt to call the same method
- *      (either <code>wrap()</code> or <code>unwrap()</code>) concurrently,
+ *      (either {@code wrap()} or {@code unwrap()}) concurrently,
  *      because there is no way to guarantee the eventual packet ordering.
  * </OL>
  *
@@ -374,7 +374,7 @@
     private int peerPort = -1;
 
     /**
-     * Constructor for an <code>SSLEngine</code> providing no hints
+     * Constructor for an {@code SSLEngine} providing no hints
      * for an internal session reuse strategy.
      *
      * @see     SSLContext#createSSLEngine()
@@ -384,10 +384,10 @@
     }
 
     /**
-     * Constructor for an <code>SSLEngine</code>.
+     * Constructor for an {@code SSLEngine}.
      * <P>
-     * <code>SSLEngine</code> implementations may use the
-     * <code>peerHost</code> and <code>peerPort</code> parameters as hints
+     * {@code SSLEngine} implementations may use the
+     * {@code peerHost} and {@code peerPort} parameters as hints
      * for their internal session reuse strategy.
      * <P>
      * Some cipher suites (such as Kerberos) require remote hostname
@@ -395,7 +395,7 @@
      * constructor to use Kerberos.
      * <P>
      * The parameters are not authenticated by the
-     * <code>SSLEngine</code>.
+     * {@code SSLEngine}.
      *
      * @param   peerHost the name of the peer host
      * @param   peerPort the port number of the peer
@@ -435,7 +435,7 @@
 
     /**
      * Attempts to encode a buffer of plaintext application data into
-     * SSL/TLS network data.
+     * SSL/TLS/DTLS network data.
      * <P>
      * An invocation of this method behaves in exactly the same manner
      * as the invocation:
@@ -445,20 +445,20 @@
      * </pre></blockquote>
      *
      * @param   src
-     *          a <code>ByteBuffer</code> containing outbound application data
+     *          a {@code ByteBuffer} containing outbound application data
      * @param   dst
-     *          a <code>ByteBuffer</code> to hold outbound network data
-     * @return  an <code>SSLEngineResult</code> describing the result
+     *          a {@code ByteBuffer} to hold outbound network data
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  ReadOnlyBufferException
-     *          if the <code>dst</code> buffer is read-only.
+     *          if the {@code dst} buffer is read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>src</code> or <code>dst</code>
+     *          if either {@code src} or {@code dst}
      *          is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
@@ -471,7 +471,7 @@
 
     /**
      * Attempts to encode plaintext bytes from a sequence of data
-     * buffers into SSL/TLS network data.
+     * buffers into SSL/TLS/DTLS network data.
      * <P>
      * An invocation of this method behaves in exactly the same manner
      * as the invocation:
@@ -481,22 +481,22 @@
      * </pre></blockquote>
      *
      * @param   srcs
-     *          an array of <code>ByteBuffers</code> containing the
+     *          an array of {@code ByteBuffers} containing the
      *          outbound application data
      * @param   dst
-     *          a <code>ByteBuffer</code> to hold outbound network data
-     * @return  an <code>SSLEngineResult</code> describing the result
+     *          a {@code ByteBuffer} to hold outbound network data
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  ReadOnlyBufferException
-     *          if the <code>dst</code> buffer is read-only.
+     *          if the {@code dst} buffer is read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>srcs</code> or <code>dst</code>
-     *          is null, or if any element in <code>srcs</code> is null.
+     *          if either {@code srcs} or {@code dst}
+     *          is null, or if any element in {@code srcs} is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
      * @see     #wrap(ByteBuffer [], int, int, ByteBuffer)
@@ -512,7 +512,7 @@
 
     /**
      * Attempts to encode plaintext bytes from a subsequence of data
-     * buffers into SSL/TLS network data.  This <i>"gathering"</i>
+     * buffers into SSL/TLS/DTLS network data.  This <i>"gathering"</i>
      * operation encodes, in a single invocation, a sequence of bytes
      * from one or more of a given sequence of buffers.  Gathering
      * wraps are often useful when implementing network protocols or
@@ -535,49 +535,49 @@
      * it was generated.  The application must properly synchronize
      * multiple calls to this method.
      * <P>
-     * If this <code>SSLEngine</code> has not yet started its initial
+     * If this {@code SSLEngine} has not yet started its initial
      * handshake, this method will automatically start the handshake.
      * <P>
-     * This method will attempt to produce SSL/TLS records, and will
+     * This method will attempt to produce SSL/TLS/DTLS records, and will
      * consume as much source data as possible, but will never consume
      * more than the sum of the bytes remaining in each buffer.  Each
-     * <code>ByteBuffer</code>'s position is updated to reflect the
+     * {@code ByteBuffer}'s position is updated to reflect the
      * amount of data consumed or produced.  The limits remain the
      * same.
      * <P>
-     * The underlying memory used by the <code>srcs</code> and
-     * <code>dst ByteBuffer</code>s must not be the same.
+     * The underlying memory used by the {@code srcs} and
+     * {@code dst ByteBuffer}s must not be the same.
      * <P>
      * See the class description for more information on engine closure.
      *
      * @param   srcs
-     *          an array of <code>ByteBuffers</code> containing the
+     *          an array of {@code ByteBuffers} containing the
      *          outbound application data
      * @param   offset
      *          The offset within the buffer array of the first buffer from
      *          which bytes are to be retrieved; it must be non-negative
-     *          and no larger than <code>srcs.length</code>
+     *          and no larger than {@code srcs.length}
      * @param   length
      *          The maximum number of buffers to be accessed; it must be
      *          non-negative and no larger than
-     *          <code>srcs.length</code>&nbsp;-&nbsp;<code>offset</code>
+     *          {@code srcs.length}&nbsp;-&nbsp;{@code offset}
      * @param   dst
-     *          a <code>ByteBuffer</code> to hold outbound network data
-     * @return  an <code>SSLEngineResult</code> describing the result
+     *          a {@code ByteBuffer} to hold outbound network data
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  IndexOutOfBoundsException
-     *          if the preconditions on the <code>offset</code> and
-     *          <code>length</code> parameters do not hold.
+     *          if the preconditions on the {@code offset} and
+     *          {@code length} parameters do not hold.
      * @throws  ReadOnlyBufferException
-     *          if the <code>dst</code> buffer is read-only.
+     *          if the {@code dst} buffer is read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>srcs</code> or <code>dst</code>
-     *          is null, or if any element in the <code>srcs</code>
+     *          if either {@code srcs} or {@code dst}
+     *          is null, or if any element in the {@code srcs}
      *          subsequence specified is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
@@ -589,7 +589,7 @@
             int length, ByteBuffer dst) throws SSLException;
 
     /**
-     * Attempts to decode SSL/TLS network data into a plaintext
+     * Attempts to decode SSL/TLS/DTLS network data into a plaintext
      * application data buffer.
      * <P>
      * An invocation of this method behaves in exactly the same manner
@@ -600,20 +600,20 @@
      * </pre></blockquote>
      *
      * @param   src
-     *          a <code>ByteBuffer</code> containing inbound network data.
+     *          a {@code ByteBuffer} containing inbound network data.
      * @param   dst
-     *          a <code>ByteBuffer</code> to hold inbound application data.
-     * @return  an <code>SSLEngineResult</code> describing the result
+     *          a {@code ByteBuffer} to hold inbound application data.
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  ReadOnlyBufferException
-     *          if the <code>dst</code> buffer is read-only.
+     *          if the {@code dst} buffer is read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>src</code> or <code>dst</code>
+     *          if either {@code src} or {@code dst}
      *          is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
@@ -625,7 +625,7 @@
     }
 
     /**
-     * Attempts to decode SSL/TLS network data into a sequence of plaintext
+     * Attempts to decode SSL/TLS/DTLS network data into a sequence of plaintext
      * application data buffers.
      * <P>
      * An invocation of this method behaves in exactly the same manner
@@ -636,22 +636,22 @@
      * </pre></blockquote>
      *
      * @param   src
-     *          a <code>ByteBuffer</code> containing inbound network data.
+     *          a {@code ByteBuffer} containing inbound network data.
      * @param   dsts
-     *          an array of <code>ByteBuffer</code>s to hold inbound
+     *          an array of {@code ByteBuffer}s to hold inbound
      *          application data.
-     * @return  an <code>SSLEngineResult</code> describing the result
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  ReadOnlyBufferException
-     *          if any of the <code>dst</code> buffers are read-only.
+     *          if any of the {@code dst} buffers are read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>src</code> or <code>dsts</code>
-     *          is null, or if any element in <code>dsts</code> is null.
+     *          if either {@code src} or {@code dsts}
+     *          is null, or if any element in {@code dsts} is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
      * @see     #unwrap(ByteBuffer, ByteBuffer [], int, int)
@@ -665,7 +665,7 @@
     }
 
     /**
-     * Attempts to decode SSL/TLS network data into a subsequence of
+     * Attempts to decode SSL/TLS/DTLS network data into a subsequence of
      * plaintext application data buffers.  This <i>"scattering"</i>
      * operation decodes, in a single invocation, a sequence of bytes
      * into one or more of a given sequence of buffers.  Scattering
@@ -688,55 +688,55 @@
      * order it was received.  The application must properly synchronize
      * multiple calls to this method.
      * <P>
-     * If this <code>SSLEngine</code> has not yet started its initial
+     * If this {@code SSLEngine} has not yet started its initial
      * handshake, this method will automatically start the handshake.
      * <P>
-     * This method will attempt to consume one complete SSL/TLS network
+     * This method will attempt to consume one complete SSL/TLS/DTLS network
      * packet, but will never consume more than the sum of the bytes
-     * remaining in the buffers.  Each <code>ByteBuffer</code>'s
+     * remaining in the buffers.  Each {@code ByteBuffer}'s
      * position is updated to reflect the amount of data consumed or
      * produced.  The limits remain the same.
      * <P>
-     * The underlying memory used by the <code>src</code> and
-     * <code>dsts ByteBuffer</code>s must not be the same.
+     * The underlying memory used by the {@code src} and
+     * {@code dsts ByteBuffer}s must not be the same.
      * <P>
      * The inbound network buffer may be modified as a result of this
      * call:  therefore if the network data packet is required for some
      * secondary purpose, the data should be duplicated before calling this
      * method.  Note:  the network data will not be useful to a second
      * SSLEngine, as each SSLEngine contains unique random state which
-     * influences the SSL/TLS messages.
+     * influences the SSL/TLS/DTLS messages.
      * <P>
      * See the class description for more information on engine closure.
      *
      * @param   src
-     *          a <code>ByteBuffer</code> containing inbound network data.
+     *          a {@code ByteBuffer} containing inbound network data.
      * @param   dsts
-     *          an array of <code>ByteBuffer</code>s to hold inbound
+     *          an array of {@code ByteBuffer}s to hold inbound
      *          application data.
      * @param   offset
      *          The offset within the buffer array of the first buffer from
      *          which bytes are to be transferred; it must be non-negative
-     *          and no larger than <code>dsts.length</code>.
+     *          and no larger than {@code dsts.length}.
      * @param   length
      *          The maximum number of buffers to be accessed; it must be
      *          non-negative and no larger than
-     *          <code>dsts.length</code>&nbsp;-&nbsp;<code>offset</code>.
-     * @return  an <code>SSLEngineResult</code> describing the result
+     *          {@code dsts.length}&nbsp;-&nbsp;{@code offset}.
+     * @return  an {@code SSLEngineResult} describing the result
      *          of this operation.
      * @throws  SSLException
      *          A problem was encountered while processing the
-     *          data that caused the <code>SSLEngine</code> to abort.
+     *          data that caused the {@code SSLEngine} to abort.
      *          See the class description for more information on
      *          engine closure.
      * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <code>offset</code> and
-     *          <code>length</code> parameters do not hold.
+     *          If the preconditions on the {@code offset} and
+     *          {@code length} parameters do not hold.
      * @throws  ReadOnlyBufferException
-     *          if any of the <code>dst</code> buffers are read-only.
+     *          if any of the {@code dst} buffers are read-only.
      * @throws  IllegalArgumentException
-     *          if either <code>src</code> or <code>dsts</code>
-     *          is null, or if any element in the <code>dsts</code>
+     *          if either {@code src} or {@code dsts}
+     *          is null, or if any element in the {@code dsts}
      *          subsequence specified is null.
      * @throws  IllegalStateException if the client/server mode
      *          has not yet been set.
@@ -749,19 +749,19 @@
 
 
     /**
-     * Returns a delegated <code>Runnable</code> task for
-     * this <code>SSLEngine</code>.
+     * Returns a delegated {@code Runnable} task for
+     * this {@code SSLEngine}.
      * <P>
-     * <code>SSLEngine</code> operations may require the results of
+     * {@code SSLEngine} operations may require the results of
      * operations that block, or may take an extended period of time to
      * complete.  This method is used to obtain an outstanding {@link
      * java.lang.Runnable} operation (task).  Each task must be assigned
      * a thread (possibly the current) to perform the {@link
      * java.lang.Runnable#run() run} operation.  Once the
-     * <code>run</code> method returns, the <code>Runnable</code> object
+     * {@code run} method returns, the {@code Runnable} object
      * is no longer needed and may be discarded.
      * <P>
-     * Delegated tasks run in the <code>AccessControlContext</code>
+     * Delegated tasks run in the {@code AccessControlContext}
      * in place when this object was created.
      * <P>
      * A call to this method will return each outstanding task
@@ -769,7 +769,7 @@
      * <P>
      * Multiple delegated tasks can be run in parallel.
      *
-     * @return  a delegated <code>Runnable</code> task, or null
+     * @return  a delegated {@code Runnable} task, or null
      *          if none are available.
      */
     public abstract Runnable getDelegatedTask();
@@ -777,7 +777,7 @@
 
     /**
      * Signals that no more inbound network data will be sent
-     * to this <code>SSLEngine</code>.
+     * to this {@code SSLEngine}.
      * <P>
      * If the application initiated the closing process by calling
      * {@link #closeOutbound()}, under some circumstances it is not
@@ -789,9 +789,9 @@
      * <P>
      * But if the application did not initiate the closure process, or
      * if the circumstances above do not apply, this method should be
-     * called whenever the end of the SSL/TLS data stream is reached.
+     * called whenever the end of the SSL/TLS/DTLS data stream is reached.
      * This ensures closure of the inbound side, and checks that the
-     * peer followed the SSL/TLS close procedure properly, thus
+     * peer followed the SSL/TLS/DTLS close procedure properly, thus
      * detecting possible truncation attacks.
      * <P>
      * This method is idempotent:  if the inbound side has already
@@ -801,7 +801,7 @@
      * called to flush any remaining handshake data.
      *
      * @throws  SSLException
-     *          if this engine has not received the proper SSL/TLS close
+     *          if this engine has not received the proper SSL/TLS/DTLS close
      *          notification message from the peer.
      *
      * @see     #isInboundDone()
@@ -814,7 +814,7 @@
      * Returns whether {@link #unwrap(ByteBuffer, ByteBuffer)} will
      * accept any more inbound data messages.
      *
-     * @return  true if the <code>SSLEngine</code> will not
+     * @return  true if the {@code SSLEngine} will not
      *          consume anymore network data (and by implication,
      *          will not produce any more application data.)
      * @see     #closeInbound()
@@ -824,7 +824,7 @@
 
     /**
      * Signals that no more outbound application data will be sent
-     * on this <code>SSLEngine</code>.
+     * on this {@code SSLEngine}.
      * <P>
      * This method is idempotent:  if the outbound side has already
      * been closed, this method does not do anything.
@@ -841,12 +841,12 @@
      * Returns whether {@link #wrap(ByteBuffer, ByteBuffer)} will
      * produce any more outbound data messages.
      * <P>
-     * Note that during the closure phase, a <code>SSLEngine</code> may
+     * Note that during the closure phase, a {@code SSLEngine} may
      * generate handshake closure data that must be sent to the peer.
-     * <code>wrap()</code> must be called to generate this data.  When
+     * {@code wrap()} must be called to generate this data.  When
      * this method returns true, no more outbound data will be created.
      *
-     * @return  true if the <code>SSLEngine</code> will not produce
+     * @return  true if the {@code SSLEngine} will not produce
      *          any more network data
      *
      * @see     #closeOutbound()
@@ -890,10 +890,10 @@
     /**
      * Sets the cipher suites enabled for use on this engine.
      * <P>
-     * Each cipher suite in the <code>suites</code> parameter must have
+     * Each cipher suite in the {@code suites} parameter must have
      * been listed by getSupportedCipherSuites(), or the method will
      * fail.  Following a successful call to this method, only suites
-     * listed in the <code>suites</code> parameter are enabled for use.
+     * listed in the {@code suites} parameter are enabled for use.
      * <P>
      * See {@link #getEnabledCipherSuites()} for more information
      * on why a specific cipher suite may never be used on a engine.
@@ -910,7 +910,7 @@
 
     /**
      * Returns the names of the protocols which could be enabled for use
-     * with this <code>SSLEngine</code>.
+     * with this {@code SSLEngine}.
      *
      * @return  an array of protocols supported
      */
@@ -919,7 +919,7 @@
 
     /**
      * Returns the names of the protocol versions which are currently
-     * enabled for use with this <code>SSLEngine</code>.
+     * enabled for use with this {@code SSLEngine}.
      *
      * @return  an array of protocols
      * @see     #setEnabledProtocols(String [])
@@ -932,7 +932,7 @@
      * <P>
      * The protocols must have been listed by getSupportedProtocols()
      * as being supported.  Following a successful call to this method,
-     * only protocols listed in the <code>protocols</code> parameter
+     * only protocols listed in the {@code protocols} parameter
      * are enabled for use.
      *
      * @param   protocols Names of all the protocols to enable.
@@ -945,8 +945,8 @@
 
 
     /**
-     * Returns the <code>SSLSession</code> in use in this
-     * <code>SSLEngine</code>.
+     * Returns the {@code SSLSession} in use in this
+     * {@code SSLEngine}.
      * <P>
      * These can be long lived, and frequently correspond to an entire
      * login session for some user.  The session specifies a particular
@@ -961,22 +961,22 @@
      * a session object which reports an invalid cipher suite of
      * "SSL_NULL_WITH_NULL_NULL".
      *
-     * @return  the <code>SSLSession</code> for this <code>SSLEngine</code>
+     * @return  the {@code SSLSession} for this {@code SSLEngine}
      * @see     SSLSession
      */
     public abstract SSLSession getSession();
 
 
     /**
-     * Returns the {@code SSLSession} being constructed during a SSL/TLS
+     * Returns the {@code SSLSession} being constructed during a SSL/TLS/DTLS
      * handshake.
      * <p>
-     * TLS protocols may negotiate parameters that are needed when using
+     * TLS/DTLS protocols may negotiate parameters that are needed when using
      * an instance of this class, but before the {@code SSLSession} has
      * been completely initialized and made available via {@code getSession}.
      * For example, the list of valid signature algorithms may restrict
      * the type of certificates that can used during TrustManager
-     * decisions, or the maximum TLS fragment packet sizes can be
+     * decisions, or the maximum TLS/DTLS fragment packet sizes can be
      * resized to better support the network environment.
      * <p>
      * This method provides early access to the {@code SSLSession} being
@@ -1012,26 +1012,26 @@
      * Initiates handshaking (initial or renegotiation) on this SSLEngine.
      * <P>
      * This method is not needed for the initial handshake, as the
-     * <code>wrap()</code> and <code>unwrap()</code> methods will
+     * {@code wrap()} and {@code unwrap()} methods will
      * implicitly call this method if handshaking has not already begun.
      * <P>
      * Note that the peer may also request a session renegotiation with
-     * this <code>SSLEngine</code> by sending the appropriate
+     * this {@code SSLEngine} by sending the appropriate
      * session renegotiate handshake message.
      * <P>
      * Unlike the {@link SSLSocket#startHandshake()
      * SSLSocket#startHandshake()} method, this method does not block
      * until handshaking is completed.
      * <P>
-     * To force a complete SSL/TLS session renegotiation, the current
+     * To force a complete SSL/TLS/DTLS session renegotiation, the current
      * session should be invalidated prior to calling this method.
      * <P>
      * Some protocols may not support multiple handshakes on an existing
-     * engine and may throw an <code>SSLException</code>.
+     * engine and may throw an {@code SSLException}.
      *
      * @throws  SSLException
      *          if a problem was encountered while signaling the
-     *          <code>SSLEngine</code> to begin a new handshake.
+     *          {@code SSLEngine} to begin a new handshake.
      *          See the class description for more information on
      *          engine closure.
      * @throws  IllegalStateException if the client/server mode
@@ -1042,9 +1042,9 @@
 
 
     /**
-     * Returns the current handshake status for this <code>SSLEngine</code>.
+     * Returns the current handshake status for this {@code SSLEngine}.
      *
-     * @return  the current <code>SSLEngineResult.HandshakeStatus</code>.
+     * @return  the current {@code SSLEngineResult.HandshakeStatus}.
      */
     public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus();
 
--- a/src/java.base/share/classes/javax/net/ssl/SSLEngineResult.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLEngineResult.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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
@@ -27,13 +27,13 @@
 
 /**
  * An encapsulation of the result state produced by
- * <code>SSLEngine</code> I/O calls.
+ * {@code SSLEngine} I/O calls.
  *
- * <p> A <code>SSLEngine</code> provides a means for establishing
- * secure communication sessions between two peers.  <code>SSLEngine</code>
+ * <p> A {@code SSLEngine} provides a means for establishing
+ * secure communication sessions between two peers.  {@code SSLEngine}
  * operations typically consume bytes from an input buffer and produce
  * bytes in an output buffer.  This class provides operational result
- * values describing the state of the <code>SSLEngine</code>, including
+ * values describing the state of the {@code SSLEngine}, including
  * indications of what operations are needed to finish an
  * ongoing handshake.  Lastly, it reports the number of bytes consumed
  * and produced as a result of this operation.
@@ -49,12 +49,12 @@
 public class SSLEngineResult {
 
     /**
-     * An <code>SSLEngineResult</code> enum describing the overall result
-     * of the <code>SSLEngine</code> operation.
+     * An {@code SSLEngineResult} enum describing the overall result
+     * of the {@code SSLEngine} operation.
      *
-     * The <code>Status</code> value does not reflect the
-     * state of a <code>SSLEngine</code> handshake currently
-     * in progress.  The <code>SSLEngineResult's HandshakeStatus</code>
+     * The {@code Status} value does not reflect the
+     * state of a {@code SSLEngine} handshake currently
+     * in progress.  The {@code SSLEngineResult's HandshakeStatus}
      * should be consulted for that information.
      *
      * @author Brad R. Wetmore
@@ -63,7 +63,7 @@
     public static enum Status {
 
         /**
-         * The <code>SSLEngine</code> was not able to unwrap the
+         * The {@code SSLEngine} was not able to unwrap the
          * incoming data because there were not enough source bytes
          * available to make a complete packet.
          *
@@ -73,7 +73,7 @@
         BUFFER_UNDERFLOW,
 
         /**
-         * The <code>SSLEngine</code> was not able to process the
+         * The {@code SSLEngine} was not able to process the
          * operation because there are not enough bytes available in the
          * destination buffer to hold the result.
          * <P>
@@ -85,22 +85,22 @@
         BUFFER_OVERFLOW,
 
         /**
-         * The <code>SSLEngine</code> completed the operation, and
+         * The {@code SSLEngine} completed the operation, and
          * is available to process similar calls.
          */
         OK,
 
         /**
          * The operation just closed this side of the
-         * <code>SSLEngine</code>, or the operation
+         * {@code SSLEngine}, or the operation
          * could not be completed because it was already closed.
          */
         CLOSED;
     }
 
     /**
-     * An <code>SSLEngineResult</code> enum describing the current
-     * handshaking state of this <code>SSLEngine</code>.
+     * An {@code SSLEngineResult} enum describing the current
+     * handshaking state of this {@code SSLEngine}.
      *
      * @author Brad R. Wetmore
      * @since 1.5
@@ -108,17 +108,17 @@
     public static enum HandshakeStatus {
 
         /**
-         * The <code>SSLEngine</code> is not currently handshaking.
+         * The {@code SSLEngine} is not currently handshaking.
          */
         NOT_HANDSHAKING,
 
         /**
-         * The <code>SSLEngine</code> has just finished handshaking.
+         * The {@code SSLEngine} has just finished handshaking.
          * <P>
          * This value is only generated by a call to
-         * <code>SSLEngine.wrap()/unwrap()</code> when that call
+         * {@code SSLEngine.wrap()/unwrap()} when that call
          * finishes a handshake.  It is never generated by
-         * <code>SSLEngine.getHandshakeStatus()</code>.
+         * {@code SSLEngine.getHandshakeStatus()}.
          *
          * @see SSLEngine#wrap(ByteBuffer, ByteBuffer)
          * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer)
@@ -127,7 +127,7 @@
         FINISHED,
 
         /**
-         * The <code>SSLEngine</code> needs the results of one (or more)
+         * The {@code SSLEngine} needs the results of one (or more)
          * delegated tasks before handshaking can continue.
          *
          * @see SSLEngine#getDelegatedTask()
@@ -135,8 +135,8 @@
         NEED_TASK,
 
         /**
-         * The <code>SSLEngine</code> must send data to the remote side
-         * before handshaking can continue, so <code>SSLEngine.wrap()</code>
+         * The {@code SSLEngine} must send data to the remote side
+         * before handshaking can continue, so {@code SSLEngine.wrap()}
          * should be called.
          *
          * @see SSLEngine#wrap(ByteBuffer, ByteBuffer)
@@ -144,10 +144,22 @@
         NEED_WRAP,
 
         /**
-         * The <code>SSLEngine</code> needs to receive data from the
+         * The {@code SSLEngine} needs to receive data from the
          * remote side before handshaking can continue.
          */
-        NEED_UNWRAP;
+        NEED_UNWRAP,
+
+        /**
+         * The {@code SSLEngine} needs to unwrap before handshaking can
+         * can continue.
+         * <P>
+         * This value is used to indicate that not-yet-interpreted data
+         * has been previously received from the remote side, and does
+         * not need to be received again.
+         *
+         * @since   1.9
+         */
+        NEED_UNWRAP_AGAIN;
     }
 
 
@@ -155,6 +167,7 @@
     private final HandshakeStatus handshakeStatus;
     private final int bytesConsumed;
     private final int bytesProduced;
+    private final long sequenceNumber;
 
     /**
      * Initializes a new instance of this class.
@@ -172,12 +185,44 @@
      *          the number of bytes placed into the destination ByteBuffer
      *
      * @throws  IllegalArgumentException
-     *          if the <code>status</code> or <code>handshakeStatus</code>
-     *          arguments are null, or if <code>bytesConsumed</code> or
-     *          <code>bytesProduced</code> is negative.
+     *          if the {@code status} or {@code handshakeStatus}
+     *          arguments are null, or if {@code bytesConsumed} or
+     *          {@code bytesProduced} is negative.
      */
     public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,
             int bytesConsumed, int bytesProduced) {
+        this(status, handshakeStatus, bytesConsumed, bytesProduced, -1);
+    }
+
+    /**
+     * Initializes a new instance of this class.
+     *
+     * @param   status
+     *          the return value of the operation.
+     *
+     * @param   handshakeStatus
+     *          the current handshaking status.
+     *
+     * @param   bytesConsumed
+     *          the number of bytes consumed from the source ByteBuffer
+     *
+     * @param   bytesProduced
+     *          the number of bytes placed into the destination ByteBuffer
+     *
+     * @param   sequenceNumber
+     *          the sequence number (unsigned long) of the produced or
+     *          consumed SSL/TLS/DTLS record, or ${@code -1L} if no record
+     *          produced or consumed
+     *
+     * @throws  IllegalArgumentException
+     *          if the {@code status} or {@code handshakeStatus}
+     *          arguments are null, or if {@code bytesConsumed} or
+     *          {@code bytesProduced} is negative
+     *
+     * @since   1.9
+     */
+    public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,
+            int bytesConsumed, int bytesProduced, long sequenceNumber) {
 
         if ((status == null) || (handshakeStatus == null) ||
                 (bytesConsumed < 0) || (bytesProduced < 0)) {
@@ -188,10 +233,11 @@
         this.handshakeStatus = handshakeStatus;
         this.bytesConsumed = bytesConsumed;
         this.bytesProduced = bytesProduced;
+        this.sequenceNumber = sequenceNumber;
     }
 
     /**
-     * Gets the return value of this <code>SSLEngine</code> operation.
+     * Gets the return value of this {@code SSLEngine} operation.
      *
      * @return  the return value
      */
@@ -200,7 +246,7 @@
     }
 
     /**
-     * Gets the handshake status of this <code>SSLEngine</code>
+     * Gets the handshake status of this {@code SSLEngine}
      * operation.
      *
      * @return  the handshake status
@@ -228,6 +274,41 @@
     }
 
     /**
+     * Returns the sequence number of the produced or consumed SSL/TLS/DTLS
+     * record (optional operation).
+     *
+     * @apiNote  Note that sequence number is an unsigned long and cannot
+     *           exceed {@code -1L}.  It is desired to use the unsigned
+     *           long comparing mode for comparison of unsigned long values
+     *           (see also {@link java.lang.Long#compareUnsigned(long, long)
+     *           Long.compareUnsigned()}).
+     *           <P>
+     *           For DTLS protocols, the first 16 bits of the sequence
+     *           number is a counter value (epoch) that is incremented on
+     *           every cipher state change.  The remaining 48 bits on the
+     *           right side of the sequence number represents the sequence
+     *           of the record, which is maintained separately for each epoch.
+     *
+     * @implNote It is recommended that providers should never allow the
+     *           sequence number incremented to {@code -1L}.  If the sequence
+     *           number is close to wrapping, renegotiate should be requested,
+     *           otherwise the connection should be closed immediately.
+     *           This should be carried on automatically by the underlying
+     *           implementation.
+     *
+     * @return  the sequence number of the produced or consumed SSL/TLS/DTLS
+     *          record; or ${@code -1L} if no record is produced or consumed,
+     *          or this operation is not supported by the underlying provider
+     *
+     * @see     java.lang.Long#compareUnsigned(long, long)
+     *
+     * @since   1.9
+     */
+    final public long sequenceNumber() {
+        return sequenceNumber;
+    }
+
+    /**
      * Returns a String representation of this object.
      */
     @Override
@@ -235,6 +316,8 @@
         return ("Status = " + status +
             " HandshakeStatus = " + handshakeStatus +
             "\nbytesConsumed = " + bytesConsumed +
-            " bytesProduced = " + bytesProduced);
+            " bytesProduced = " + bytesProduced +
+            (sequenceNumber == -1 ? "" :
+                " sequenceNumber = " + Long.toUnsignedString(sequenceNumber)));
     }
 }
--- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java	Thu Jun 11 00:51:11 2015 +0200
@@ -35,22 +35,22 @@
 import java.util.LinkedHashMap;
 
 /**
- * Encapsulates parameters for an SSL/TLS connection. The parameters
- * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
+ * Encapsulates parameters for an SSL/TLS/DTLS connection. The parameters
+ * are the list of ciphersuites to be accepted in an SSL/TLS/DTLS handshake,
  * the list of protocols to be allowed, the endpoint identification
- * algorithm during SSL/TLS handshaking, the Server Name Indication (SNI),
- * the algorithm constraints and whether SSL/TLS servers should request
- * or require client authentication, etc.
+ * algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
+ * the maximum network packet size, the algorithm constraints and whether
+ * SSL/TLS/DTLS servers should request or require client authentication, etc.
  * <p>
  * SSLParameters can be created via the constructors in this class.
- * Objects can also be obtained using the <code>getSSLParameters()</code>
+ * Objects can also be obtained using the {@code getSSLParameters()}
  * methods in
  * {@link SSLSocket#getSSLParameters SSLSocket} and
  * {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
  * {@link SSLEngine#getSSLParameters SSLEngine} or the
  * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
  * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
- * methods in <code>SSLContext</code>.
+ * methods in {@code SSLContext}.
  * <p>
  * SSLParameters can be applied to a connection via the methods
  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
@@ -74,14 +74,18 @@
     private Map<Integer, SNIServerName> sniNames = null;
     private Map<Integer, SNIMatcher> sniMatchers = null;
     private boolean preferLocalCipherSuites;
+    private boolean enableRetransmissions = true;
+    private int maximumPacketSize = 0;
 
     /**
      * Constructs SSLParameters.
      * <p>
      * The values of cipherSuites, protocols, cryptographic algorithm
      * constraints, endpoint identification algorithm, server names and
-     * server name matchers are set to <code>null</code>, useCipherSuitesOrder,
-     * wantClientAuth and needClientAuth are set to <code>false</code>.
+     * server name matchers are set to {@code null}; useCipherSuitesOrder,
+     * wantClientAuth and needClientAuth are set to {@code false};
+     * enableRetransmissions is set to {@code true}; maximum network packet
+     * size is set to {@code 0}.
      */
     public SSLParameters() {
         // empty
@@ -92,7 +96,7 @@
      * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
-     * <code>setCipherSuites(cipherSuites);</code>.
+     * {@code setCipherSuites(cipherSuites);}.
      *
      * @param cipherSuites the array of ciphersuites (or null)
      */
@@ -106,7 +110,7 @@
      * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
-     * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
+     * {@code setCipherSuites(cipherSuites); setProtocols(protocols);}.
      *
      * @param cipherSuites the array of ciphersuites (or null)
      * @param protocols the array of protocols (or null)
@@ -171,7 +175,7 @@
 
     /**
      * Sets whether client authentication should be requested. Calling
-     * this method clears the <code>needClientAuth</code> flag.
+     * this method clears the {@code needClientAuth} flag.
      *
      * @param wantClientAuth whether client authentication should be requested
      */
@@ -191,7 +195,7 @@
 
     /**
      * Sets whether client authentication should be required. Calling
-     * this method clears the <code>wantClientAuth</code> flag.
+     * this method clears the {@code wantClientAuth} flag.
      *
      * @param needClientAuth whether client authentication should be required
      */
@@ -218,9 +222,9 @@
      * Sets the cryptographic algorithm constraints, which will be used
      * in addition to any configured by the runtime environment.
      * <p>
-     * If the <code>constraints</code> parameter is non-null, every
+     * If the {@code constraints} parameter is non-null, every
      * cryptographic algorithm, key and algorithm parameters used in the
-     * SSL/TLS handshake must be permitted by the constraints.
+     * SSL/TLS/DTLS handshake must be permitted by the constraints.
      *
      * @param constraints the algorithm constraints (or null)
      *
@@ -249,9 +253,9 @@
     /**
      * Sets the endpoint identification algorithm.
      * <p>
-     * If the <code>algorithm</code> parameter is non-null or non-empty, the
+     * If the {@code algorithm} parameter is non-null or non-empty, the
      * endpoint identification/verification procedures must be handled during
-     * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
+     * SSL/TLS/DTLS handshaking.  This is to prevent man-in-the-middle attacks.
      *
      * @param algorithm The standard string name of the endpoint
      *     identification algorithm (or null).  See Appendix A in the <a href=
@@ -317,7 +321,7 @@
      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
      * operating in client mode.
      * <P>
-     * For SSL/TLS connections, the underlying SSL/TLS provider
+     * For SSL/TLS/DTLS connections, the underlying SSL/TLS/DTLS provider
      * may specify a default value for a certain server name type.  In
      * client mode, it is recommended that, by default, providers should
      * include the server name indication whenever the server can be located
@@ -440,7 +444,7 @@
      *
      * @param honorOrder whether local cipher suites order in
      *        {@code #getCipherSuites} should be honored during
-     *        SSL/TLS handshaking.
+     *        SSL/TLS/DTLS handshaking.
      *
      * @see #getUseCipherSuitesOrder()
      *
@@ -454,7 +458,7 @@
      * Returns whether the local cipher suites preference should be honored.
      *
      * @return whether local cipher suites order in {@code #getCipherSuites}
-     *         should be honored during SSL/TLS handshaking.
+     *         should be honored during SSL/TLS/DTLS handshaking.
      *
      * @see #setUseCipherSuitesOrder(boolean)
      *
@@ -463,5 +467,107 @@
     public final boolean getUseCipherSuitesOrder() {
         return preferLocalCipherSuites;
     }
+
+    /**
+     * Sets whether DTLS handshake retransmissions should be enabled.
+     *
+     * This method only applies to DTLS.
+     *
+     * @param   enableRetransmissions
+     *          {@code true} indicates that DTLS handshake retransmissions
+     *          should be enabled; {@code false} indicates that DTLS handshake
+     *          retransmissions should be disabled
+     *
+     * @see     #getEnableRetransmissions()
+     *
+     * @since 1.9
+     */
+    public void setEnableRetransmissions(boolean enableRetransmissions) {
+        this.enableRetransmissions = enableRetransmissions;
+    }
+
+    /**
+     * Returns whether DTLS handshake retransmissions should be enabled.
+     *
+     * This method only applies to DTLS.
+     *
+     * @return  true, if DTLS handshake retransmissions should be enabled
+     *
+     * @see     #setEnableRetransmissions(boolean)
+     *
+     * @since 1.9
+     */
+    public boolean getEnableRetransmissions() {
+        return enableRetransmissions;
+    }
+
+    /**
+     * Sets the maximum expected network packet size in bytes for
+     * SSL/TLS/DTLS records.
+     *
+     * @apiNote  It is recommended that if possible, the maximum packet size
+     *           should not be less than 256 bytes so that small handshake
+     *           messages, such as HelloVerifyRequests, are not fragmented.
+     *
+     * @implNote If the maximum packet size is too small to hold a minimal
+     *           record, an implementation may attempt to generate as minimal
+     *           records as possible.  However, this may cause a generated
+     *           packet to be larger than the maximum packet size.
+     *
+     * @param   maximumPacketSize
+     *          the maximum expected network packet size in bytes, or
+     *          {@code 0} to use the implicit size that is automatically
+     *          specified by the underlying implementation.
+     * @throws  IllegalArgumentException
+     *          if {@code maximumPacketSize} is negative.
+     *
+     * @see     #getMaximumPacketSize()
+     *
+     * @since 1.9
+     */
+    public void setMaximumPacketSize(int maximumPacketSize) {
+        if (maximumPacketSize < 0) {
+            throw new IllegalArgumentException(
+                "The maximum packet size cannot be negative");
+        }
+
+        this.maximumPacketSize = maximumPacketSize;
+    }
+
+    /**
+     * Returns the maximum expected network packet size in bytes for
+     * SSL/TLS/DTLS records.
+     *
+     * @apiNote  The implicit size may not be a fixed value, especially
+     *           for a DTLS protocols implementation.
+     *
+     * @implNote For SSL/TLS/DTLS connections, the underlying provider
+     *           should calculate and specify the implicit value of the
+     *           maximum expected network packet size if it is not
+     *           configured explicitly.  For any connection populated
+     *           object, this method should never return {@code 0} so
+     *           that applications can retrieve the actual implicit size
+     *           of the underlying implementation.
+     *           <P>
+     *           An implementation should attempt to comply with the maximum
+     *           packet size configuration.  However, if the maximum packet
+     *           size is too small to hold a minimal record, an implementation
+     *           may try to generate as minimal records as possible.  This
+     *           may cause a generated packet to be larger than the maximum
+     *           packet size.
+     *
+     * @return   the maximum expected network packet size, or {@code 0} if
+     *           use the implicit size that is automatically specified by
+     *           the underlying implementation and this object has not been
+     *           populated by any connection.
+     *
+     * @see      #setMaximumPacketSize(int)
+     *
+     * @since 1.9
+     */
+    public int getMaximumPacketSize() {
+        return maximumPacketSize;
+    }
+
 }
 
--- a/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Thu Jun 11 00:51:11 2015 +0200
@@ -35,7 +35,7 @@
  * also be replaced by a different session.  Sessions are created, or
  * rejoined, as part of the SSL handshaking protocol. Sessions may be
  * invalidated due to policies affecting security or resource usage,
- * or by an application explicitly calling <code>invalidate</code>.
+ * or by an application explicitly calling {@code invalidate}.
  * Session management policies are typically used to tune performance.
  *
  * <P> In addition to the standard session attributes, SSL sessions expose
@@ -82,8 +82,8 @@
      * security manager installed, the caller may require
      * permission to access it or a security exception may be thrown.
      * In a Java environment, the security manager's
-     * <code>checkPermission</code> method is called with a
-     * <code>SSLPermission("getSSLSessionContext")</code> permission.
+     * {@code checkPermission} method is called with a
+     * {@code SSLPermission("getSSLSessionContext")} permission.
      *
      * @throws SecurityException if the calling thread does not have
      *         permission to get SSL session context.
@@ -148,14 +148,14 @@
 
     /**
      *
-     * Binds the specified <code>value</code> object into the
+     * Binds the specified {@code value} object into the
      * session's application layer data
-     * with the given <code>name</code>.
+     * with the given {@code name}.
      * <P>
-     * Any existing binding using the same <code>name</code> is
-     * replaced.  If the new (or existing) <code>value</code> implements the
-     * <code>SSLSessionBindingListener</code> interface, the object
-     * represented by <code>value</code> is notified appropriately.
+     * Any existing binding using the same {@code name} is
+     * replaced.  If the new (or existing) {@code value} implements the
+     * {@code SSLSessionBindingListener} interface, the object
+     * represented by {@code value} is notified appropriately.
      * <p>
      * For security reasons, the same named values may not be
      * visible across different access control contexts.
@@ -187,7 +187,7 @@
      * Removes the object bound to the given name in the session's
      * application layer data.  Does nothing if there is no object
      * bound to the given name.  If the bound existing object
-     * implements the <code>SessionBindingListener</code> interface,
+     * implements the {@code SessionBindingListener} interface,
      * it is notified appropriately.
      * <p>
      * For security reasons, the same named values may not be
@@ -349,7 +349,7 @@
      * by this method.
      * <P>
      * This value is not authenticated and should not be relied upon.
-     * It is mainly used as a hint for <code>SSLSession</code> caching
+     * It is mainly used as a hint for {@code SSLSession} caching
      * strategies.
      *
      * @return  the host name of the peer host, or null if no information
@@ -364,7 +364,7 @@
      * the client, it is the server's port number.
      * <P>
      * This value is not authenticated and should not be relied upon.
-     * It is mainly used as a hint for <code>SSLSession</code> caching
+     * It is mainly used as a hint for {@code SSLSession} caching
      * strategies.
      *
      * @return  the port number of the peer host, or -1 if no information
@@ -375,14 +375,14 @@
     public int getPeerPort();
 
     /**
-     * Gets the current size of the largest SSL/TLS packet that is expected
-     * when using this session.
+     * Gets the current size of the largest SSL/TLS/DTLS packet that is
+     * expected when using this session.
      * <P>
-     * A <code>SSLEngine</code> using this session may generate SSL/TLS
+     * An {@code SSLEngine} using this session may generate SSL/TLS/DTLS
      * packets of any size up to and including the value returned by this
-     * method. All <code>SSLEngine</code> network buffers should be sized
+     * method. All {@code SSLEngine} network buffers should be sized
      * at least this large to avoid insufficient space problems when
-     * performing <code>wrap</code> and <code>unwrap</code> calls.
+     * performing {@code wrap} and {@code unwrap} calls.
      *
      * @return  the current maximum expected network packet size
      *
@@ -398,7 +398,7 @@
      * Gets the current size of the largest application data that is
      * expected when using this session.
      * <P>
-     * <code>SSLEngine</code> application data buffers must be large
+     * {@code SSLEngine} application data buffers must be large
      * enough to hold the application data from any inbound network
      * application data packet received.  Typically, outbound
      * application data buffers can be of any size.
--- a/src/java.base/share/classes/javax/net/ssl/X509ExtendedTrustManager.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/javax/net/ssl/X509ExtendedTrustManager.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. 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
@@ -32,16 +32,17 @@
 import java.security.cert.CertificateException;
 
 /**
- * Extensions to the <code>X509TrustManager</code> interface to support
- * SSL/TLS connection sensitive trust management.
+ * Extensions to the {@code X509TrustManager} interface to support
+ * SSL/TLS/DTLS connection sensitive trust management.
  * <p>
  * To prevent man-in-the-middle attacks, hostname checks can be done
  * to verify that the hostname in an end-entity certificate matches the
- * targeted hostname.  TLS does not require such checks, but some protocols
- * over TLS (such as HTTPS) do.  In earlier versions of the JDK, the
- * certificate chain checks were done at the SSL/TLS layer, and the hostname
- * verification checks were done at the layer over TLS.  This class allows
- * for the checking to be done during a single call to this class.
+ * targeted hostname.  TLS/DTLS does not require such checks, but some
+ * protocols over TLS/DTLS (such as HTTPS) do.  In earlier versions of the
+ * JDK, the certificate chain checks were done at the SSL/TLS/DTLS layer,
+ * and the hostname verification checks were done at the layer over TLS/DTLS.
+ * This class allows for the checking to be done during a single call to
+ * this class.
  * <p>
  * RFC 2830 defines the server identification specification for the "LDAPS"
  * algorithm. RFC 2818 defines both the server identification and the
@@ -62,17 +63,17 @@
      * used. For instance, if RSAPublicKey is used, the authType
      * should be "RSA". Checking is case-sensitive.
      * <p>
-     * If the <code>socket</code> parameter is an instance of
+     * If the {@code socket} parameter is an instance of
      * {@link javax.net.ssl.SSLSocket}, and the endpoint identification
-     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
-     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * algorithm of the {@code SSLParameters} is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the {@code socket}
      * connected to should be checked against the peer's identity presented
      * in the end-entity X509 certificate, as specified in the endpoint
      * identification algorithm.
      * <p>
-     * If the <code>socket</code> parameter is an instance of
+     * If the {@code socket} parameter is an instance of
      * {@link javax.net.ssl.SSLSocket}, and the algorithm constraints of the
-     * <code>SSLParameters</code> is non-null, for every certificate in the
+     * {@code SSLParameters} is non-null, for every certificate in the
      * certification path, fields such as subject public key, the signature
      * algorithm, key usage, extended key usage, etc. need to conform to the
      * algorithm constraints in place on this socket.
@@ -83,8 +84,8 @@
      *        can be null, which indicates that implementations need not check
      *        the ssl parameters
      * @throws IllegalArgumentException if null or zero-length array is passed
-     *        in for the <code>chain</code> parameter or if null or zero-length
-     *        string is passed in for the <code>authType</code> parameter
+     *        in for the {@code chain} parameter or if null or zero-length
+     *        string is passed in for the {@code authType} parameter
      * @throws CertificateException if the certificate chain is not trusted
      *        by this TrustManager
      *
@@ -110,17 +111,17 @@
      * used for the key exchange, and RSA when the key from the server
      * certificate is used. Checking is case-sensitive.
      * <p>
-     * If the <code>socket</code> parameter is an instance of
+     * If the {@code socket} parameter is an instance of
      * {@link javax.net.ssl.SSLSocket}, and the endpoint identification
-     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
-     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * algorithm of the {@code SSLParameters} is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the {@code socket}
      * connected to should be checked against the peer's identity presented
      * in the end-entity X509 certificate, as specified in the endpoint
      * identification algorithm.
      * <p>
-     * If the <code>socket</code> parameter is an instance of
+     * If the {@code socket} parameter is an instance of
      * {@link javax.net.ssl.SSLSocket}, and the algorithm constraints of the
-     *  <code>SSLParameters</code> is non-null, for every certificate in the
+     *  {@code SSLParameters} is non-null, for every certificate in the
      * certification path, fields such as subject public key, the signature
      * algorithm, key usage, extended key usage, etc. need to conform to the
      * algorithm constraints in place on this socket.
@@ -131,8 +132,8 @@
      *        can be null, which indicates that implementations need not check
      *        the ssl parameters
      * @throws IllegalArgumentException if null or zero-length array is passed
-     *        in for the <code>chain</code> parameter or if null or zero-length
-     *        string is passed in for the <code>authType</code> parameter
+     *        in for the {@code chain} parameter or if null or zero-length
+     *        string is passed in for the {@code authType} parameter
      * @throws CertificateException if the certificate chain is not trusted
      *        by this TrustManager
      *
@@ -153,15 +154,15 @@
      * used. For instance, if RSAPublicKey is used, the authType
      * should be "RSA". Checking is case-sensitive.
      * <p>
-     * If the <code>engine</code> parameter is available, and the endpoint
-     * identification algorithm of the <code>SSLParameters</code> is
+     * If the {@code engine} parameter is available, and the endpoint
+     * identification algorithm of the {@code SSLParameters} is
      * non-empty, to prevent man-in-the-middle attacks, the address that
-     * the <code>engine</code> connected to should be checked against
+     * the {@code engine} connected to should be checked against
      * the peer's identity presented in the end-entity X509 certificate,
      * as specified in the endpoint identification algorithm.
      * <p>
-     * If the <code>engine</code> parameter is available, and the algorithm
-     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * If the {@code engine} parameter is available, and the algorithm
+     * constraints of the {@code SSLParameters} is non-null, for every
      * certificate in the certification path, fields such as subject public
      * key, the signature algorithm, key usage, extended key usage, etc.
      * need to conform to the algorithm constraints in place on this engine.
@@ -172,8 +173,8 @@
      *        can be null, which indicates that implementations need not check
      *        the ssl parameters
      * @throws IllegalArgumentException if null or zero-length array is passed
-     *        in for the <code>chain</code> parameter or if null or zero-length
-     *        string is passed in for the <code>authType</code> parameter
+     *        in for the {@code chain} parameter or if null or zero-length
+     *        string is passed in for the {@code authType} parameter
      * @throws CertificateException if the certificate chain is not trusted
      *        by this TrustManager
      *
@@ -199,15 +200,15 @@
      * used for the key exchange, and RSA when the key from the server
      * certificate is used. Checking is case-sensitive.
      * <p>
-     * If the <code>engine</code> parameter is available, and the endpoint
-     * identification algorithm of the <code>SSLParameters</code> is
+     * If the {@code engine} parameter is available, and the endpoint
+     * identification algorithm of the {@code SSLParameters} is
      * non-empty, to prevent man-in-the-middle attacks, the address that
-     * the <code>engine</code> connected to should be checked against
+     * the {@code engine} connected to should be checked against
      * the peer's identity presented in the end-entity X509 certificate,
      * as specified in the endpoint identification algorithm.
      * <p>
-     * If the <code>engine</code> parameter is available, and the algorithm
-     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * If the {@code engine} parameter is available, and the algorithm
+     * constraints of the {@code SSLParameters} is non-null, for every
      * certificate in the certification path, fields such as subject public
      * key, the signature algorithm, key usage, extended key usage, etc.
      * need to conform to the algorithm constraints in place on this engine.
@@ -218,8 +219,8 @@
      *        can be null, which indicates that implementations need not check
      *        the ssl parameters
      * @throws IllegalArgumentException if null or zero-length array is passed
-     *        in for the <code>chain</code> parameter or if null or zero-length
-     *        string is passed in for the <code>authType</code> parameter
+     *        in for the {@code chain} parameter or if null or zero-length
+     *        string is passed in for the {@code authType} parameter
      * @throws CertificateException if the certificate chain is not trusted
      *        by this TrustManager
      *
--- a/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java	Thu Jun 11 00:51:11 2015 +0200
@@ -417,7 +417,7 @@
             | CONSTANT_InterfaceMethodref;
 
     private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
-        = new IdentityHashMap<Class<?>, Byte>();
+        = new IdentityHashMap<Class<?>, Byte>(6);
     private static final Class<?>[] CONSTANT_VALUE_CLASS = new Class<?>[16];
     static {
         Object[][] values = {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/misc/JavaBeansAccess.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public interface JavaBeansAccess {
+    /**
+     * Returns the getter method for a property of the given name
+     * @param clazz The JavaBeans class
+     * @param property The property name
+     * @return The resolved property getter method
+     * @throws Exception
+     */
+    Method getReadMethod(Class<?> clazz, String property) throws Exception;
+
+    /**
+     * Return the <b>value</b> attribute of the associated
+     * <code>@ConstructorProperties</code> annotation if that is present.
+     * @param ctr The constructor to extract the annotation value from
+     * @return The {@code value} attribute of the <code>@ConstructorProperties</code>
+     *         annotation or {@code null} if the constructor is not annotated by
+     *         this annotation or the annotation is not accessible.
+     */
+    String[] getConstructorPropertiesValue(Constructor<?> ctr);
+}
--- a/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java	Thu Jun 11 00:23:01 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.lang.reflect.Method;
-
-public interface JavaBeansIntrospectorAccess {
-    Method getReadMethod(Class<?> clazz, String property) throws Exception;
-}
--- a/src/java.base/share/classes/sun/misc/SharedSecrets.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/misc/SharedSecrets.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. 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
@@ -56,7 +56,7 @@
     private static JavaUtilZipFileAccess javaUtilZipFileAccess;
     private static JavaAWTAccess javaAWTAccess;
     private static JavaAWTFontAccess javaAWTFontAccess;
-    private static JavaBeansIntrospectorAccess javaBeansIntrospectorAccess;
+    private static JavaBeansAccess javaBeansAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -194,11 +194,11 @@
         return javaAWTFontAccess;
     }
 
-    public static JavaBeansIntrospectorAccess getJavaBeansIntrospectorAccess() {
-        return javaBeansIntrospectorAccess;
+    public static JavaBeansAccess getJavaBeansAccess() {
+        return javaBeansAccess;
     }
 
-    public static void setJavaBeansIntrospectorAccess(JavaBeansIntrospectorAccess access) {
-        javaBeansIntrospectorAccess = access;
+    public static void setJavaBeansAccess(JavaBeansAccess access) {
+        javaBeansAccess = access;
     }
 }
--- a/src/java.base/share/classes/sun/nio/cs/AbstractCharsetProvider.java	Thu Jun 11 00:23:01 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.nio.cs;
-
-import java.lang.ref.SoftReference;
-import java.nio.charset.Charset;
-import java.nio.charset.spi.CharsetProvider;
-import java.util.ArrayList;
-import java.util.TreeMap;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Map;
-import sun.misc.ASCIICaseInsensitiveComparator;
-
-
-/**
- * Abstract base class for charset providers.
- *
- * @author Mark Reinhold
- */
-
-public class AbstractCharsetProvider
-    extends CharsetProvider
-{
-
-    /* Maps canonical names to class names
-     */
-    private Map<String,String> classMap
-        = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
-
-    /* Maps alias names to canonical names
-     */
-    private Map<String,String> aliasMap
-        = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
-
-    /* Maps canonical names to alias-name arrays
-     */
-    private Map<String,String[]> aliasNameMap
-        = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
-
-    /* Maps canonical names to soft references that hold cached instances
-     */
-    private Map<String,SoftReference<Charset>> cache
-        = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
-
-    private String packagePrefix;
-
-    protected AbstractCharsetProvider() {
-        packagePrefix = "sun.nio.cs";
-    }
-
-    protected AbstractCharsetProvider(String pkgPrefixName) {
-        packagePrefix = pkgPrefixName;
-    }
-
-    /* Add an entry to the given map, but only if no mapping yet exists
-     * for the given name.
-     */
-    private static <K,V> void put(Map<K,V> m, K name, V value) {
-        if (!m.containsKey(name))
-            m.put(name, value);
-    }
-
-    private static <K,V> void remove(Map<K,V> m, K name) {
-        V x  = m.remove(name);
-        assert (x != null);
-    }
-
-    /* Declare support for the given charset
-     */
-    protected void charset(String name, String className, String[] aliases) {
-        synchronized (this) {
-            put(classMap, name, className);
-            for (int i = 0; i < aliases.length; i++)
-                put(aliasMap, aliases[i], name);
-            put(aliasNameMap, name, aliases);
-            cache.clear();
-        }
-    }
-
-    protected void deleteCharset(String name, String[] aliases) {
-        synchronized (this) {
-            remove(classMap, name);
-            for (int i = 0; i < aliases.length; i++)
-                remove(aliasMap, aliases[i]);
-            remove(aliasNameMap, name);
-            cache.clear();
-        }
-    }
-
-    protected boolean hasCharset(String name) {
-        synchronized (this) {
-            return classMap.containsKey(name);
-        }
-    }
-
-    /* Late initialization hook, needed by some providers
-     */
-    protected void init() { }
-
-    private String canonicalize(String charsetName) {
-        String acn = aliasMap.get(charsetName);
-        return (acn != null) ? acn : charsetName;
-    }
-
-    private Charset lookup(String csn) {
-
-        // Check cache first
-        SoftReference<Charset> sr = cache.get(csn);
-        if (sr != null) {
-            Charset cs = sr.get();
-            if (cs != null)
-                return cs;
-        }
-
-        // Do we even support this charset?
-        String cln = classMap.get(csn);
-
-        if (cln == null)
-            return null;
-
-        // Instantiate the charset and cache it
-        try {
-
-            Class<?> c = Class.forName(packagePrefix + "." + cln,
-                                       true,
-                                       this.getClass().getClassLoader());
-
-            Charset cs = (Charset)c.newInstance();
-            cache.put(csn, new SoftReference<Charset>(cs));
-            return cs;
-        } catch (ClassNotFoundException x) {
-            return null;
-        } catch (IllegalAccessException x) {
-            return null;
-        } catch (InstantiationException x) {
-            return null;
-        }
-    }
-
-    public final Charset charsetForName(String charsetName) {
-        synchronized (this) {
-            init();
-            return lookup(canonicalize(charsetName));
-        }
-    }
-
-    public final Iterator<Charset> charsets() {
-
-        final ArrayList<String> ks;
-        synchronized (this) {
-            init();
-            ks = new ArrayList<>(classMap.keySet());
-        }
-
-        return new Iterator<Charset>() {
-                Iterator<String> i = ks.iterator();
-
-                public boolean hasNext() {
-                    return i.hasNext();
-                }
-
-                public Charset next() {
-                    String csn = i.next();
-                    synchronized (AbstractCharsetProvider.this) {
-                        return lookup(csn);
-                    }
-                }
-
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-            };
-    }
-
-    public final String[] aliases(String charsetName) {
-        synchronized (this) {
-            init();
-            return aliasNameMap.get(charsetName);
-        }
-    }
-
-}
--- a/src/java.base/share/classes/sun/security/ssl/AppInputStream.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/AppInputStream.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. 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
@@ -26,41 +26,54 @@
 
 package sun.security.ssl;
 
-import java.io.*;
+import java.io.InputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import javax.net.ssl.SSLProtocolException;
 
 /**
  * InputStream for application data as returned by SSLSocket.getInputStream().
- * It uses an InputRecord as internal buffer that is refilled on demand
- * whenever it runs out of data.
  *
  * @author David Brownell
  */
-class AppInputStream extends InputStream {
+final class AppInputStream extends InputStream {
+    // the buffer size for each read of network data
+    private static final int READ_BUFFER_SIZE = 4096;
 
     // static dummy array we use to implement skip()
-    private final static byte[] SKIP_ARRAY = new byte[1024];
+    private static final byte[] SKIP_ARRAY = new byte[256];
 
-    private SSLSocketImpl c;
-    InputRecord r;
+    // the related socket of the input stream
+    private final SSLSocketImpl socket;
+
+    // the temporary buffer used to read network
+    private ByteBuffer buffer;
+
+    // Is application data available in the stream?
+    private boolean appDataIsAvailable;
 
     // One element array used to implement the single byte read() method
     private final byte[] oneByte = new byte[1];
 
     AppInputStream(SSLSocketImpl conn) {
-        r = new InputRecord();
-        c = conn;
+        this.buffer = ByteBuffer.allocate(READ_BUFFER_SIZE);
+        this.socket = conn;
+        this.appDataIsAvailable = false;
     }
 
     /**
      * Return the minimum number of bytes that can be read without blocking.
+     *
      * Currently not synchronized.
      */
     @Override
     public int available() throws IOException {
-        if (c.checkEOF() || (r.isAppDataValid() == false)) {
+        if ((!appDataIsAvailable) || socket.checkEOF()) {
             return 0;
         }
-        return r.available();
+
+        return buffer.remaining();
     }
 
     /**
@@ -72,17 +85,21 @@
         if (n <= 0) { // EOF
             return -1;
         }
-        return oneByte[0] & 0xff;
+        return oneByte[0] & 0xFF;
     }
 
     /**
-     * Read up to "len" bytes into this buffer, starting at "off".
+     * Reads up to {@code len} bytes of data from the input stream into an
+     * array of bytes. An attempt is made to read as many as {@code len} bytes,
+     * but a smaller number may be read. The number of bytes actually read
+     * is returned as an integer.
+     *
      * If the layer above needs more data, it asks for more, so we
      * are responsible only for blocking to fill at most one buffer,
      * and returning "-1" on non-fault EOF status.
      */
     @Override
-    public synchronized int read(byte b[], int off, int len)
+    public synchronized int read(byte[] b, int off, int len)
             throws IOException {
         if (b == null) {
             throw new NullPointerException();
@@ -92,28 +109,69 @@
             return 0;
         }
 
-        if (c.checkEOF()) {
+        if (socket.checkEOF()) {
             return -1;
         }
+
+        // Read the available bytes at first.
+        int remains = available();
+        if (remains > 0) {
+            int howmany = Math.min(remains, len);
+            buffer.get(b, off, howmany);
+
+            return howmany;
+        }
+
+        appDataIsAvailable = false;
+        int volume = 0;
+
         try {
             /*
              * Read data if needed ... notice that the connection guarantees
              * that handshake, alert, and change cipher spec data streams are
              * handled as they arrive, so we never see them here.
              */
-            while (r.available() == 0) {
-                c.readDataRecord(r);
-                if (c.checkEOF()) {
+            while(volume == 0) {
+                // Clear the buffer for a new record reading.
+                buffer.clear();
+
+                //
+                // grow the buffer if needed
+                //
+
+                // Read the header of a record into the buffer, and return
+                // the packet size.
+                int packetLen = socket.bytesInCompletePacket();
+                if (packetLen < 0) {    // EOF
                     return -1;
                 }
+
+                // Is this packet bigger than SSL/TLS normally allows?
+                if (packetLen > SSLRecord.maxLargeRecordSize) {
+                    throw new SSLProtocolException(
+                        "Illegal packet size: " + packetLen);
+                }
+
+                if (packetLen > buffer.remaining()) {
+                    buffer = ByteBuffer.allocate(packetLen);
+                }
+
+                volume = socket.readRecord(buffer);
+                if (volume < 0) {    // EOF
+                    return -1;
+                } else if (volume > 0) {
+                    appDataIsAvailable = true;
+                    break;
+                }
             }
 
-            int howmany = Math.min(len, r.available());
-            howmany = r.read(b, off, howmany);
+            int howmany = Math.min(len, volume);
+            buffer.get(b, off, howmany);
             return howmany;
         } catch (Exception e) {
             // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
+            socket.handleException(e);
+
             // dummy for compiler
             return -1;
         }
@@ -147,9 +205,8 @@
      */
     @Override
     public void close() throws IOException {
-        c.close();
+        socket.close();
     }
 
     // inherit default mark/reset behavior (throw Exceptions) from InputStream
-
 }
--- a/src/java.base/share/classes/sun/security/ssl/AppOutputStream.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/AppOutputStream.java	Thu Jun 11 00:51:11 2015 +0200
@@ -23,41 +23,33 @@
  * questions.
  */
 
-
 package sun.security.ssl;
 
 import java.io.OutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 /*
- * Output stream for application data. This is the kind of stream
- * that's handed out via SSLSocket.getOutputStream(). It's all the application
- * ever sees.
- *
- * Once the initial handshake has completed, application data may be
- * interleaved with handshake data. That is handled internally and remains
- * transparent to the application.
+ * OutputStream for application data as returned by SSLSocket.getOutputStream().
  *
  * @author  David Brownell
  */
 class AppOutputStream extends OutputStream {
 
-    private SSLSocketImpl c;
-    OutputRecord r;
+    private SSLSocketImpl socket;
 
     // One element array used to implement the write(byte) method
     private final byte[] oneByte = new byte[1];
 
     AppOutputStream(SSLSocketImpl conn) {
-        r = new OutputRecord(Record.ct_application_data);
-        c = conn;
+        this.socket = conn;
     }
 
     /**
      * Write the data out, NOW.
      */
     @Override
-    synchronized public void write(byte b[], int off, int len)
+    synchronized public void write(byte[] b, int off, int len)
             throws IOException {
         if (b == null) {
             throw new NullPointerException();
@@ -68,64 +60,15 @@
         }
 
         // check if the Socket is invalid (error or closed)
-        c.checkWrite();
+        socket.checkWrite();
 
-        /*
-         * By default, we counter chosen plaintext issues on CBC mode
-         * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
-         * data in the first record of every payload, and the rest in
-         * subsequent record(s). Note that the issues have been solved in
-         * TLS 1.1 or later.
-         *
-         * It is not necessary to split the very first application record of
-         * a freshly negotiated TLS session, as there is no previous
-         * application data to guess.  To improve compatibility, we will not
-         * split such records.
-         *
-         * This avoids issues in the outbound direction.  For a full fix,
-         * the peer must have similar protections.
-         */
-        boolean isFirstRecordOfThePayload = true;
-
-        // Always flush at the end of each application level record.
-        // This lets application synchronize read and write streams
-        // however they like; if we buffered here, they couldn't.
+        // Delegate the writing to the underlying socket.
         try {
-            do {
-                boolean holdRecord = false;
-                int howmuch;
-                if (isFirstRecordOfThePayload && c.needToSplitPayload()) {
-                    howmuch = Math.min(0x01, r.availableDataBytes());
-                     /*
-                      * Nagle's algorithm (TCP_NODELAY) was coming into
-                      * play here when writing short (split) packets.
-                      * Signal to the OutputRecord code to internally
-                      * buffer this small packet until the next outbound
-                      * packet (of any type) is written.
-                      */
-                     if ((len != 1) && (howmuch == 1)) {
-                         holdRecord = true;
-                     }
-                } else {
-                    howmuch = Math.min(len, r.availableDataBytes());
-                }
-
-                if (isFirstRecordOfThePayload && howmuch != 0) {
-                    isFirstRecordOfThePayload = false;
-                }
-
-                // NOTE: *must* call c.writeRecord() even for howmuch == 0
-                if (howmuch > 0) {
-                    r.write(b, off, howmuch);
-                    off += howmuch;
-                    len -= howmuch;
-                }
-                c.writeRecord(r, holdRecord);
-                c.checkWrite();
-            } while (len > 0);
+            socket.writeRecord(b, off, len);
+            socket.checkWrite();
         } catch (Exception e) {
             // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
+            socket.handleException(e);
         }
     }
 
@@ -143,7 +86,7 @@
      */
     @Override
     public void close() throws IOException {
-        c.close();
+        socket.close();
     }
 
     // inherit no-op flush()
--- a/src/java.base/share/classes/sun/security/ssl/Authenticator.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/Authenticator.java	Thu Jun 11 00:51:11 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. 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
@@ -28,19 +28,26 @@
 import java.util.Arrays;
 
 /**
- * This class represents an SSL/TLS message authentication token,
+ * This class represents an SSL/TLS/DTLS message authentication token,
  * which encapsulates a sequence number and ensures that attempts to
  * delete or reorder messages can be detected.
  *
- * Each SSL/TLS connection state contains a sequence number, which
- * is maintained separately for read and write states.  The sequence
- * number MUST be set to zero whenever a connection state is made the
- * active state.  Sequence numbers are of type uint64 and may not
- * exceed 2^64-1.  Sequence numbers do not wrap.  If a SSL/TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead.  A sequence number is incremented after each
- * record: specifically, the first record transmitted under a
- * particular connection state MUST use sequence number 0.
+ * Each connection state contains a sequence number, which is maintained
+ * separately for read and write states.
+ *
+ * For SSL/TLS protocols, the sequence number MUST be set to zero
+ * whenever a connection state is made the active state.
+ *
+ * DTLS uses an explicit sequence number, rather than an implicit one.
+ * Sequence numbers are maintained separately for each epoch, with
+ * each sequence number initially being 0 for each epoch.  The sequence
+ * number used to compute the DTLS MAC is the 64-bit value formed by
+ * concatenating the epoch and the sequence number.
+ *
+ * Sequence numbers do not wrap.  If an implementation would need to wrap
+ * a sequence number, it must renegotiate instead.  A sequence number is
+ * incremented after each record: specifically, the first record transmitted
+ * under a particular connection state MUST use sequence number 0.
  */
 class Authenticator {
 
@@ -56,13 +63,30 @@
     // sequence number + record type + protocol version + record length
     private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
 
+    // the block size of DTLS v1.0 and later:
+    // epoch + sequence number + record type + protocol version + record length
+    private static final int BLOCK_SIZE_DTLS = 2 + 6 + 1 + 2 + 2;
+
+    private final boolean isDTLS;
+
     /**
      * Default construct, no message authentication token is initialized.
      *
      * Note that this construct can only be called for null MAC
      */
-    Authenticator() {
-        block = new byte[0];
+    protected Authenticator(boolean isDTLS) {
+        if (isDTLS) {
+            // For DTLS protocols, plaintexts use explicit epoch and
+            // sequence number in each record.  The first 8 byte of
+            // the block is initialized for null MAC so that the
+            // epoch and sequence number can be acquired to generate
+            // plaintext records.
+            block = new byte[8];
+        } else {
+            block = new byte[0];
+        }
+
+        this.isDTLS = isDTLS;
     }
 
     /**
@@ -70,12 +94,22 @@
      * SSL/TLS protocol.
      */
     Authenticator(ProtocolVersion protocolVersion) {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+        if (protocolVersion.isDTLSProtocol()) {
+            block = new byte[BLOCK_SIZE_DTLS];
+            block[9] = protocolVersion.major;
+            block[10] = protocolVersion.minor;
+
+            this.isDTLS = true;
+        } else if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
             block = new byte[BLOCK_SIZE_TLS];
             block[9] = protocolVersion.major;
             block[10] = protocolVersion.minor;
+
+            this.isDTLS = false;
         } else {
             block = new byte[BLOCK_SIZE_SSL];
+
+            this.isDTLS = false;
         }
     }
 
@@ -93,11 +127,19 @@
          * Conservatively, we don't allow more records to be generated
          * when there are only 2^8 sequence numbers left.
          */
-        return (block.length != 0 &&
+        if (isDTLS) {
+            return (block.length != 0 &&
+                // no epoch bytes, block[0] and block[1]
+                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
+                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
+                block[6] == (byte)0xFF);
+        } else {
+            return (block.length != 0 &&
                 block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
                 block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
                 block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
                 block[6] == (byte)0xFF);
+        }
     }
 
     /**
@@ -113,14 +155,22 @@
     final boolean seqNumIsHuge() {
         /*
          * Conservatively, we should ask for renegotiation when there are
-         * only 2^48 sequence numbers left.
+         * only 2^32 sequence numbers left.
          */
-        return (block.length != 0 &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF);
+        if (isDTLS) {
+            return (block.length != 0 &&
+                // no epoch bytes, block[0] and block[1]
+                block[2] == (byte)0xFF && block[3] == (byte)0xFF);
+        } else {
+            return (block.length != 0 &&
+                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
+                block[2] == (byte)0xFF && block[3] == (byte)0xFF);
+        }
     }
 
     /**
-     * Gets the current sequence number.
+     * Gets the current sequence number, including the epoch number for
+     * DTLS protocols.
      *
      * @return the byte array of the current sequence number
      */
@@ -129,33 +179,83 @@
     }
 
     /**
+     * Sets the epoch number (only apply to DTLS protocols).
+     */
+    final void setEpochNumber(int epoch) {
+        if (!isDTLS) {
+            throw new RuntimeException(
+                "Epoch numbers apply to DTLS protocols only");
+        }
+
+        block[0] = (byte)((epoch >> 8) & 0xFF);
+        block[1] = (byte)(epoch & 0xFF);
+    }
+
+    /**
+     * Increase the sequence number.
+     */
+    final void increaseSequenceNumber() {
+        /*
+         * The sequence number in the block array is a 64-bit
+         * number stored in big-endian format.
+         */
+        int k = 7;
+        while ((k >= 0) && (++block[k] == 0)) {
+            k--;
+        }
+    }
+
+    /**
      * Acquires the current message authentication information with the
      * specified record type and fragment length, and then increases the
      * sequence number.
      *
      * @param  type the record type
      * @param  length the fragment of the record
+     * @param  sequence the explicit sequence number of the record
+     *
      * @return the byte array of the current message authentication information
      */
-    final byte[] acquireAuthenticationBytes(byte type, int length) {
+    final byte[] acquireAuthenticationBytes(
+            byte type, int length, byte[] sequence) {
+
         byte[] copy = block.clone();
+        if (sequence != null) {
+            if (sequence.length != 8) {
+                throw new RuntimeException(
+                        "Insufficient explicit sequence number bytes");
+            }
+
+            System.arraycopy(sequence, 0, copy, 0, sequence.length);
+        }   // Otherwise, use the implicit sequence number.
 
         if (block.length != 0) {
             copy[8] = type;
+
             copy[copy.length - 2] = (byte)(length >> 8);
             copy[copy.length - 1] = (byte)(length);
 
-            /*
-             * Increase the sequence number in the block array
-             * it is a 64-bit number stored in big-endian format
-             */
-            int k = 7;
-            while ((k >= 0) && (++block[k] == 0)) {
-                k--;
+            if (sequence == null || sequence.length != 0) {
+                // Increase the implicit sequence number in the block array.
+                increaseSequenceNumber();
             }
         }
 
         return copy;
     }
 
+    final static long toLong(byte[] recordEnS) {
+        if (recordEnS != null && recordEnS.length == 8) {
+            return ((recordEnS[0] & 0xFFL) << 56) |
+                   ((recordEnS[1] & 0xFFL) << 48) |
+                   ((recordEnS[2] & 0xFFL) << 40) |
+                   ((recordEnS[3] & 0xFFL) << 32) |
+                   ((recordEnS[4] & 0xFFL) << 24) |
+                   ((recordEnS[5] & 0xFFL) << 16) |
+                   ((recordEnS[6] & 0xFFL) <<  8) |
+                    (recordEnS[7] & 0xFFL);
+        }
+
+        return -1L;
+    }
 }
--- a/src/java.base/share/classes/sun/security/ssl/CipherBox.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/CipherBox.java	Thu Jun 11 00:51:11 2015 +0200
@@ -154,9 +154,9 @@
      * NULL cipherbox. Identity operation, no encryption.
      */
     private CipherBox() {
-        this.protocolVersion = ProtocolVersion.DEFAULT;
+        this.protocolVersion = ProtocolVersion.DEFAULT_TLS;
         this.cipher = null;
-        this.cipherType = STREAM_CIPHER;
+        this.cipherType = NULL_CIPHER;
         this.fixedIv = new byte[0];
         this.key = null;
         this.mode = Cipher.ENCRYPT_MODE;    // choose at random
@@ -197,7 +197,7 @@
              */
             if (iv == null && bulkCipher.ivSize != 0 &&
                     mode == Cipher.DECRYPT_MODE &&
-                    protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    protocolVersion.useTLS11PlusSpec()) {
                 iv = getFixedMask(bulkCipher.ivSize);
             }
 
@@ -491,7 +491,7 @@
                 newLen = removePadding(
                     buf, offset, newLen, tagLen, blockSize, protocolVersion);
 
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                if (protocolVersion.useTLS11PlusSpec()) {
                     if (newLen < blockSize) {
                         throw new BadPaddingException("invalid explicit IV");
                     }
@@ -573,7 +573,7 @@
                 newLen = removePadding(bb, tagLen, blockSize, protocolVersion);
 
                 // check the explicit IV of TLS v1.1 or later
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                if (protocolVersion.useTLS11PlusSpec()) {
                     if (newLen < blockSize) {
                         throw new BadPaddingException("invalid explicit IV");
                     }
@@ -746,7 +746,7 @@
         // The padding data should be filled with the padding length value.
         int[] results = checkPadding(buf, offset + newLen,
                         padLen + 1, (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+        if (protocolVersion.useTLS10PlusSpec()) {
             if (results[0] != 0) {          // padding data has invalid bytes
                 throw new BadPaddingException("Invalid TLS padding data");
             }
@@ -792,7 +792,7 @@
         int[] results = checkPadding(
                 bb.duplicate().position(offset + newLen),
                 (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+        if (protocolVersion.useTLS10PlusSpec()) {
             if (results[0] != 0) {          // padding data has invalid bytes
                 throw new BadPaddingException("Invalid TLS padding data");
             }
@@ -873,7 +873,7 @@
                 // For block ciphers, the explicit IV length is of length
                 // SecurityParameters.record_iv_length, which is equal to
                 // the SecurityParameters.block_size.
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                if (protocolVersion.useTLS11PlusSpec()) {
                     return cipher.getBlockSize();
                 }
                 break;
@@ -902,7 +902,7 @@
      * @return the explicit nonce size of the cipher.
      */
     int applyExplicitNonce(Authenticator authenticator, byte contentType,
-            ByteBuffer bb) throws BadPaddingException {
+            ByteBuffer bb, byte[] sequence) throws BadPaddingException {
         switch (cipherType) {
             case BLOCK_CIPHER:
                 // sanity check length of the ciphertext
@@ -918,7 +918,7 @@
                 // For block ciphers, the explicit IV length is of length
                 // SecurityParameters.record_iv_length, which is equal to
                 // the SecurityParameters.block_size.
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                if (protocolVersion.useTLS11PlusSpec()) {
                     return cipher.getBlockSize();
                 }
                 break;
@@ -945,7 +945,8 @@
 
                 // update the additional authentication data
                 byte[] aad = authenticator.acquireAuthenticationBytes(
-                        contentType, bb.remaining() - recordIvSize - tagSize);
+                        contentType, bb.remaining() - recordIvSize - tagSize,
+                        sequence);
                 cipher.updateAAD(aad);
 
                 return recordIvSize;
@@ -957,33 +958,6 @@
     }
 
     /*
-     * Applies the explicit nonce/IV to this cipher. This method is used to
-     * decrypt an SSL/TLS input record.
-     *
-     * The returned value is the SecurityParameters.record_iv_length in
-     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
-     * size of explicit nonce for AEAD mode.
-     *
-     * @param  authenticator the authenticator to get the additional
-     *         authentication data
-     * @param  contentType the content type of the input record
-     * @param  buf the byte array to get the explicit nonce from
-     * @param  offset the offset of the byte buffer
-     * @param  cipheredLength the ciphered fragment length of the output
-     *         record, it is the TLSCiphertext.length in RFC 4346/5246.
-     *
-     * @return the explicit nonce size of the cipher.
-     */
-    int applyExplicitNonce(Authenticator authenticator,
-            byte contentType, byte[] buf, int offset,
-            int cipheredLength) throws BadPaddingException {
-
-        ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength);
-
-        return applyExplicitNonce(authenticator, contentType, bb);
-    }
-
-    /*
      * Creates the explicit nonce/IV to this cipher. This method is used to
      * encrypt an SSL/TLS output record.
      *
@@ -1005,7 +979,7 @@
         byte[] nonce = new byte[0];
         switch (cipherType) {
             case BLOCK_CIPHER:
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                if (protocolVersion.useTLS11PlusSpec()) {
                     // For block ciphers, the explicit IV length is of length
                     // SecurityParameters.record_iv_length, which is equal to
                     // the SecurityParameters.block_size.
@@ -1034,9 +1008,10 @@
                                 "invalid key or spec in GCM mode", ikae);
                 }
 
-                // update the additional authentication data
+                // Update the additional authentication data, using the
+                // implicit sequence number of the authenticator.
                 byte[] aad = authenticator.acquireAuthenticationBytes(
-                                                contentType, fragmentLength);
+                                        contentType, fragmentLength, null);
                 cipher.updateAAD(aad);
                 break;
         }
@@ -1044,6 +1019,93 @@
         return nonce;
     }
 
+    // See also CipherSuite.calculatePacketSize().
+    int calculatePacketSize(int fragmentSize, int macLen, int headerSize) {
+        int packetSize = fragmentSize;
+        if (cipher != null) {
+            int blockSize = cipher.getBlockSize();
+            switch (cipherType) {
+                case BLOCK_CIPHER:
+                    packetSize += macLen;
+                    packetSize += 1;        // 1 byte padding length field
+                    packetSize +=           // use the minimal padding
+                            (blockSize - (packetSize % blockSize)) % blockSize;
+                    if (protocolVersion.useTLS11PlusSpec()) {
+                        packetSize += blockSize;        // explicit IV
+                    }
+
+                    break;
+                case AEAD_CIPHER:
+                    packetSize += recordIvSize;
+                    packetSize += tagSize;
+
+                    break;
+                default:    // NULL_CIPHER or STREAM_CIPHER
+                    packetSize += macLen;
+            }
+        }
+
+        return packetSize + headerSize;
+    }
+
+    // See also CipherSuite.calculateFragSize().
+    int calculateFragmentSize(int packetLimit, int macLen, int headerSize) {
+        int fragLen = packetLimit - headerSize;
+        if (cipher != null) {
+            int blockSize = cipher.getBlockSize();
+            switch (cipherType) {
+                case BLOCK_CIPHER:
+                    if (protocolVersion.useTLS11PlusSpec()) {
+                        fragLen -= blockSize;           // explicit IV
+                    }
+                    fragLen -= (fragLen % blockSize);   // cannot hold a block
+                    // No padding for a maximum fragment.
+                    fragLen -= 1;       // 1 byte padding length field: 0x00
+                    fragLen -= macLen;
+
+                    break;
+                case AEAD_CIPHER:
+                    fragLen -= recordIvSize;
+                    fragLen -= tagSize;
+
+                    break;
+                default:    // NULL_CIPHER or STREAM_CIPHER
+                    fragLen -= macLen;
+            }
+        }
+
+        return fragLen;
+    }
+
+    // Estimate the maximum fragment size of a received packet.
+    int estimateFragmentSize(int packetSize, int macLen, int headerSize) {
+        int fragLen = packetSize - headerSize;
+        if (cipher != null) {
+            int blockSize = cipher.getBlockSize();
+            switch (cipherType) {
+                case BLOCK_CIPHER:
+                    if (protocolVersion.useTLS11PlusSpec()) {
+                        fragLen -= blockSize;       // explicit IV
+                    }
+                    // No padding for a maximum fragment.
+                    fragLen -= 1;       // 1 byte padding length field: 0x00
+                    fragLen -= macLen;
+
+                    break;
+                case AEAD_CIPHER:
+                    fragLen -= recordIvSize;
+                    fragLen -= tagSize;
+
+                    break;
+                default:    // NULL_CIPHER or STREAM_CIPHER
+                    fragLen -= macLen;
+            }
+        }
+
+        return fragLen;
+    }
+
+
     /*
      * Is this cipher available?
      *
@@ -1100,7 +1162,7 @@
         if ((fragmentLen % blockSize) == 0) {
             int minimal = tagLen + 1;
             minimal = (minimal >= blockSize) ? minimal : blockSize;
-            if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+            if (protocolVersion.useTLS11PlusSpec()) {
                 minimal += blockSize;   // plus the size of the explicit IV
             }
 
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Thu Jun 11 00:51:11 2015 +0200
@@ -122,9 +122,15 @@
     final boolean allowed;
 
     // obsoleted since protocol version
+    //
+    // TLS version is used.  If checking DTLS versions, please map to
+    // TLS version firstly.  See ProtocolVersion.mapToTLSProtocol().
     final int obsoleted;
 
-    // supported since protocol version
+    // supported since protocol version (TLS version is used)
+    //
+    // TLS version is used.  If checking DTLS versions, please map to
+    // TLS version firstly.  See ProtocolVersion.mapToTLSProtocol().
     final int supported;
 
     /**
@@ -182,6 +188,70 @@
         return this != C_SCSV && isAvailable();
     }
 
+    // See also CipherBox.calculatePacketSize().
+    int calculatePacketSize(int fragmentSize,
+            ProtocolVersion protocolVersion, boolean isDTLS) {
+
+        int packetSize = fragmentSize;
+        if (cipher != B_NULL) {
+            int blockSize = cipher.ivSize;
+            switch (cipher.cipherType) {
+                case BLOCK_CIPHER:
+                    packetSize += macAlg.size;
+                    packetSize += 1;        // 1 byte padding length field
+                    packetSize +=           // use the minimal padding
+                            (blockSize - (packetSize % blockSize)) % blockSize;
+                    if (protocolVersion.useTLS11PlusSpec()) {
+                        packetSize += blockSize;        // explicit IV
+                    }
+
+                    break;
+            case AEAD_CIPHER:
+                packetSize += cipher.ivSize - cipher.fixedIvSize;   // record IV
+                packetSize += cipher.tagSize;
+
+                break;
+            default:    // NULL_CIPHER or STREAM_CIPHER
+                packetSize += macAlg.size;
+            }
+        }
+
+        return packetSize +
+            (isDTLS ? DTLSRecord.headerSize : SSLRecord.headerSize);
+    }
+
+    // See also CipherBox.calculateFragmentSize().
+    int calculateFragSize(int packetLimit,
+            ProtocolVersion protocolVersion, boolean isDTLS) {
+
+        int fragSize = packetLimit -
+                (isDTLS ? DTLSRecord.headerSize : SSLRecord.headerSize);
+        if (cipher != B_NULL) {
+            int blockSize = cipher.ivSize;
+            switch (cipher.cipherType) {
+            case BLOCK_CIPHER:
+                if (protocolVersion.useTLS11PlusSpec()) {
+                    fragSize -= blockSize;              // explicit IV
+                }
+                fragSize -= (fragSize % blockSize);     // cannot hold a block
+                // No padding for a maximum fragment.
+                fragSize -= 1;        // 1 byte padding length field: 0x00
+                fragSize -= macAlg.size;
+
+                break;
+            case AEAD_CIPHER:
+                fragSize -= cipher.tagSize;
+                fragSize -= cipher.ivSize - cipher.fixedIvSize;     // record IV
+
+                break;
+            default:    // NULL_CIPHER or STREAM_CIPHER
+                fragSize -= macAlg.size;
+            }
+        }
+
+        return fragSize;
+    }
+
     /**
      * Compares CipherSuites based on their priority. Has the effect of
      * sorting CipherSuites when put in a sorted collection, which is
@@ -242,7 +312,7 @@
         return c;
     }
 
-    // for use by CipherSuiteList only
+    // for use by SSLContextImpl only
     static Collection<CipherSuite> allowedCipherSuites() {
         return nameMap.values();
     }
@@ -372,7 +442,8 @@
     }
 
     static enum CipherType {
-        STREAM_CIPHER,         // null or stream cipher
+        NULL_CIPHER,           // null cipher
+        STREAM_CIPHER,         // stream cipher
         BLOCK_CIPHER,          // block cipher in CBC mode
         AEAD_CIPHER            // AEAD cipher
     }
@@ -387,7 +458,7 @@
     static enum BulkCipher {
 
         // export strength ciphers
-        B_NULL("NULL", STREAM_CIPHER, 0, 0, 0, 0, true),
+        B_NULL("NULL", NULL_CIPHER, 0, 0, 0, 0, true),
         B_RC4_40(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true),
         B_RC2_40("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false),
         B_DES_40(CIPHER_DES,  BLOCK_CIPHER, 5, 8, 8, 0, true),
@@ -568,7 +639,7 @@
                             iv = new IvParameterSpec(new byte[cipher.ivSize]);
                         }
                         temporary = cipher.newCipher(
-                                            ProtocolVersion.DEFAULT,
+                                            ProtocolVersion.DEFAULT_TLS,
                                             key, iv, secureRandom, true);
                         b = temporary.isAvailable();
                     } catch (NoSuchAlgorithmException e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/Ciphertext.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import static sun.security.ssl.HandshakeMessage.*;
+
+/*
+ * enumeration of record type
+ */
+final class Ciphertext {
+    final static Ciphertext CIPHERTEXT_NULL = new Ciphertext();
+
+    RecordType recordType;
+    long recordSN;
+
+    HandshakeStatus handshakeStatus;    // null if not used or not handshaking
+
+    Ciphertext() {
+        this.recordType = null;
+        this.recordSN = -1L;
+        this.handshakeStatus = null;
+    }
+
+    Ciphertext(RecordType recordType, long recordSN) {
+        this.recordType = recordType;
+        this.recordSN = recordSN;
+        this.handshakeStatus = null;
+    }
+
+    static enum RecordType {
+        RECORD_CHANGE_CIPHER_SPEC (
+                Record.ct_change_cipher_spec, ht_not_applicable),
+        RECORD_ALERT (
+                Record.ct_alert, ht_not_applicable),
+        RECORD_HELLO_REQUEST (
+                Record.ct_handshake, ht_hello_request),
+        RECORD_CLIENT_HELLO (
+                Record.ct_handshake, ht_client_hello),
+        RECORD_SERVER_HELLO (
+                Record.ct_handshake, ht_server_hello),
+        RECORD_HELLO_VERIFY_REQUEST (
+                Record.ct_handshake, ht_hello_verify_request),
+        RECORD_NEW_SESSION_TICKET (
+                Record.ct_handshake, ht_new_session_ticket),
+        RECORD_CERTIFICATE (
+                Record.ct_handshake, ht_certificate),
+        RECORD_SERVER_KEY_EXCHANGE (
+                Record.ct_handshake, ht_server_key_exchange),
+        RECORD_CERTIFICATE_REQUEST (
+                Record.ct_handshake, ht_certificate_request),
+        RECORD_SERVER_HELLO_DONE (
+                Record.ct_handshake, ht_server_hello_done),
+        RECORD_CERTIFICATE_VERIFY (
+                Record.ct_handshake, ht_certificate_verify),
+        RECORD_CLIENT_KEY_EXCHANGE (
+                Record.ct_handshake, ht_client_key_exchange),
+        RECORD_FINISHED (
+                Record.ct_handshake, ht_finished),
+        RECORD_CERTIFICATE_URL (
+                Record.ct_handshake, ht_certificate_url),
+        RECORD_CERTIFICATE_STATUS (
+                Record.ct_handshake, ht_certificate_status),
+        RECORD_SUPPLIEMENTAL_DATA (
+                Record.ct_handshake, ht_supplemental_data),
+        RECORD_APPLICATION_DATA (
+                Record.ct_application_data, ht_not_applicable);
+
+        byte contentType;
+        byte handshakeType;
+
+        private RecordType(byte contentType, byte handshakeType) {
+            this.contentType = contentType;
+            this.handshakeType = handshakeType;
+        }
+
+        static RecordType valueOf(byte contentType, byte handshakeType) {
+            if (contentType == Record.ct_change_cipher_spec) {
+                return RECORD_CHANGE_CIPHER_SPEC;
+            } else if (contentType == Record.ct_alert) {
+                return RECORD_ALERT;
+            } else if (contentType == Record.ct_application_data) {
+                return RECORD_APPLICATION_DATA;
+            } else if (handshakeType == ht_hello_request) {
+                return RECORD_HELLO_REQUEST;
+            } else if (handshakeType == ht_client_hello) {
+                return RECORD_CLIENT_HELLO;
+            } else if (handshakeType == ht_server_hello) {
+                return RECORD_SERVER_HELLO;
+            } else if (handshakeType == ht_hello_verify_request) {
+                return RECORD_HELLO_VERIFY_REQUEST;
+            } else if (handshakeType == ht_new_session_ticket) {
+                return RECORD_NEW_SESSION_TICKET;
+            } else if (handshakeType == ht_certificate) {
+                return RECORD_CERTIFICATE;
+            } else if (handshakeType == ht_server_key_exchange) {
+                return RECORD_SERVER_KEY_EXCHANGE;
+            } else if (handshakeType == ht_certificate_request) {
+                return RECORD_CERTIFICATE_REQUEST;
+            } else if (handshakeType == ht_server_hello_done) {
+                return RECORD_SERVER_HELLO_DONE;
+            } else if (handshakeType == ht_certificate_verify) {
+                return RECORD_CERTIFICATE_VERIFY;
+            } else if (handshakeType == ht_client_key_exchange) {
+                return RECORD_CLIENT_KEY_EXCHANGE;
+            } else if (handshakeType == ht_finished) {
+                return RECORD_FINISHED;
+            } else if (handshakeType == ht_certificate_url) {
+                return RECORD_CERTIFICATE_URL;
+            } else if (handshakeType == ht_certificate_status) {
+                return RECORD_CERTIFICATE_STATUS;
+            } else if (handshakeType == ht_supplemental_data) {
+                return RECORD_SUPPLIEMENTAL_DATA;
+            }
+
+            // otherwise, invalid record type
+            throw new IllegalArgumentException(
+                    "Invalid record type (ContentType:" + contentType +
+                    ", HandshakeType:" + handshakeType + ")");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ClientAuthType.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+/**
+ * Client authentication type.
+ */
+enum ClientAuthType {
+    CLIENT_AUTH_NONE,           // turn off client authentication
+    CLIENT_AUTH_REQUESTED,      // need to request client authentication
+    CLIENT_AUTH_REQUIRED        // require client authentication
+}
+
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Thu Jun 11 00:23:01 2015 +0200
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Thu Jun 11 00:51:11 2015 +0200
@@ -44,8 +44,6 @@
 
 import javax.net.ssl.*;
 
-import javax.security.auth.Subject;
-
 import sun.security.ssl.HandshakeMessage.*;
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
 
@@ -141,11 +139,20 @@
     private final static boolean allowUnsafeServerCertChange =
         Debug.getBooleanProperty("jdk.tls.allowUnsafeServerCertChange", false);
 
+    // To switch off the max_fragment_length extension.
+    private final static boolean enableMFLExtension =
+            Debug.getBooleanProperty("jsse.enableMFLExtension", false);
+
     private List<SNIServerName> requestedServerNames =
             Collections.<SNIServerName>emptyList();
 
+    // maximum fragment length
+    private int requestedMFLength = -1;     // -1: no fragment length limit
+
     private boolean serverNamesAccepted = false;
 
+    private ClientHello initialClientHelloMsg = null;   // DTLS only
+
     /*
      * the reserved server certificate chain in previous handshaking
      *
@@ -172,11 +179,12 @@
             ProtocolList enabledProtocols,
             ProtocolVersion activeProtocolVersion,
             boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
+            byte[] clientVerifyData, byte[] serverVerifyData,
+            boolean isDTLS) {
 
         super(engine, context, enabledProtocols, true, true,
             activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
+            clientVerifyData, serverVerifyData, isDTLS);
     }
 
     /*
@@ -191,29 +199,48 @@
      */
     @Override
     void processMessage(byte type, int messageLen) throws IOException {
-        if (state >= type
-                && (type != HandshakeMessage.ht_hello_request)) {
-            throw new SSLProtocolException(
-                    "Handshake message sequence violation, " + type);
-        }
+        // check the handshake state
+        handshakeState.check(type);
 
         switch (type) {
         case HandshakeMessage.ht_hello_request:
-            this.serverHelloRequest(new HelloRequest(input));
+            HelloRequest helloRequest = new HelloRequest(input);
+            handshakeState.update(helloRequest, resumingSession);
+            this.serverHelloRequest(helloRequest);
+            break;
+
+        case HandshakeMessage.ht_hello_verify_request:
+            if (!isDTLS) {
+                throw new SSLProtocolException(
+                    "hello_verify_request is not a SSL/TLS handshake message");
+            }
+
+            HelloVerifyRequest helloVerifyRequest =
+                        new HelloVerifyRequest(input, messageLen);
+            handshakeState.update(helloVerifyRequest, resumingSession);
+            this.helloVerifyRequest(helloVerifyRequest);
             break;
 
         case HandshakeMessage.ht_server_hello:
-            this.serverHello(new ServerHello(input, messageLen));
+            ServerHello serverHello = new ServerHello(input, messageLen);
+            this.serverHello(serverHello);
+
+            // This handshake state update needs the resumingSession value
+            // set by serverHello().
+            handshakeState.update(serverHello, resumingSession);
             break;
 
         case HandshakeMessage.ht_certificate:
             if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
-                    || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
+                    || ClientKeyExchangeService.find(keyExchange.name) != null) {
+                // No external key exchange provider needs a cert now.
                 fatalSE(Alerts.alert_unexpected_message,
                     "unexpected server cert chain");
                 // NOTREACHED
             }
-            this.serverCertificate(new CertificateMsg(input));
+            CertificateMsg certificateMsg = new CertificateMsg(input);
+            handshakeState.update(certificateMsg, resumingSession);
+            this.serverCertificate(certificateMsg);
             serverKey =
                 session.getPeerCertificates()[0].getPublicKey();
             break;
@@ -249,41 +276,52 @@
                 }
 
                 try {
-                    this.serverKeyExchange(new RSA_ServerKeyExchange(input));
+                    RSA_ServerKeyExchange rsaSrvKeyExchange =
+                                    new RSA_ServerKeyExchange(input);
+                    handshakeState.update(rsaSrvKeyExchange, resumingSession);
+                    this.serverKeyExchange(rsaSrvKeyExchange);
                 } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
+                    throw new SSLException("Server key", e);
                 }
                 break;
             case K_DH_ANON:
                 try {
-                    this.serverKeyExchange(new DH_ServerKeyExchange(
-                                                input, protocolVersion));
+                    DH_ServerKeyExchange dhSrvKeyExchange =
+                            new DH_ServerKeyExchange(input, protocolVersion);
+                    handshakeState.update(dhSrvKeyExchange, resumingSession);
+                    this.serverKeyExchange(dhSrvKeyExchange);
                 } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
+                    throw new SSLException("Server key", e);
                 }
                 break;
             case K_DHE_DSS:
             case K_DHE_RSA:
                 try {
-                    this.serverKeyExchange(new DH_ServerKeyExchange(
-                        input, serverKey,
-                        clnt_random.random_bytes, svr_random.random_bytes,
-                        messageLen,
-                        localSupportedSignAlgs, protocolVersion));
+                    DH_ServerKeyExchange dhSrvKeyExchange =
+                        new DH_ServerKeyExchange(
+                            input, serverKey,
+                            clnt_random.random_bytes, svr_random.random_bytes,
+                            messageLen,
+                            localSupportedSignAlgs, protocolVersion);
+                    handshakeState.update(dhSrvKeyExchange, resumingSession);
+                    this.serverKeyExchange(dhSrvKeyExchange);
                 } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
+                    throw new SSLException("Server key", e);
                 }
                 break;
             case K_ECDHE_ECDSA:
             case K_ECDHE_RSA:
             case K_ECDH_ANON:
                 try {
-                    this.serverKeyExchange(new ECDH_ServerKeyExchange
-                        (input, serverKey, clnt_random.random_bytes,
-                        svr_random.random_bytes,
-                        localSupportedSignAlgs, protocolVersion));
+                    ECDH_ServerKeyExchange ecdhSrvKeyExchange =
+                        new ECDH_ServerKeyExchange
+                            (input, serverKey, clnt_random.random_bytes,
+                            svr_random.random_bytes,
+                            localSupportedSignAlgs, protocolVersion);
+                    handshakeState.update(ecdhSrvKeyExchange, resumingSession);
+                    this.serverKeyExchange(ecdhSrvKeyExchange);
                 } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
+                    throw new SSLException("Server key", e);
                 }
                 break;
             case K_RSA:
@@ -294,13 +332,9 @@
                 throw new SSLProtocolException(
                     "Protocol violation: server sent a server key exchange"
                     + " message for key exchange " + keyExchange);
-            case K_KRB5:
-            case K_KRB5_EXPORT:
-                throw new SSLProtocolException(
-                    "unexpected receipt of server key exchange algorithm");
             default:
                 throw new SSLProtocolException(
-                    "unsupported key exchange algorithm = "
+                    "unsupported or unexpected key exchange algorithm = "
                     + keyExchange);
             }
             break;
@@ -311,17 +345,19 @@
                 throw new SSLHandshakeException(
                     "Client authentication requested for "+
                     "anonymous cipher suite.");
-            } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
+            } else if (ClientKeyExchangeService.find(keyExchange.name) != null) {
+                // No external key exchange provider needs a cert now.
                 throw new SSLHandshakeException(
                     "Client certificate requested for "+
-                    "kerberos cipher suite.");
+                    "external cipher suite: " + keyExchange);
             }
             certRequest = new CertificateRequest(input, protocolVersion);
             if (debug != null && Debug.isOn("handshake")) {
                 certRequest.print(System.out);
             }
+            handshakeState.update(certRequest, resumingSession);
 
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            if (protocolVersion.useTLS12PlusSpec()) {
                 Collection<SignatureAndHashAlgorithm> peerSignAlgs =
                                         certRequest.getSignAlgorithms();
                 if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
@@ -345,33 +381,24 @@
             break;
 
         case HandshakeMessage.ht_server_hello_done:
-            this.serverHelloDone(new ServerHelloDone(input));
+            ServerHelloDone serverHelloDone = new ServerHelloDone(input);
+            handshakeState.update(serverHelloDone, resumingSession);
+            this.serverHelloDone(serverHelloDone);
+
             break;
 
         case HandshakeMessage.ht_finished:
-            // A ChangeCipherSpec record must have been received prior to
-            // reception of the Finished message (RFC 5246, 7.4.9).
-            if (!receivedChangeCipherSpec()) {
-                fatalSE(Alerts.alert_handshake_failure,
-                    "Received Finished message before ChangeCipherSpec");
-            }
+            Finished serverFinished =
+                    new Finished(protocolVersion, input, cipherSuite);
+            handshakeState.update(serverFinished, resumingSession);
+            this.serverFinished(serverFinished);
 
-            this.serverFinished(
-                new Finished(protocolVersion, input, cipherSuite));
             break;
 
         default:
             throw new SSLProtocolException(
                 "Illegal client handshake msg, " + type);
         }
-
-        //
-        // Move state machine forward if the message handling
-        // code didn't already do so
-        //
-        if (state < type) {
-            state = type;
-        }
     }
 
     /*
@@ -389,10 +416,10 @@
         // Could be (e.g. at connection setup) that we already
         // sent the "client hello" but the server's not seen it.
         //
-        if (state < HandshakeMessage.ht_client_hello) {
+        if (!clientHelloDelivered) {
             if (!secureRenegotiation && !allowUnsafeRenegotiation) {
                 // renegotiation is not allowed.
-                if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
+                if (activeProtocolVersion.useTLS10PlusSpec()) {
                     // response with a no_renegotiation warning,
                     warningSE(Alerts.alert_no_renegotiation);
 
@@ -428,6 +455,29 @@
         }
     }
 
+    private void helloVerifyRequest(
+            HelloVerifyRequest mesg) throws IOException {
+
+        if (debug != null && Debug.isOn("handshake")) {
+            mesg.print(System.out);
+        }
+
+        //
+        // Note that HelloVerifyRequest.server_version is used solely to
+        // indicate packet formatting, and not as part of version negotiation.
+        // Need not to check version values match for HelloVerifyRequest
+        // message.
+        //
+        initialClientHelloMsg.cookie = mesg.cookie.clone();
+
+        if (debug != null && Debug.isOn("handshake")) {
+            initialClientHelloMsg.print(System.out);
+        }
+
+        // deliver the ClientHello message with cookie
+        initialClientHelloMsg.write(output);
+        handshakeState.update(initialClientHelloMsg, resumingSession);
+    }
 
     /*
      * Server chooses session parameters given options created by the
@@ -441,6 +491,9 @@
      * probably authentication getting done.
      */
     private void serverHello(ServerHello mesg) throws IOException {
+        // Dispose the reserved ClientHello message (if exists).
+        initialClientHelloMsg = null;
+
         serverKeyExchangeReceived = false;
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
@@ -536,7 +589,7 @@
         }
 
         setCipherSuite(mesg.cipherSuite);
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+        if (protocolVersion.useTLS12PlusSpec()) {
             handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
         }
 
@@ -569,51 +622,22 @@
                 }
 
                 // validate subject identity
-                if (sessionSuite.keyExchange == K_KRB5 ||
-                    sessionSuite.keyExchange == K_KRB5_EXPORT) {
+                ClientKeyExchangeService p =
+                        ClientKeyExchangeService.find(sessionSuite.keyExchange.name);
+                if (p != null) {
                     Principal localPrincipal = session.getLocalPrincipal();
 
-                    Subject subject = null;
-                    try {
-                        subject = AccessController.doPrivileged(
-                            new PrivilegedExceptionAction<Subject>() {
-                            @Override
-                            public Subject run() throws Exception {
-                                return Krb5Helper.getClientSubject(getAccSE());
-                            }});
-                    } catch (PrivilegedActionException e) {
-                        subject = null;
-                        if (debug != null && Debug.isOn("session")) {
-                            System.out.println("Attempt to obtain" +
-                                        " subject failed!");
-                        }
-                    }
-
-                    if (subject != null) {
-                        // Eliminate dependency on KerberosPrincipal
-                        Set<Principal> principals =
-                            subject.getPrincipals(Principal.class);
-                        if (!principals.contains(localPrincipal)) {
-                            throw new SSLProtocolException("Server resumed" +
-                                " session with wrong subject identity");
-                        } else {
-                            if (debug != null && Debug.isOn("session"))
-                                System.out.println("Subject identity is same");
-                        }
+                    if (p.isRelated(true, getAccSE(), localPrincipal)) {
+                        if (debug != null && Debug.isOn("session"))
+                            System.out.println("Subject identity is same");
                     } else {
-                        if (debug != null && Debug.isOn("session"))
-                            System.out.println("Kerberos credentials are not" +
-                                " present in the current Subject; check if " +
-                                " javax.security.auth.useSubjectAsCreds" +
-                                " system property has been set to false");
-                        throw new SSLProtocolException
-                            ("Server resumed session with no subject");
+                        throw new SSLProtocolException("Server resumed" +
+                                " session with wrong subject identity or no subject");
                     }
                 }
 
-                // looks fine; resume it, and update the state machine.
+                // looks fine; resume it.
                 resumingSession = true;
-                state = HandshakeMessage.ht_finished - 1;
                 calculateConnectionKeys(session.getMasterSecret());
                 if (debug != null && Debug.isOn("session")) {
                     System.out.println("%% Server resumed " + session);
@@ -627,6 +651,24 @@
             }
         }
 
+        // check the "max_fragment_length" extension
+        MaxFragmentLengthExtension maxFragLenExt = (MaxFragmentLengthExtension)
+                mesg.extensions.get(ExtensionType.EXT_MAX_FRAGMENT_LENGTH);
+        if (maxFragLenExt != null) {
+            if ((requestedMFLength == -1) ||
+                    maxFragLenExt.getMaxFragLen() != requestedMFLength) {
+                // If the client did not request this extension, or the
+                // response value is different from the length it requested,
+                // abort the handshake with a fatal illegal_parameter alert.
+                fatalSE(Alerts.alert_illegal_parameter,
+                        "Failed to negotiate the max_fragment_length");
+            }
+        } else if (!resumingSession) {
+            // no "max_fragment_length" extension
+            requestedMFLength = -1;
+        }   // Otherwise, using the value negotiated during the original
+            // session initiation
+
         if (resumingSession && session != null) {
             setHandshakeSessionSE(session);
             // Reserve the handshake state if this is a session-resumption
@@ -657,6 +699,8 @@
                             getLocalSupportedSignAlgs(),
                             mesg.sessionId, getHostSE(), getPortSE());
         session.setRequestedServerNames(requestedServerNames);
+        session.setNegotiatedMaxFragSize(requestedMFLength);
+        session.setMaximumPacketSize(maximumPacketSize);
         setHandshakeSessionSE(session);
         if (debug != null && Debug.isOn("handshake")) {
             System.out.println("** " + cipherSuite);
@@ -681,7 +725,6 @@
         ephemeralServerKey = mesg.getPublicKey();
     }
 
-
     /*
      * Diffie-Hellman key exchange.  We save the server public key and
      * our own D-H algorithm object so we can defer key calculations
@@ -716,13 +759,6 @@
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
-        /*
-         * Always make sure the input has been digested before we
-         * start emitting data, to ensure the hashes are correctly
-         * computed for the Finished and CertificateVerify messages
-         * which we send (here).
-         */
-        input.digestNow();
 
         /*
          * FIRST ... if requested, send an appropriate Certificate chain
@@ -817,7 +853,7 @@
                 // server.  For SSLv3, send the no_certificate alert;
                 // TLS uses an empty cert chain instead.
                 //
-                if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+                if (protocolVersion.useTLS10PlusSpec()) {
                     m1 = new CertificateMsg(new X509Certificate [0]);
                 } else {
                     warningSE(Alerts.alert_no_certificate);
@@ -837,6 +873,7 @@
                     m1.print(System.out);
                 }
                 m1.write(output);
+                handshakeState.update(m1, resumingSession);
             }
         }
 
@@ -943,8 +980,14 @@
             ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
             m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
             break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
+        default:
+            ClientKeyExchangeService p =
+                    ClientKeyExchangeService.find(keyExchange.name);
+            if (p == null) {
+                // somethings very wrong
+                throw new RuntimeException
+                        ("Unsupported key exchange: " + keyExchange);
+            }
             String sniHostname = null;
             for (SNIServerName serverName : requestedServerNames) {
                 if (serverName instanceof SNIHostName) {
@@ -953,13 +996,13 @@
                 }
             }
 
-            KerberosClientKeyExchange kerberosMsg = null;
+            ClientKeyExchange exMsg = null;
             if (sniHostname != null) {
                 // use first requested SNI hostname
                 try {
-                    kerberosMsg = new KerberosClientKeyExchange(
-                        sniHostname, getAccSE(), protocolVersion,
-                        sslContext.getSecureRandom());
+                    exMsg = p.createClientExchange(
+                            sniHostname, getAccSE(), protocolVersion,
+                            sslContext.getSecureRandom());
                 } catch(IOException e) {
                     if (serverNamesAccepted) {
                         // server accepted requested SNI hostname,
@@ -975,32 +1018,28 @@
                 }
             }
 
-            if (kerberosMsg == null) {
+            if (exMsg == null) {
                 String hostname = getHostSE();
                 if (hostname == null) {
                     throw new IOException("Hostname is required" +
-                        " to use Kerberos cipher suites");
+                        " to use " + keyExchange + " key exchange");
                 }
-                kerberosMsg = new KerberosClientKeyExchange(
-                     hostname, getAccSE(), protocolVersion,
-                     sslContext.getSecureRandom());
+                exMsg = p.createClientExchange(
+                        hostname, getAccSE(), protocolVersion,
+                        sslContext.getSecureRandom());
             }
 
             // Record the principals involved in exchange
-            session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
-            session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
-            m2 = kerberosMsg;
+            session.setPeerPrincipal(exMsg.getPeerPrincipal());
+            session.setLocalPrincipal(exMsg.getLocalPrincipal());
+            m2 = exMsg;
             break;
-        default:
-            // somethings very wrong
-            throw new RuntimeException
-                                ("Unsupported key exchange: " + keyExchange);
         }
         if (debug != null && Debug.isOn("handshake")) {
             m2.print(System.out);
         }
         m2.write(output);
-
+        handshakeState.update(m2, resumingSession);
 
         /*
          * THIRD, send a "change_cipher_spec" record followed by the
@@ -1010,8 +1049,6 @@
          * to compute the "Finished" message, and to compute the keys used
          * to protect all records following the change_cipher_spec.
          */
-
-        output.doHashes();
         output.flush();
 
         /*
@@ -1027,13 +1064,6 @@
         case K_RSA_EXPORT:
             preMasterSecret = ((RSAClientKeyExchange)m2).preMaster;
             break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            byte[] secretBytes =
-                ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
-            preMasterSecret = new SecretKeySpec(secretBytes,
-                "TlsPremasterSecret");
-            break;
         case K_DHE_RSA:
         case K_DHE_DSS:
         case K_DH_ANON:
@@ -1049,8 +1079,13 @@
             preMasterSecret = ecdh.getAgreedSecret(serverKey);
             break;
         default:
-            throw new IOException("Internal error: unknown key exchange "
-                + keyExchange);
+            if (ClientKeyExchangeService.find(keyExchange.name) != null) {
+                preMasterSecret =
+                        ((ClientKeyExchange) m2).clientKeyExchange();
+            } else {
+                throw new IOException("Internal error: unknown key exchange "
+                        + keyExchange);
+            }
         }
 
         calculateKeys(preMasterSecret, null);
@@ -1069,7 +1104,7 @@
             CertificateVerify m3;
             try {
                 SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (protocolVersion.useTLS12PlusSpec()) {
                     preferableSignatureAlgorithm =
                         SignatureAndHashAlgorithm.getPreferableAlgorithm(
                             peerSupportedSignAlgs, signingKey.getAlgorithm(),
@@ -1103,13 +1138,17 @@
                 m3.print(System.out);
             }
             m3.write(output);
-            output.doHashes();
+            handshakeState.update(m3, resumingSession);
+            output.flush();
         }
 
         /*
          * OK, that's that!
          */
         sendChangeCipherAndFinish(false);
+
+        // expecting the final ChangeCipherSpec and Finished messages
+        expectingFinishFlightSE();
     }
 
 
@@ -1158,8 +1197,9 @@
          * completed handshakes.
          */
         if (resumingSession) {
-            input.digestNow();
             sendChangeCipherAndFinish(true);
+        } else {
+            handshakeFinished = true;
         }
         session.setLastAccessedTime(System.currentTimeMillis());
 
@@ -1188,6 +1228,10 @@
      */
     private void sendChangeCipherAndFinish(boolean finishedTag)
             throws IOException {
+
+        // Reload if this message has been reserved.
+        handshakeHash.reload();
+
         Finished mesg = new Finished(protocolVersion, handshakeHash,
             Finished.CLIENT, session.getMasterSecret(), cipherSuite);
 
@@ -1205,13 +1249,6 @@
         if (secureRenegotiation) {
             clientVerifyData = mesg.getVerifyData();
         }
-
-        /*
-         * Update state machine so server MUST send 'finished' next.
-         * (In "long" handshake case; in short case, we're responding
-         * to its message.)
-         */
-        state = HandshakeMessage.ht_finished - 1;
     }
 
 
@@ -1361,10 +1398,10 @@
         // create the ClientHello message
         ClientHello clientHelloMessage = new ClientHello(
                 sslContext.getSecureRandom(), maxProtocolVersion,
-                sessionId, cipherSuites);
+                sessionId, cipherSuites, isDTLS);
 
         // add signature_algorithm extension
-        if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
+        if (maxProtocolVersion.useTLS12PlusSpec()) {
             // we will always send the signature_algorithm extension
             Collection<SignatureAndHashAlgorithm> localSignAlgs =
                                                 getLocalSupportedSignAlgs();
@@ -1389,6 +1426,37 @@
             }
         }
 
+        // add max_fragment_length extension
+        if (enableMFLExtension) {
+            if (session != null) {
+                // The same extension should be sent for resumption.
+                requestedMFLength = session.getNegotiatedMaxFragSize();
+            } else if (maximumPacketSize != 0) {
+                // Maybe we can calculate the fragment size more accurate
+                // by condering the enabled cipher suites in the future.
+                requestedMFLength = maximumPacketSize;
+                if (isDTLS) {
+                    requestedMFLength -= DTLSRecord.maxPlaintextPlusSize;
+                } else {
+                    requestedMFLength -= SSLRecord.maxPlaintextPlusSize;
+                }
+            } else {
+                // Need no max_fragment_length extension.
+                requestedMFLength = -1;
+            }
+
+            if ((requestedMFLength > 0) &&
+                MaxFragmentLengthExtension.needFragLenNego(requestedMFLength)) {
+
+                requestedMFLength =
+                        MaxFragmentLengthExtension.getValidMaxFragLen(
+                                                        requestedMFLength);
+                clientHelloMessage.addMFLExtension(requestedMFLength);
+            } else {
+                requestedMFLength = -1;
+            }
+        }
+
         // reset the client random cookie
         clnt_random = clientHelloMessage.clnt_random;
 
@@ -1403,6 +1471,11 @@
             clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
         }
 
+        if (isDTLS) {
+            // Cookie exchange need to reserve the initial ClientHello message.
+            initialClientHelloMsg = clientHelloMessage;
+        }
+
         return clientHelloMessage;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ClientKeyExchange.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import javax.crypto.SecretKey;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.security.Principal;
+
+/**
+ * Models a non-certificate based ClientKeyExchange
+ */
+public abstract class ClientKeyExchange extends HandshakeMessage {
+
+    public ClientKeyExchange() {
+    }
+
+    @Override
+    int messageType() {
+        return ht_client_key_exchange;
+    }
+
+    @Override
+    abstract public int messageLength();
+
+    @Override
+    abstract public void send(HandshakeOutStream s) throws IOException;
+
+    @Override
+    abstract public void print(PrintStream s) throws IOException;
+
+    abstract public SecretKey clientKeyExchange();
+
+    abstract public Principal getPeerPrincipal();
+
+    abstract public Principal getLocalPrincipal();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import sun.security.action.GetPropertyAction;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.SecureRandom;
+import java.util.*;
+
+/**
+ * Models a service that provides support for a particular client key exchange
+ * mode. Currently used to implement Kerberos-related cipher suites.
+ *
+ * @since 1.9
+ */
+public interface ClientKeyExchangeService {
+
+    static class Loader {
+        private static final Map<String,ClientKeyExchangeService>
+                providers = new HashMap<>();
+
+        static {
+            final String key = "java.home";
+            String path = AccessController.doPrivileged(
+                    new GetPropertyAction(key), null,
+                    new PropertyPermission(key, "read"));
+            ServiceLoader<ClientKeyExchangeService> sc =
+                    AccessController.doPrivileged(
+                            (PrivilegedAction<ServiceLoader<ClientKeyExchangeService>>)
+                                    () -> ServiceLoader.loadInstalled(ClientKeyExchangeService.class),
+                            null,
+                            new FilePermission(new File(path, "-").toString(), "read"));
+            Iterator<ClientKeyExchangeService> iter = sc.iterator();
+            while (iter.hasNext()) {
+                ClientKeyExchangeService cs = iter.next();
+                for (String ex: cs.supported()) {
+                    providers.put(ex, cs);
+                }
+            }
+        }
+
+    }
+
+    public static ClientKeyExchangeService find(String ex) {
+        return Loader.providers.get(ex);
+    }
+
+
+    /**
+     * Returns the supported key exchange modes by this provider.
+     * @return the supported key exchange modes
+     */
+    String[] supported();
+
+    /**
+     * Returns a generalized credential object on the server side. The server
+     * side can use the info to determine if a cipher suite can be enabled.
+     * @param acc the AccessControlContext of the SSL session
+     * @return the credential object
+     */
+    Object getServiceCreds(AccessControlContext acc);
+
+    /**
+     * Returns the host name for a service principal. The info can be used in
+     * SNI or host name verifier.
+     * @param principal the principal of a service
+     * @return the string formed host name
+     */
+    String getServiceHostName(Principal principal);
+
+    /**
+     * Returns whether the specified principal is related to the current
+     * SSLSession. The info can be used to verify a SSL resume.
+     * @param isClient if true called from client side, otherwise from server
+     * @param acc the AccessControlContext of the SSL session
+     * @param p the specified principal
+     * @return true if related
+     */
+    boolean isRelated(boolean isClient, AccessControlContext acc, Principal p);
+
+    /**
+     * Creates the ClientKeyExchange object on the client side.
+     * @param serverName the intented peer name
+     * @param acc the AccessControlContext of the SSL session
+     * @param protocolVersion the TLS protocol version
+     * @param rand the SecureRandom that will used to generate the premaster
+     * @return the new Exchanger object
+     * @throws IOException if there is an error
+     */
+    ClientKeyExchange createClientExchange(String serverName, AccessControlContext acc,
+            ProtocolVersion protocolVersion, SecureRandom rand) throws IOException;
+
+    /**
+     * Create the ClientKeyExchange on the server side.
+     * @param protocolVersion the protocol version
+     * @param clientVersion the input protocol version
+     * @param rand a SecureRandom object used to generate premaster
+     *             (if the server has to create one)
+     * @param encodedTicket the ticket from client
+     * @param encrypted the encrypted premaster secret from client
+     * @param acc the AccessControlContext of the SSL session
+     * @param ServiceCreds the service side credentials object as retrived from
+     *                     {@link #getServiceCreds}
+     * @return the new Exchanger object
+     * @throws IOException if there is an error
+     */
+    ClientKeyExchange createServerExchange(
+            ProtocolVersion protocolVersion, ProtocolVersion clientVersion,
+            SecureRandom rand, byte[] encodedTicket, byte[] encrypted,
+            AccessControlContext acc, Object ServiceCreds) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+import javax.crypto.BadPaddingException;
+
+import javax.net.ssl.*;
+
+import sun.misc.HexDumpEncoder;
+import static sun.security.ssl.HandshakeMessage.*;
+
+/**
+ * DTLS {@code InputRecord} implementation for {@code SSLEngine}.
+ */
+final class DTLSInputRecord extends InputRecord implements DTLSRecord {
+
+    private DTLSReassembler reassembler = null;
+
+    // Cache the session identifier for the detection of session-resuming
+    // handshake.
+    byte[]              prevSessionID = new byte[0];
+
+    int                 readEpoch;
+
+    int                 prevReadEpoch;
+    Authenticator       prevReadAuthenticator;
+    CipherBox           prevReadCipher;
+
+    DTLSInputRecord() {
+        this.readEpoch = 0;
+        this.readAuthenticator = new MAC(true);
+
+        this.prevReadEpoch = 0;
+        this.prevReadCipher = CipherBox.NULL;
+        this.prevReadAuthenticator = new MAC(true);
+    }
+
+    @Override
+    void changeReadCiphers(Authenticator readAuthenticator,
+            CipherBox readCipher) {
+
+        prevReadCipher.dispose();
+
+        this.prevReadAuthenticator = this.readAuthenticator;
+        this.prevReadCipher = this.readCipher;
+        this.prevReadEpoch = this.readEpoch;
+
+        this.readAuthenticator = readAuthenticator;
+        this.readCipher = readCipher;
+        this.readEpoch++;
+    }
+
+    @Override
+    synchronized public void close() throws IOException {
+        if (!isClosed) {
+            prevReadCipher.dispose();
+            super.close();
+        }
+    }
+
+    @Override
+    boolean isEmpty() {
+        return ((reassembler == null) || reassembler.isEmpty());
+    }
+
+    @Override
+    int estimateFragmentSize(int packetSize) {
+        int macLen = 0;
+        if (readAuthenticator instanceof MAC) {
+            macLen = ((MAC)readAuthenticator).MAClen();
+        }
+
+        if (packetSize > 0) {
+            return readCipher.estimateFragmentSize(
+                    packetSize, macLen, headerSize);
+        } else {
+            return Record.maxDataSize;
+        }
+    }
+
+    @Override
+    void expectingFinishFlight() {
+        if (reassembler != null) {
+            reassembler.expectingFinishFlight();
+        }
+    }
+
+    @Override
+    Plaintext acquirePlaintext() {
+        if (reassembler != null) {
+            Plaintext plaintext = reassembler.acquirePlaintext();
+            if (reassembler.finished()) {
+                // discard all buffered unused message.
+                reassembler = null;
+            }
+
+            return plaintext;
+        }
+
+        return null;
+    }
+
+    @Override
+    Plaintext decode(ByteBuffer packet) {
+
+        if (isClosed) {
+            return null;
+        }
+
+        if (debug != null && Debug.isOn("packet")) {
+             Debug.printHex(
+                    "[Raw read]: length = " + packet.remaining(), packet);
+        }
+
+        // The caller should have validated the record.
+        int srcPos = packet.position();
+        int srcLim = packet.limit();
+
+        byte contentType = packet.get();                   // pos: 0
+        byte majorVersion = packet.get();                  // pos: 1
+        byte minorVersion = packet.get();                  // pos: 2
+        byte[] recordEnS = new byte[8];                    // epoch + seqence
+        packet.get(recordEnS);
+        int recordEpoch = ((recordEnS[0] & 0xFF) << 8) |
+                           (recordEnS[1] & 0xFF);          // pos: 3, 4
+        long recordSeq  = Authenticator.toLong(recordEnS);
+        int contentLen = ((packet.get() & 0xFF) << 8) |
+                          (packet.get() & 0xFF);            // pos: 11, 12
+
+        if (debug != null && Debug.isOn("record")) {
+             System.out.println(Thread.currentThread().getName() +
+                    ", READ: " +
+                    ProtocolVersion.valueOf(majorVersion, minorVersion) +
+                    " " + Record.contentName(contentType) + ", length = " +
+                    contentLen);
+        }
+
+        int recLim = srcPos + DTLSRecord.headerSize + contentLen;
+        if (this.readEpoch > recordEpoch) {
+            // Discard old records delivered before this epoch.
+
+            // Reset the position of the packet buffer.
+            packet.position(recLim);
+            return null;
+        }
+
+        if (this.readEpoch < recordEpoch) {
+            if (contentType != Record.ct_handshake) {
+                // just discard it if not a handshake message
+                packet.position(recLim);
+                return null;
+            }
+
+            // Not ready to decrypt this record, may be encrypted Finished
+            // message, need to buffer it.
+            if (reassembler == null) {
+               reassembler = new DTLSReassembler();
+            }
+
+            byte[] fragment = new byte[contentLen];
+            packet.get(fragment);              // copy the fragment
+            RecordFragment buffered = new RecordFragment(fragment, contentType,
+                    majorVersion, minorVersion,
+                    recordEnS, recordEpoch, recordSeq, true);
+
+            reassembler.queueUpFragment(buffered);
+
+            // consume the full record in the packet buffer.
+            packet.position(recLim);
+
+            Plaintext plaintext = reassembler.acquirePlaintext();
+            if (reassembler.finished()) {
+                // discard all buffered unused message.
+                reassembler = null;
+            }
+
+            return plaintext;
+        }
+
+        if (this.readEpoch == recordEpoch) {
+            // decrypt the fragment
+            packet.limit(recLim);
+            packet.position(srcPos + DTLSRecord.headerSize);
+
+            ByteBuffer plaintextFragment;
+            try {
+                plaintextFragment = decrypt(readAuthenticator,
+                        readCipher, contentType, packet, recordEnS);
+            } catch (BadPaddingException bpe) {
+                if (debug != null && Debug.isOn("ssl")) {
+                    System.out.println(Thread.currentThread().getName() +
+                            " discard invalid record: " + bpe);
+                }
+
+                // invalid, discard this record [section 4.1.2.7, RFC 6347]
+                return null;
+            } finally {
+                // comsume a complete record
+                packet.limit(srcLim);
+                packet.position(recLim);
+            }
+
+            if (contentType != Record.ct_change_cipher_spec &&
+                contentType != Record.ct_handshake) {   // app data or alert
+                                                        // no retransmission
+               return new Plaintext(contentType, majorVersion, minorVersion,
+                        recordEpoch, recordSeq, plaintextFragment);
+            }
+
+            if (contentType == Record.ct_change_cipher_spec) {
+                if (reassembler == null) {
+                    // handshake has not started, should be an
+                    // old handshake message, discard it.
+                    return null;
+                }
+
+                reassembler.queueUpFragment(
+                        new RecordFragment(plaintextFragment, contentType,
+                                majorVersion, minorVersion,
+                                recordEnS, recordEpoch, recordSeq, false));
+            } else {    // handshake record
+                // One record may contain 1+ more handshake messages.
+                while (plaintextFragment.remaining() > 0) {
+
+                    HandshakeFragment hsFrag = parseHandshakeMessage(
+                        contentType, majorVersion, minorVersion,
+                        recordEnS, recordEpoch, recordSeq, plaintextFragment);
+
+                    if (hsFrag == null) {
+                        // invalid, discard this record
+                        return null;
+                    }
+
+                    if ((reassembler == null) &&
+                            isKickstart(hsFrag.handshakeType)) {
+                       reassembler = new DTLSReassembler();
+                    }
+
+                    if (reassembler != null) {
+                        reassembler.queueUpHandshake(hsFrag);
+                    }   // else, just ignore the message.
+                }
+            }
+
+            // Completed the read of the full record. Acquire the reassembled
+            // messages.
+            if (reassembler != null) {
+                Plaintext plaintext = reassembler.acquirePlaintext();
+                if (reassembler.finished()) {
+                    // discard all buffered unused message.
+                    reassembler = null;
+                }
+
+                return plaintext;
+            }
+        }
+
+        return null;    // make the complier happy
+    }
+
+    @Override
+    int bytesInCompletePacket(ByteBuffer packet) throws SSLException {
+
+        // DTLS length field is in bytes 11/12
+        if (packet.remaining() < headerSize) {
+            return -1;
+        }
+
+        // Last sanity check that it's not a wild record
+        int pos = packet.position();
+
+        // Check the content type of the record.
+        byte contentType = packet.get(pos);
+        if (!Record.isValidContentType(contentType)) {
+            throw new SSLException(
+                    "Unrecognized SSL message, plaintext connection?");
+        }
+
+        // Check the protocol version of the record.
+        ProtocolVersion recordVersion =
+            ProtocolVersion.valueOf(packet.get(pos + 1), packet.get(pos + 2));
+        checkRecordVersion(recordVersion, false);
+
+        // Get the fragment length of the record.
+        int fragLen = ((packet.get(pos + 11) & 0xFF) << 8) +
+                       (packet.get(pos + 12) & 0xFF) + headerSize;
+        if (fragLen > Record.maxFragmentSize) {
+            throw new SSLException(
+                    "Record overflow, fragment length (" + fragLen +
+                    ") MUST not exceed " + Record.maxFragmentSize);
+        }
+
+        return fragLen;
+    }
+
+    @Override
+    void checkRecordVersion(ProtocolVersion recordVersion,
+            boolean allowSSL20Hello) throws SSLException {
+
+        if (!recordVersion.maybeDTLSProtocol()) {
+            throw new SSLException(
+                    "Unrecognized record version " + recordVersion +
+                    " , plaintext connection?");
+        }
+    }
+
+    private static boolean isKickstart(byte handshakeType) {
+        return (handshakeType == HandshakeMessage.ht_client_hello) ||
+               (handshakeType == HandshakeMessage.ht_hello_request) ||
+               (handshakeType == HandshakeMessage.ht_hello_verify_request);
+    }
+
+    private static HandshakeFragment parseHandshakeMessage(
+            byte contentType, byte majorVersion, byte minorVersion,
+            byte[] recordEnS, int recordEpoch, long recordSeq,
+            ByteBuffer plaintextFragment) {
+
+        int remaining = plaintextFragment.remaining();
+        if (remaining < handshakeHeaderSize) {
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(
+                        Thread.currentThread().getName() +
+                        " discard invalid record: " +
+                        "too small record to hold a handshake fragment");
+            }
+
+            // invalid, discard this record [section 4.1.2.7, RFC 6347]
+            return null;
+        }
+
+        byte handshakeType = plaintextFragment.get();       // pos: 0
+        int messageLength =
+                ((plaintextFragment.get() & 0xFF) << 16) |
+                ((plaintextFragment.get() & 0xFF) << 8) |
+                 (plaintextFragment.get() & 0xFF);          // pos: 1-3
+        int messageSeq =
+                ((plaintextFragment.get() & 0xFF) << 8) |
+                 (plaintextFragment.get() & 0xFF);          // pos: 4/5
+        int fragmentOffset =
+                ((plaintextFragment.get() & 0xFF) << 16) |
+                ((plaintextFragment.get() & 0xFF) << 8) |
+                 (plaintextFragment.get() & 0xFF);          // pos: 6-8
+        int fragmentLength =
+                ((plaintextFragment.get() & 0xFF) << 16) |
+                ((plaintextFragment.get() & 0xFF) << 8) |
+                 (plaintextFragment.get() & 0xFF);          // pos: 9-11
+        if ((remaining - handshakeHeaderSize) < fragmentLength) {
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(
+                        Thread.currentThread().getName() +
+                        " discard invalid record: " +
+                        "not a complete handshake fragment in the record");
+            }
+
+            // invalid, discard this record [section 4.1.2.7, RFC 6347]
+            return null;
+        }
+
+        byte[] fragment = new byte[fragmentLength];
+        plaintextFragment.get(fragment);
+
+        return new HandshakeFragment(fragment, contentType,
+                majorVersion, minorVersion,
+                recordEnS, recordEpoch, recordSeq,
+                handshakeType, messageLength,
+                messageSeq, fragmentOffset, fragmentLength);
+    }
+
+    // buffered record fragment
+    private static class RecordFragment implements Comparable<RecordFragment> {
+        boolean         isCiphertext;
+
+        byte            contentType;
+        byte            majorVersion;
+        byte            minorVersion;
+        int             recordEpoch;
+        long            recordSeq;
+        byte[]          recordEnS;
+        byte[]          fragment;
+
+        RecordFragment(ByteBuffer fragBuf, byte contentType,
+                byte majorVersion, byte minorVersion, byte[] recordEnS,
+                int recordEpoch, long recordSeq, boolean isCiphertext) {
+            this((byte[])null, contentType, majorVersion, minorVersion,
+                    recordEnS, recordEpoch, recordSeq, isCiphertext);
+
+            this.fragment = new byte[fragBuf.remaining()];
+            fragBuf.get(this.fragment);
+        }
+
+        RecordFragment(byte[] fragment, byte contentType,
+                byte majorVersion, byte minorVersion, byte[] recordEnS,
+                int recordEpoch, long recordSeq, boolean isCiphertext) {
+            this.isCiphertext = isCiphertext;
+
+            this.contentType = contentType;
+            this.majorVersion = majorVersion;
+            this.minorVersion = minorVersion;
+            this.recordEpoch = recordEpoch;
+            this.recordSeq = recordSeq;
+            this.recordEnS = recordEnS;
+            this.fragment = fragment;       // The caller should have cloned
+                                            // the buffer if necessary.
+        }
+
+        @Override
+        public int compareTo(RecordFragment o) {
+            return Long.compareUnsigned(this.recordSeq, o.recordSeq);
+        }
+    }
+
+    // buffered handshake message
+    private static final class HandshakeFragment extends RecordFragment {
+
+        byte            handshakeType;     // handshake msg_type
+        int             messageSeq;        // message_seq
+        int             messageLength;     // Handshake body length
+        int             fragmentOffset;    // fragment_offset
+        int             fragmentLength;    // fragment_length
+
+        HandshakeFragment(byte[] fragment, byte contentType,
+                byte majorVersion, byte minorVersion, byte[] recordEnS,
+                int recordEpoch, long recordSeq,
+                byte handshakeType, int messageLength,
+                int messageSeq, int fragmentOffset, int fragmentLength) {
+
+            super(fragment, contentType, majorVersion, minorVersion,
+                    recordEnS, recordEpoch , recordSeq, false);
+
+            this.handshakeType = handshakeType;
+            this.messageSeq = messageSeq;
+            this.messageLength = messageLength;
+            this.fragmentOffset = fragmentOffset;
+            this.fragmentLength = fragmentLength;
+        }
+
+        @Override
+        public int compareTo(RecordFragment o) {
+            if (o instanceof HandshakeFragment) {
+                HandshakeFragment other = (HandshakeFragment)o;
+                if (this.messageSeq != other.messageSeq) {
+                    // keep the insertion order for the same message
+                    return this.messageSeq - other.messageSeq;
+                }
+            }
+
+            return Long.compareUnsigned(this.recordSeq, o.recordSeq);
+        }
+    }
+
+    private static final class HoleDescriptor {
+        int offset;             // fragment_offset
+        int limit;              // fragment_offset + fragment_length
+
+        HoleDescriptor(int offset, int limit) {
+            this.offset = offset;
+            this.limit = limit;
+        }
+    }
+
+    final class DTLSReassembler {
+        TreeSet<RecordFragment> bufferedFragments = new TreeSet<>();
+
+        HashMap<Byte, List<HoleDescriptor>> holesMap = new HashMap<>(5);
+
+        // Epoch, sequence number and handshake message sequence of the
+        // beginning message of a flight.
+        byte        flightType = (byte)0xFF;
+
+        int         flightTopEpoch = 0;
+        long        flightTopRecordSeq = -1;
+        int         flightTopMessageSeq = 0;
+
+        // Epoch, sequence number and handshake message sequence of the
+        // next message acquisition of a flight.
+        int         nextRecordEpoch = 0;    // next record epoch
+        long        nextRecordSeq = 0;      // next record sequence number
+        int         nextMessageSeq = 0;     // next handshake message number
+
+        // Expect ChangeCipherSpec and Finished messages for the final flight.
+        boolean     expectCCSFlight = false;
+
+        // Ready to process this flight if received all messages of the flight.
+        boolean     flightIsReady = false;
+        boolean     needToCheckFlight = false;
+
+        // Is it a session-resuming abbreviated handshake.?
+        boolean     isAbbreviatedHandshake = false;
+
+        // The handshke fragment with the biggest record sequence number
+        // in a flight, not counting the Finished message.
+        HandshakeFragment lastHandshakeFragment = null;
+
+        // Is handshake (intput) finished?
+        boolean handshakeFinished = false;
+
+        DTLSReassembler() {
+            // blank
+        }
+
+        boolean finished() {
+            return handshakeFinished;
+        }
+
+        void expectingFinishFlight() {
+            expectCCSFlight = true;
+        }
+
+        void queueUpHandshake(HandshakeFragment hsf) {
+
+            if ((nextRecordEpoch > hsf.recordEpoch) ||
+                    (nextRecordSeq > hsf.recordSeq) ||
+                    (nextMessageSeq > hsf.messageSeq)) {
+                // too old, discard this record
+                return;
+            }
+
+            // Is it the first message of next flight?
+            if ((flightTopMessageSeq == hsf.messageSeq) &&
+                    (hsf.fragmentOffset == 0) && (flightTopRecordSeq == -1)) {
+
+                flightType = hsf.handshakeType;
+                flightTopEpoch = hsf.recordEpoch;
+                flightTopRecordSeq = hsf.recordSeq;
+
+                if (hsf.handshakeType == HandshakeMessage.ht_server_hello) {
+                    // Is it a session-resuming handshake?
+                    try {
+                        isAbbreviatedHandshake =
+                                isSessionResuming(hsf.fragment, prevSessionID);
+                    } catch (SSLException ssle) {
+                        if (debug != null && Debug.isOn("ssl")) {
+                            System.out.println(
+                                    Thread.currentThread().getName() +
+                                    " discard invalid record: " + ssle);
+                        }
+
+                        // invalid, discard it [section 4.1.2.7, RFC 6347]
+                        return;
+                    }
+
+                    if (!isAbbreviatedHandshake) {
+                        prevSessionID = getSessionID(hsf.fragment);
+                    }
+                }
+            }
+
+            boolean fragmented = false;
+            if ((hsf.fragmentOffset) != 0 ||
+                (hsf.fragmentLength != hsf.messageLength)) {
+
+                fragmented = true;
+            }
+
+            List<HoleDescriptor> holes = holesMap.get(hsf.handshakeType);
+            if (holes == null) {
+                if (!fragmented) {
+                    holes = Collections.emptyList();
+                } else {
+                    holes = new LinkedList<HoleDescriptor>();
+                    holes.add(new HoleDescriptor(0, hsf.messageLength));
+                }
+                holesMap.put(hsf.handshakeType, holes);
+            } else if (holes.isEmpty()) {
+                // Have got the full handshake message.  This record may be
+                // a handshake message retransmission.  Discard this record.
+                //
+                // It's OK to discard retransmission as the handshake hash
+                // is computed as if each handshake message had been sent
+                // as a single fragment.
+                //
+                // Note that ClientHello messages are delivered twice in
+                // DTLS handshaking.
+                if ((hsf.handshakeType != HandshakeMessage.ht_client_hello &&
+                     hsf.handshakeType != ht_hello_verify_request) ||
+                        (nextMessageSeq != hsf.messageSeq)) {
+                    return;
+                }
+
+                if (fragmented) {
+                    holes = new LinkedList<HoleDescriptor>();
+                    holes.add(new HoleDescriptor(0, hsf.messageLength));
+                }
+                holesMap.put(hsf.handshakeType, holes);
+            }
+
+            if (fragmented) {
+                int fragmentLimit = hsf.fragmentOffset + hsf.fragmentLength;
+                for (int i = 0; i < holes.size(); i++) {
+
+                    HoleDescriptor hole = holes.get(i);
+                    if ((hole.limit <= hsf.fragmentOffset) ||
+                        (hole.offset >= fragmentLimit)) {
+                        // Also discard overlapping handshake retransmissions.
+                        continue;
+                    }
+
+                    // The ranges SHOULD NOT overlap.
+                    if (((hole.offset > hsf.fragmentOffset) &&
+                         (hole.offset < fragmentLimit)) ||
+                        ((hole.limit > hsf.fragmentOffset) &&
+                         (hole.limit < fragmentLimit))) {
+
+                        if (debug != null && Debug.isOn("ssl")) {
+                            System.out.println(
+                                Thread.currentThread().getName() +
+                                " discard invalid record: " +
+                                "handshake fragment ranges are overlapping");
+                        }
+
+                        // invalid, discard it [section 4.1.2.7, RFC 6347]
+                        return;
+                    }
+
+                    // This record interacts with this hole, fill the hole.
+                    holes.remove(i);
+                    // i--;
+
+                    if (hsf.fragmentOffset > hole.offset) {
+                        holes.add(new HoleDescriptor(
+                                hole.offset, hsf.fragmentOffset));
+                        // i++;
+                    }
+
+                    if (fragmentLimit < hole.limit) {
+                        holes.add(new HoleDescriptor(
+                                fragmentLimit, hole.limit));
+                        // i++;
+                    }
+
+                    // As no ranges overlap, no interact with other holes.
+                    break;
+                }
+            }
+
+            // append this fragment
+            bufferedFragments.add(hsf);
+
+            if ((lastHandshakeFragment == null) ||
+                (lastHandshakeFragment.compareTo(hsf) < 0)) {
+
+                lastHandshakeFragment = hsf;
+            }
+
+            if (flightIsReady) {
+                flightIsReady = false;
+            }
+            needToCheckFlight = true;
+        }
+
+        // queue up change_cipher_spec or encrypted message
+        void queueUpFragment(RecordFragment rf) {
+            if ((nextRecordEpoch > rf.recordEpoch) ||
+                    (nextRecordSeq > rf.recordSeq)) {
+                // too old, discard this record
+                return;
+            }
+
+            // Is it the first message of next flight?
+            if (expectCCSFlight &&
+                    (rf.contentType == Record.ct_change_cipher_spec)) {
+
+                flightType = (byte)0xFE;
+                flightTopEpoch = rf.recordEpoch;
+                flightTopRecordSeq = rf.recordSeq;
+            }
+
+            // append this fragment
+            bufferedFragments.add(rf);
+
+            if (flightIsReady) {
+                flightIsReady = false;
+            }
+            needToCheckFlight = true;
+        }
+
+        boolean isEmpty() {
+            return (bufferedFragments.isEmpty() ||
+                    (!flightIsReady && !needToCheckFlight) ||
+                    (needToCheckFlight && !flightIsReady()));
+        }
+
+        Plaintext acquirePlaintext() {
+            if (bufferedFragments.isEmpty()) {
+                // reset the flight
+                if (flightIsReady) {
+                    flightIsReady = false;
+                    needToCheckFlight = false;
+                }
+
+                return null;
+            }
+
+            if (!flightIsReady && needToCheckFlight) {
+                // check the fligth status
+                flightIsReady = flightIsReady();
+
+                // set for next flight
+                if (flightIsReady) {
+                    flightTopMessageSeq = lastHandshakeFragment.messageSeq + 1;
+                    flightTopRecordSeq = -1;
+                }
+
+                needToCheckFlight = false;
+            }
+
+            if (!flightIsReady) {
+                return null;
+            }
+
+            RecordFragment rFrag = bufferedFragments.first();
+            if (!rFrag.isCiphertext) {
+                // handshake message, or ChangeCipherSpec message
+                return acquireHandshakeMessage();
+            } else {
+                // a Finished message or other ciphertexts
+                return acquireCachedMessage();
+            }
+        }
+
+        private Plaintext acquireCachedMessage() {
+
+            RecordFragment rFrag = bufferedFragments.first();
+            if (readEpoch != rFrag.recordEpoch) {
+                if (readEpoch > rFrag.recordEpoch) {
+                    // discard old records
+                    bufferedFragments.remove(rFrag);    // popup the fragment
+                }
+
+                // reset the flight
+                if (flightIsReady) {
+                    flightIsReady = false;
+                }
+                return null;
+            }
+
+            bufferedFragments.remove(rFrag);    // popup the fragment
+
+            ByteBuffer fragment = ByteBuffer.wrap(rFrag.fragment);
+            ByteBuffer plaintextFragment = null;
+            try {
+                plaintextFragment = decrypt(readAuthenticator, readCipher,
+                        rFrag.contentType, fragment, rFrag.recordEnS);
+            } catch (BadPaddingException bpe) {
+                if (debug != null && Debug.isOn("ssl")) {
+                    System.out.println(Thread.currentThread().getName() +
+                            " discard invalid record: " + bpe);
+                }
+
+                // invalid, discard this record [section 4.1.2.7, RFC 6347]
+                return null;
+            }
+
+            // The ciphtext handshake message can only be Finished (the
+            // end of this flight), ClinetHello or HelloRequest (the
+            // beginning of the next flight) message.  Need not to check
+            // any ChangeCipherSpec message.
+            if (rFrag.contentType == Record.ct_handshake) {
+                HandshakeFragment finFrag = null;
+                while (plaintextFragment.remaining() > 0) {
+                    HandshakeFragment hsFrag = parseHandshakeMessage(
+                            rFrag.contentType,
+                            rFrag.majorVersion, rFrag.minorVersion,
+                            rFrag.recordEnS, rFrag.recordEpoch, rFrag.recordSeq,
+                            plaintextFragment);
+
+                    if (hsFrag == null) {
+                        // invalid, discard this record
+                        return null;
+                    }
+
+                    if (hsFrag.handshakeType == HandshakeMessage.ht_finished) {
+                        finFrag = hsFrag;
+
+                        // reset for the next flight
+                        this.flightType = (byte)0xFF;
+                        this.flightTopEpoch = rFrag.recordEpoch;
+                        this.flightTopMessageSeq = hsFrag.messageSeq + 1;
+                        this.flightTopRecordSeq = -1;
+                    } else {
+                        // reset the flight
+                        if (flightIsReady) {
+                            flightIsReady = false;
+                        }
+                        queueUpHandshake(hsFrag);
+                    }
+                }
+
+                this.nextRecordSeq = rFrag.recordSeq + 1;
+                this.nextMessageSeq = 0;
+
+                if (finFrag != null) {
+                    this.nextRecordEpoch = finFrag.recordEpoch;
+                    this.nextRecordSeq = finFrag.recordSeq + 1;
+                    this.nextMessageSeq = finFrag.messageSeq + 1;
+
+                    // Finished message does not fragment.
+                    byte[] recordFrag = new byte[finFrag.messageLength + 4];
+                    Plaintext plaintext = new Plaintext(finFrag.contentType,
+                            finFrag.majorVersion, finFrag.minorVersion,
+                            finFrag.recordEpoch, finFrag.recordSeq,
+                            ByteBuffer.wrap(recordFrag));
+
+                    // fill the handshake fragment of the record
+                    recordFrag[0] = finFrag.handshakeType;
+                    recordFrag[1] =
+                            (byte)((finFrag.messageLength >>> 16) & 0xFF);
+                    recordFrag[2] =
+                            (byte)((finFrag.messageLength >>> 8) & 0xFF);
+                    recordFrag[3] = (byte)(finFrag.messageLength & 0xFF);
+
+                    System.arraycopy(finFrag.fragment, 0,
+                            recordFrag, 4, finFrag.fragmentLength);
+
+                    // handshake hashing
+                    handshakeHashing(finFrag, plaintext);
+
+                    // input handshake finished
+                    handshakeFinished = true;
+
+                    return plaintext;
+                } else {
+                    return acquirePlaintext();
+                }
+            } else {
+                return new Plaintext(rFrag.contentType,
+                        rFrag.majorVersion, rFrag.minorVersion,
+                        rFrag.recordEpoch, rFrag.recordSeq,
+                        plaintextFragment);
+            }
+        }
+
+        private Plaintext acquireHandshakeMessage() {
+
+            RecordFragment rFrag = bufferedFragments.first();
+            if (rFrag.contentType == Record.ct_change_cipher_spec) {
+                this.nextRecordEpoch = rFrag.recordEpoch + 1;
+                this.nextRecordSeq = 0;
+                // no change on next handshake message sequence number
+
+                bufferedFragments.remove(rFrag);        // popup the fragment
+
+                // Reload if this message has been reserved for handshake hash.
+                handshakeHash.reload();
+
+                return new Plaintext(rFrag.contentType,
+                        rFrag.majorVersion, rFrag.minorVersion,
+                        rFrag.recordEpoch, rFrag.recordSeq,
+                        ByteBuffer.wrap(rFrag.fragment));
+            } else {    // rFrag.contentType == Record.ct_handshake
+                HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
+                if ((hsFrag.messageLength == hsFrag.fragmentLength) &&
+                    (hsFrag.fragmentOffset == 0)) {     // no fragmentation
+
+                    bufferedFragments.remove(rFrag);    // popup the fragment
+
+                    // this.nextRecordEpoch = hsFrag.recordEpoch;
+                    this.nextRecordSeq = hsFrag.recordSeq + 1;
+                    this.nextMessageSeq = hsFrag.messageSeq + 1;
+
+                    // Note: may try to avoid byte array copy in the future.
+                    byte[] recordFrag = new byte[hsFrag.messageLength + 4];
+                    Plaintext plaintext = new Plaintext(hsFrag.contentType,
+                            hsFrag.majorVersion, hsFrag.minorVersion,
+                            hsFrag.recordEpoch, hsFrag.recordSeq,
+                            ByteBuffer.wrap(recordFrag));
+
+                    // fill the handshake fragment of the record
+                    recordFrag[0] = hsFrag.handshakeType;
+                    recordFrag[1] =
+                            (byte)((hsFrag.messageLength >>> 16) & 0xFF);
+                    recordFrag[2] =
+                            (byte)((hsFrag.messageLength >>> 8) & 0xFF);
+                    recordFrag[3] = (byte)(hsFrag.messageLength & 0xFF);
+
+                    System.arraycopy(hsFrag.fragment, 0,
+                            recordFrag, 4, hsFrag.fragmentLength);
+
+                    // handshake hashing
+                    handshakeHashing(hsFrag, plaintext);
+
+                    return plaintext;
+                } else {                // fragmented handshake message
+                    // the first record
+                    //
+                    // Note: may try to avoid byte array copy in the future.
+                    byte[] recordFrag = new byte[hsFrag.messageLength + 4];
+                    Plaintext plaintext = new Plaintext(hsFrag.contentType,
+                            hsFrag.majorVersion, hsFrag.minorVersion,
+                            hsFrag.recordEpoch, hsFrag.recordSeq,
+                            ByteBuffer.wrap(recordFrag));
+
+                    // fill the handshake fragment of the record
+                    recordFrag[0] = hsFrag.handshakeType;
+                    recordFrag[1] =
+                            (byte)((hsFrag.messageLength >>> 16) & 0xFF);
+                    recordFrag[2] =
+                            (byte)((hsFrag.messageLength >>> 8) & 0xFF);
+                    recordFrag[3] = (byte)(hsFrag.messageLength & 0xFF);
+
+                    int msgSeq = hsFrag.messageSeq;
+                    long maxRecodeSN = hsFrag.recordSeq;
+                    HandshakeFragment hmFrag = hsFrag;
+                    do {
+                        System.arraycopy(hmFrag.fragment, 0,
+                                recordFrag, hmFrag.fragmentOffset + 4,
+                                hmFrag.fragmentLength);
+                        // popup the fragment
+                        bufferedFragments.remove(rFrag);
+
+                        if (maxRecodeSN < hmFrag.recordSeq) {
+                            maxRecodeSN = hmFrag.recordSeq;
+                        }
+
+                        // Note: may buffer retransmitted fragments in order to
+                        // speed up the reassembly in the future.
+
+                        // read the next buffered record
+                        if (!bufferedFragments.isEmpty()) {
+                            rFrag = bufferedFragments.first();
+                            if (rFrag.contentType != Record.ct_handshake) {
+                                break;
+                            } else {
+                                hmFrag = (HandshakeFragment)rFrag;
+                            }
+                        }
+                    } while (!bufferedFragments.isEmpty() &&
+                            (msgSeq == hmFrag.messageSeq));
+
+                    // handshake hashing
+                    handshakeHashing(hsFrag, plaintext);
+
+                    this.nextRecordSeq = maxRecodeSN + 1;
+                    this.nextMessageSeq = msgSeq + 1;
+
+                    return plaintext;
+                }
+            }
+        }
+
+        boolean flightIsReady() {
+
+            //
+            // the ChangeCipherSpec/Finished flight
+            //
+            if (expectCCSFlight) {
+                // Have the ChangeCipherSpec/Finished messages been received?
+                return hasFinisedMessage(bufferedFragments);
+            }
+
+            if (flightType == (byte)0xFF) {
+                return false;
+            }
+
+            if ((flightType == HandshakeMessage.ht_client_hello) ||
+                (flightType == HandshakeMessage.ht_hello_request) ||
+                (flightType == HandshakeMessage.ht_hello_verify_request)) {
+
+                // single handshake message flight
+                return hasCompleted(holesMap.get(flightType));
+            }
+
+            //
+            // the ServerHello flight
+            //
+            if (flightType == HandshakeMessage.ht_server_hello) {
+                // Firstly, check the first flight handshake message.
+                if (!hasCompleted(holesMap.get(flightType))) {
+                    return false;
+                }
+
+                //
+                // an abbreviated handshake
+                //
+                if (isAbbreviatedHandshake) {
+                    // Ready to use the flight if received the
+                    // ChangeCipherSpec and Finished messages.
+                    return hasFinisedMessage(bufferedFragments);
+                }
+
+                //
+                // a full handshake
+                //
+                if (lastHandshakeFragment.handshakeType !=
+                        HandshakeMessage.ht_server_hello_done) {
+                    // Not yet got the final message of the flight.
+                    return false;
+                }
+
+                // Have all handshake message been received?
+                return hasCompleted(bufferedFragments,
+                    flightTopMessageSeq, lastHandshakeFragment.messageSeq);
+            }
+
+            //
+            // the ClientKeyExchange flight
+            //
+            // Note: need to consider more messages in this flight if
+            //       ht_supplemental_data and ht_certificate_url are
+            //       suppported in the future.
+            //
+            if ((flightType == HandshakeMessage.ht_certificate) ||
+                (flightType == HandshakeMessage.ht_client_key_exchange)) {
+
+                // Firstly, check the first flight handshake message.
+                if (!hasCompleted(holesMap.get(flightType))) {
+                    return false;
+                }
+
+                if (!hasFinisedMessage(bufferedFragments)) {
+                    // not yet got the ChangeCipherSpec/Finished messages
+                    return false;
+                }
+
+                if (flightType == HandshakeMessage.ht_client_key_exchange) {
+                    // single handshake message flight
+                    return true;
+                }
+
+                //
+                // flightType == HandshakeMessage.ht_certificate
+                //
+                // We don't support certificates containing fixed
+                // Diffie-Hellman parameters.  Therefore, CertificateVerify
+                // message is required if client Certificate message presents.
+                //
+                if (lastHandshakeFragment.handshakeType !=
+                        HandshakeMessage.ht_certificate_verify) {
+                    // Not yet got the final message of the flight.
+                    return false;
+                }
+
+                // Have all handshake message been received?
+                return hasCompleted(bufferedFragments,
+                    flightTopMessageSeq, lastHandshakeFragment.messageSeq);
+            }
+
+            //
+            // Otherwise, need to receive more handshake messages.
+            //
+            return false;
+        }
+
+        private boolean isSessionResuming(
+                byte[] fragment, byte[] prevSid) throws SSLException {
+
+            // As the first fragment of ServerHello should be big enough
+            // to hold the session_id field, need not to worry about the
+            // fragmentation here.
+            if ((fragment == null) || (fragment.length < 38)) {
+                                    // 38: the minimal ServerHello body length
+                throw new SSLException(
+                        "Invalid ServerHello message: no sufficient data");
+            }
+
+            int sidLen = fragment[34];          // 34: the length field
+            if (sidLen > 32) {                  // opaque SessionID<0..32>
+                throw new SSLException(
+                        "Invalid ServerHello message: invalid session id");
+            }
+
+            if (fragment.length < 38 + sidLen) {
+                throw new SSLException(
+                        "Invalid ServerHello message: no sufficient data");
+            }
+
+            if (sidLen != 0 && (prevSid.length == sidLen)) {
+                // may be a session-resuming handshake
+                for (int i = 0; i < sidLen; i++) {
+                    if (prevSid[i] != fragment[35 + i]) {
+                                                // 35: the session identifier
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+
+            return false;
+        }
+
+        private byte[] getSessionID(byte[] fragment) {
+            // The validity has been checked in the call to isSessionResuming().
+            int sidLen = fragment[34];      // 34: the sessionID length field
+
+            byte[] temporary = new byte[sidLen];
+            System.arraycopy(fragment, 35, temporary, 0, sidLen);
+
+            return temporary;
+        }
+
+        // Looking for the ChangeCipherSpec and Finished messages.
+        //
+        // As the cached Finished message should be a ciphertext, we don't
+        // exactly know a ciphertext is a Finished message or not.  According
+        // to the spec of TLS/DTLS handshaking, a Finished message is always
+        // sent immediately after a ChangeCipherSpec message.  The first
+        // ciphertext handshake message should be the expected Finished message.
+        private boolean hasFinisedMessage(
+                Set<RecordFragment> fragments) {
+
+            boolean hasCCS = false;
+            boolean hasFin = false;
+            for (RecordFragment fragment : fragments) {
+                if (fragment.contentType == Record.ct_change_cipher_spec) {
+                    if (hasFin) {
+                        return true;
+                    }
+                    hasCCS = true;
+                } else if (fragment.contentType == Record.ct_handshake) {
+                    // Finished is the first expected message of a new epoch.
+                    if (fragment.isCiphertext) {
+                        if (hasCCS) {
+                            return true;
+                        }
+                        hasFin = true;
+                    }
+                }
+            }
+
+            return hasFin && hasCCS;
+        }
+
+        private boolean hasCompleted(List<HoleDescriptor> holes) {
+            if (holes == null) {
+                // not yet received this kind of handshake message
+                return false;
+            }
+
+            return holes.isEmpty();  // no fragment hole for complete message
+        }
+
+        private boolean hasCompleted(
+                Set<RecordFragment> fragments,
+                int presentMsgSeq, int endMsgSeq) {
+
+            // The caller should have checked the completion of the first
+            // present handshake message.  Need not to check it again.
+            for (RecordFragment rFrag : fragments) {
+                if ((rFrag.contentType != Record.ct_handshake) ||
+                        rFrag.isCiphertext) {
+                    break;
+                }
+
+                HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
+                if (hsFrag.messageSeq == presentMsgSeq) {
+                    continue;
+                } else if (hsFrag.messageSeq == (presentMsgSeq + 1)) {
+                    // check the completion of the handshake message
+                    if (!hasCompleted(holesMap.get(hsFrag.handshakeType))) {
+                        return false;
+                    }
+
+                    presentMsgSeq = hsFrag.messageSeq;
+                } else {
+                    // not yet got handshake message next to presentMsgSeq
+                    break;
+                }
+            }
+
+            return (presentMsgSeq >= endMsgSeq);
+                        // false: if not yet got all messages of the flight.
+        }
+
+        private void handshakeHashing(
+                HandshakeFragment hsFrag, Plaintext plaintext) {
+
+            byte hsType = hsFrag.handshakeType;
+            if ((hsType == HandshakeMessage.ht_hello_request) ||
+                (hsType == HandshakeMessage.ht_hello_verify_request)) {
+
+                // omitted from handshake hash computation
+                return;
+            }
+
+            if ((hsFrag.messageSeq == 0) &&
+                (hsType == HandshakeMessage.ht_client_hello)) {
+
+                // omit initial ClientHello message
+                //
+                //  4: handshake header
+                //  2: ClientHello.client_version
+                // 32: ClientHello.random
+                int sidLen = plaintext.fragment.get(38);
+
+                if (sidLen == 0) {      // empty session_id, initial handshake
+                    return;
+                }
+            }
+
+            // calculate the DTLS header
+            byte[] temporary = new byte[12];    // 12: handshake header size
+
+            // Handshake.msg_type
+            temporary[0] = hsFrag.handshakeType;
+
+            // Handshake.length
+            temporary[1] = (byte)((hsFrag.messageLength >> 16) & 0xFF);
+            temporary[2] = (byte)((hsFrag.messageLength >> 8) & 0xFF);
+            temporary[3] = (byte)(hsFrag.messageLength & 0xFF);
+
+            // Handshake.message_seq
+            temporary[4] = (byte)((hsFrag.messageSeq >> 8) & 0xFF);
+            temporary[5] = (byte)(hsFrag.messageSeq & 0xFF);
+
+            // Handshake.fragment_offset
+            temporary[6] = 0;
+            temporary[7] = 0;
+            temporary[8] = 0;
+
+            // Handshake.fragment_length
+            temporary[9] = temporary[1];
+            temporary[10] = temporary[2];
+            temporary[11] = temporary[3];
+
+            plaintext.fragment.position(4);     // ignore the TLS header
+            if ((hsType != HandshakeMessage.ht_finished) &&
+                (hsType != HandshakeMessage.ht_certificate_verify)) {
+
+                if (handshakeHash == null) {
+                    // used for cache only
+                    handshakeHash = new HandshakeHash(false);
+                }
+                handshakeHash.update(temporary, 0, 12);
+                handshakeHash.update(plaintext.fragment);
+            } else {
+                // Reserve until this handshake message has been processed.
+                if (handshakeHash == null) {
+                    // used for cache only
+                    handshakeHash = new HandshakeHash(false);
+                }
+                handshakeHash.reserve(temporary, 0, 12);
+                handshakeHash.reserve(plaintext.fragment);
+            }
+            plaintext.fragment.position(0);     // restore the position
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java	Thu Jun 11 00:51:11 2015 +0200
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+
+import javax.crypto.BadPaddingException;
+
+import javax.net.ssl.*;
+
+import sun.misc.HexDumpEncoder;
+import static sun.security.ssl.Ciphertext.RecordType;
+
+/**
+ * DTLS {@code OutputRecord} implementation for {@code SSLEngine}.
+ */
+final class DTLSOutputRecord extends OutputRecord implements DTLSRecord {
+
+    private DTLSFragmenter fragmenter = null;
+
+    int                 writeEpoch;
+
+    int                 prevWriteEpoch;
+    Authenticator       prevWriteAuthenticator;
+    CipherBox           prevWriteCipher;
+
+    private LinkedList<RecordMemo> alertMemos = new LinkedList<>();
+
+    DTLSOutputRecord() {
+        this.writeAuthenticator = new MAC(true);
+
+        this.writeEpoch = 0;
+        this.prevWriteEpoch = 0;
+        this.prevWriteCipher = CipherBox.NULL;
+        this.prevWriteAuthenticator = new MAC(true);
+
+        this.packetSize = DTLSRecord.maxRecordSize;
+        this.protocolVersion = ProtocolVersion.DEFAULT_DTLS;
+    }
+
+    @Override
+    void changeWriteCiphers(Authenticator writeAuthenticator,
+            CipherBox writeCipher) throws IOException {
+
+        encodeChangeCipherSpec();
+
+        prevWriteCipher.dispose();
+
+        this.prevWriteAuthenticator = this.writeAuthenticator;
+        this.prevWriteCipher = this.writeCipher;
+        this.prevWriteEpoch = this.writeEpoch;
+
+        this.writeAuthenticator = writeAuthenticator;
+        this.writeCipher = writeCipher;
+        this.writeEpoch++;
+
+        this.isFirstAppOutputRecord = true;
+
+        // set the epoch number
+        this.writeAuthenticator.setEpochNumber(this.writeEpoch);
+    }
+
+    @Override
+    void encodeAlert(byte level, byte description) throws IOException {
+        RecordMemo memo = new RecordMemo();
+
+        memo.contentType = Record.ct_alert;
+        memo.majorVersion = protocolVersion.major;
+        memo.minorVersion = protocolVersion.minor;
+        memo.encodeEpoch = writeEpoch;
+        memo.encodeCipher = writeCipher;
+        memo.encodeAuthenticator = writeAuthenticator;
+
+        memo.fragment = new byte[2];
+        memo.fragment[0] = level;
+        memo.fragment[1] = description;
+
+        alertMemos.add(memo);
+    }
+
+    @Override
+    void encodeChangeCipherSpec() throws IOException {
+        if (fragmenter == null) {
+           fragmenter = new DTLSFragmenter();
+        }
+        fragmenter.queueUpChangeCipherSpec();
+    }
+
+    @Override
+    void encodeHandshake(byte[] source,
+            int offset, int length) throws IOException {
+
+        if (firstMessage) {
+            firstMessage = false;
+        }
+
+        if (fragmenter == null) {
+           fragmenter = new DTLSFragmenter();
+        }
+
+        fragmenter.queueUpHandshake(source, offset, length);
+    }
+
+    @Override
+    Ciphertext encode(ByteBuffer[] sources, int offset, int length,
+            ByteBuffer destination) throws IOException {
+
+        if (writeAuthenticator.seqNumOverflow()) {
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(Thread.currentThread().getName() +
+                    ", sequence number extremely close to overflow " +
+                    "(2^64-1 packets). Closing connection.");
+            }
+
+            throw new SSLHandshakeException("sequence number overflow");
+        }
+
+        // not apply to handshake message
+        int macLen = 0;
+        if (writeAuthenticator instanceof MAC) {
+            macLen = ((MAC)writeAuthenticator).MAClen();
+        }
+
+        int fragLen;
+        if (packetSize > 0) {
+            fragLen = Math.min(maxRecordSize, packetSize);
+            fragLen = writeCipher.calculateFragmentSize(
+                    fragLen, macLen, headerSize);
+
+            fragLen = Math.min(fragLen, Record.maxDataSize);
+        } else {
+            fragLen = Record.maxDataSize;
+        }
+
+        if (fragmentSize > 0) {
+            fragLen = Math.min(fragLen, fragmentSize);
+        }
+
+        int dstPos = destination.position();
+        int dstLim = destination.limit();
+        int dstContent = dstPos + headerSize +
+                                writeCipher.getExplicitNonceSize();
+        destination.position(dstContent);
+
+        int remains = Math.min(fragLen, destination.remaining());
+        fragLen = 0;
+        int srcsLen = offset + length;
+        for (int i = offset; (i < srcsLen) && (remains > 0); i++) {
+            int amount = Math.min(sources[i].remaining(), remains);
+            int srcLimit = sources[i].limit();
+            sources[i].limit(sources[i].position() + amount);
+            destination.put(sources[i]);
+            sources[i].limit(srcLimit);         // restore the limit
+            remains -= amount;
+            fragLen += amount;
+        }
+
+        destination.limit(destination.position());
+        destination.position(dstContent);
+
+        if ((debug != null) && Debug.isOn("record")) {
+            System.out.println(Thread.currentThread().getName() +
+                    ", WRITE: " + protocolVersion + " " +
+                    Record.contentName(Record.ct_application_data) +
+                    ", length = " + destination.remaining());
+        }
+
+        // Encrypt the fragment and wrap up a record.
+        long recordSN = encrypt(writeAuthenticator, writeCipher,
+                Record.ct_application_data, destination,
+                dstPos, dstLim, headerSize,
+                protocolVersion, true);
+
+        if ((debug != null) && Debug.isOn("packet")) {
+            ByteBuffer temporary = destination.duplicate();
+            temporary.limit(temporary.position());
+            temporary.position(dstPos);
+            Debug.printHex(
+                    "[Raw write]: length = " + temporary.remaining(),
+                    temporary);
+        }
+
+        // remain the limit unchanged
+        destination.limit(dstLim);
+
+        return new Ciphertext(RecordType.RECORD_APPLICATION_DATA, recordSN);
+    }
+
+    @Override
+    Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException {
+        if (alertMemos != null && !alertMemos.isEmpty()) {
+            RecordMemo memo = alertMemos.pop();
+
+            int macLen = 0;
+            if (memo.encodeAuthenticator instanceof MAC) {
+                macLen = ((MAC)memo.encodeAuthenticator).MAClen();
+            }
+
+            int dstPos = destination.position();
+            int dstLim = destination.limit();
+            int dstContent = dstPos + headerSize +
+                                writeCipher.getExplicitNonceSize();
+            destination.position(dstContent);
+
+            destination.put(memo.fragment);
+
+            destination.limit(destination.position());
+            destination.position(dstContent);
+
+            if ((debug != null) && Debug.isOn("record")) {
+                System.out.println(Thread.currentThread().getName() +
+                        ", WRITE: " + protocolVersion + " " +
+                        Record.contentName(Record.ct_alert) +
+                        ", length = " + destination.remaining());
+            }
+
+            // Encrypt the fragment and wrap up a record.
+            long recordSN = encrypt(memo.encodeAuthenticator, memo.encodeCipher,
+                    Record.ct_alert, destination, dstPos, dstLim, headerSize,
+                    ProtocolVersion.valueOf(memo.majorVersion,
+                            memo.minorVersion), true);
+
+            if ((debug != null) && Debug.isOn("packet")) {
+                ByteBuffer temporary = destination.duplicate();
+                temporary.limit(temporary.position());
+                temporary.position(dstPos);
+                Debug.printHex(
+                        "[Raw write]: length = " + temporary.remaining(),
+                        temporary);
+            }
+
+            // remain the limit unchanged
+            destination.limit(dstLim);
+
+            return new Ciphertext(RecordType.RECORD_ALERT, recordSN);
+        }
+
+        if (fragmenter != null) {
+            return fragmenter.acquireCiphertext(destination);
+        }
+
+        return null;
+    }
+
+    @Override
+    boolean isEmpty() {
+        return ((fragmenter == null) || fragmenter.isEmpty()) &&
+               ((alertMemos == null) || alertMemos.isEmpty());
+    }
+
+    @Override
+    void initHandshaker() {
+        // clean up
+        fragmenter = null;
+    }
+
+    // buffered record fragment
+    private static class RecordMemo {
+        byte            contentType;
+        byte            majorVersion;
+        byte            minorVersion;
+        int             encodeEpoch;
+        CipherBox       encodeCipher;
+        Authenticator   encodeAuthenticator;
+
+        byte[]          fragment;
+    }
+
+    private static class HandshakeMemo extends RecordMemo {
+        byte            handshakeType;
+        int             messageSequence;
+        int             acquireOffset;
+    }
+
+    private final class DTLSFragmenter {
+        private LinkedList<RecordMemo> handshakeMemos = new LinkedList<>();
+        private int acquireIndex = 0;
+        private int messageSequence = 0;
+        private boolean flightIsReady = false;
+
+        // Per section 4.1.1, RFC 6347:
+        //
+        // If repeated retransmissions do not result in a response, and the
+        // PMTU is unknown, subsequent retransmissions SHOULD back off to a
+        // smaller record size, fragmenting the handshake message as
+        // appropriate.
+        //
+        // In this implementation, two times of retransmits would be attempted
+        // before backing off.  The back off is supported only if the packet
+        // size is bigger than 256 bytes.
+        private int retransmits = 2;            // attemps of retransmits
+
+        void queueUpChangeCipherSpec() {
+
+            // Cleanup if a new flight starts.
+            if (flightIsReady) {
+                handshakeMemos.clear();
+                acquireIndex = 0;
+                flightIsReady = false;
+            }
+
+            RecordMemo memo = new RecordMemo();
+
+            memo.contentType = Record.ct_change_cipher_spec;
+            memo.majorVersion = protocolVersion.major;
+            memo.minorVersion = protocolVersion.minor;
+            memo.encodeEpoch = writeEpoch;
+            memo.encodeCipher = writeCipher;
+            memo.encodeAuthenticator = writeAuthenticator;
+
+            memo.fragment = new byte[1];
+            memo.fragment[0] = 1;
+
+            handshakeMemos.add(memo);
+        }
+
+        void queueUpHandshake(byte[] buf,
+                int offset, int length) throws IOException {
+
+            // Cleanup if a new flight starts.
+            if (flightIsReady) {
+                handshakeMemos.clear();
+                acquireIndex = 0;
+                flightIsReady = false;
+            }
+
+            HandshakeMemo memo = new HandshakeMemo();
+
+            memo.contentType = Record.ct_handshake;
+            memo.majorVersion = protocolVersion.major;
+            memo.minorVersion = protocolVersion.minor;
+            memo.encodeEpoch = writeEpoch;
+