changeset 17387:c7107fc8482d

Merge
author henryjen
date Mon, 19 Jun 2017 11:29:42 -0700
parents d0a0f9e3cf9f c007075f78dd
children 88f666ee4523
files src/java.base/share/classes/com/sun/crypto/provider/PBECipherCore.java src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java
diffstat 149 files changed, 5520 insertions(+), 2367 deletions(-) [+]
line wrap: on
line diff
--- a/make/rmic/Rmic-java.rmi.gmk	Mon Jun 19 08:16:03 2017 -0400
+++ b/make/rmic/Rmic-java.rmi.gmk	Mon Jun 19 11:29:42 2017 -0700
@@ -40,16 +40,9 @@
     RUN_V12 := true))
 GENCLASSES += $(RMI_12)
 
-$(eval $(call SetupRMICompilation,RMI_11, \
-    CLASSES := sun.rmi.registry.RegistryImpl \
-        sun.rmi.transport.DGCImpl, \
-    CLASSES_DIR := $(CLASSES_DIR)/java.rmi, \
-    STUB_CLASSES_DIR := $(STUB_CLASSES_DIR)/java.rmi, \
-    RUN_V11 := true))
-GENCLASSES += $(RMI_11)
 
 ################################################################################
 
-all: $(RMI_11) $(RMI_12)
+all: $(RMI_12)
 
 .PHONY: all
--- a/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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,7 +156,7 @@
                 throw new InvalidKeyException("Key encoding must not be null");
             } else if (value.length != fixedKeySize) {
                 throw new InvalidKeyException("The key must be " +
-                    fixedKeySize*8 + " bits");
+                    fixedKeySize + " bytes");
             }
         }
     }
@@ -509,7 +509,7 @@
             throw new InvalidKeyException("Invalid AES key length: " +
                                           encoded.length + " bytes");
         }
-        return encoded.length * 8;
+        return Math.multiplyExact(encoded.length, 8);
     }
 
     /**
@@ -628,9 +628,9 @@
         }
         if (src != null) {
             int aadLen = src.limit() - src.position();
-            if (aadLen != 0) {
+            if (aadLen > 0) {
                 if (src.hasArray()) {
-                    int aadOfs = src.arrayOffset() + src.position();
+                    int aadOfs = Math.addExact(src.arrayOffset(), src.position());
                     core.updateAAD(src.array(), aadOfs, aadLen);
                     src.position(src.limit());
                 } else {
--- a/src/java.base/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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,7 +156,7 @@
         if (decrypting) {
             result = inputLen - 8;
         } else {
-            result = inputLen + 8;
+            result = Math.addExact(inputLen, 8);
         }
         return (result < 0? 0:result);
     }
@@ -378,7 +378,7 @@
             throw new InvalidKeyException("Invalid key length: " +
                                           encoded.length + " bytes");
         }
-        return encoded.length * 8;
+        return Math.multiplyExact(encoded.length, 8);
     }
 
     /**
@@ -404,7 +404,7 @@
             throw new InvalidKeyException("Cannot get an encoding of " +
                                           "the key to be wrapped");
         }
-        byte[] out = new byte[keyVal.length + 8];
+        byte[] out = new byte[Math.addExact(keyVal.length, 8)];
 
         if (keyVal.length == 8) {
             System.arraycopy(IV, 0, out, 0, IV.length);
--- a/src/java.base/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -257,7 +257,7 @@
     // see JCE spec
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
         byte[] encodedKey = getEncodedKey(key);
-        return encodedKey.length << 3;
+        return Math.multiplyExact(encodedKey.length, 8);
     }
 
 }
--- a/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCipher.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCipher.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -373,7 +373,7 @@
      * @exception InvalidKeyException if <code>key</code> is invalid.
      */
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
-        return (key.getEncoded().length * 8);
+        return Math.multiplyExact(key.getEncoded().length, 8);
     }
 
     /**
--- a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -324,13 +324,14 @@
     }
 
     private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
-        int totalLen = buffered + inputLen + cipher.getBufferedLength();
+        int totalLen = Math.addExact(buffered, cipher.getBufferedLength());
+        totalLen = Math.addExact(totalLen, inputLen);
         switch (cipherMode) {
         case GCM_MODE:
             if (isDoFinal) {
                 int tagLen = ((GaloisCounterMode) cipher).getTagLen();
                 if (!decrypting) {
-                    totalLen += tagLen;
+                    totalLen = Math.addExact(totalLen, tagLen);
                 } else {
                     totalLen -= tagLen;
                 }
@@ -346,10 +347,10 @@
                         totalLen = diffBlocksize;
                     } else {
                         int residue = (totalLen - diffBlocksize) % blockSize;
-                        totalLen += (blockSize - residue);
+                        totalLen = Math.addExact(totalLen, (blockSize - residue));
                     }
                 } else {
-                    totalLen += padding.padLength(totalLen);
+                    totalLen = Math.addExact(totalLen, padding.padLength(totalLen));
                 }
             }
             break;
@@ -711,7 +712,8 @@
         }
 
         // figure out how much can be sent to crypto function
-        int len = buffered + inputLen - minBytes;
+        int len = Math.addExact(buffered, inputLen);
+        len -= minBytes;
         if (padding != null && decrypting) {
             // do not include the padding bytes when decrypting
             len -= blockSize;
@@ -730,12 +732,12 @@
         int outLen = 0;
         if (len != 0) { // there is some work to do
             if ((input == output)
-                 && (outputOffset < (inputOffset + inputLen))
-                 && (inputOffset < (outputOffset + buffer.length))) {
+                 && (outputOffset - inputOffset < inputLen)
+                 && (inputOffset - outputOffset < buffer.length)) {
                 // copy 'input' out to avoid its content being
                 // overwritten prematurely.
                 input = Arrays.copyOfRange(input, inputOffset,
-                    inputOffset + inputLen);
+                    Math.addExact(inputOffset, inputLen));
                 inputOffset = 0;
             }
             if (len <= buffered) {
@@ -757,13 +759,13 @@
                     if (bufferCapacity != 0) {
                         temp = Math.min(bufferCapacity, inputConsumed);
                         if (unitBytes != blockSize) {
-                            temp -= ((buffered + temp) % unitBytes);
+                            temp -= (Math.addExact(buffered, temp) % unitBytes);
                         }
                         System.arraycopy(input, inputOffset, buffer, buffered, temp);
-                        inputOffset += temp;
+                        inputOffset = Math.addExact(inputOffset, temp);
                         inputConsumed -= temp;
                         inputLen -= temp;
-                        buffered += temp;
+                        buffered = Math.addExact(buffered, temp);
                     }
                     // process 'buffer'
                     if (decrypting) {
@@ -771,7 +773,7 @@
                     } else {
                          outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
                     }
-                    outputOffset += outLen;
+                    outputOffset = Math.addExact(outputOffset, outLen);
                     buffered = 0;
                 }
                 if (inputConsumed > 0) { // still has input to process
@@ -802,7 +804,7 @@
         if (inputLen > 0) {
             System.arraycopy(input, inputOffset, buffer, buffered,
                              inputLen);
-            buffered += inputLen;
+            buffered = Math.addExact(buffered, inputLen);
         }
         return outLen;
     }
@@ -912,10 +914,10 @@
         }
 
         // calculate total input length
-        int len = buffered + inputLen;
+        int len = Math.addExact(buffered, inputLen);
 
         // calculate padding length
-        int totalLen = len + cipher.getBufferedLength();
+        int totalLen = Math.addExact(len, cipher.getBufferedLength());
         int paddingLen = 0;
         // will the total input length be a multiple of blockSize?
         if (unitBytes != blockSize) {
@@ -948,12 +950,12 @@
         int finalBufLen = inputLen;
         if ((buffered != 0) || (!decrypting && padding != null) ||
             ((input == output)
-              && (outputOffset < (inputOffset + inputLen))
-              && (inputOffset < (outputOffset + buffer.length)))) {
+              && (outputOffset - inputOffset < inputLen)
+              && (inputOffset - outputOffset < buffer.length))) {
             if (decrypting || padding == null) {
                 paddingLen = 0;
             }
-            finalBuf = new byte[len + paddingLen];
+            finalBuf = new byte[Math.addExact(len, paddingLen)];
             finalOffset = 0;
             if (buffered != 0) {
                 System.arraycopy(buffer, 0, finalBuf, 0, buffered);
@@ -963,7 +965,7 @@
                                  buffered, inputLen);
             }
             if (paddingLen != 0) {
-                padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen);
+                padding.padWithLen(finalBuf, Math.addExact(buffered, inputLen), paddingLen);
             }
             finalBufLen = finalBuf.length;
         }
--- a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java	Mon Jun 19 11:29:42 2017 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.lang.ref.Reference;
 import java.security.MessageDigest;
 import java.security.KeyRep;
 import java.security.InvalidKeyException;
@@ -79,7 +80,12 @@
     public byte[] getEncoded() {
         // Return a copy of the key, rather than a reference,
         // so that the key data cannot be modified from outside
-        return this.key.clone();
+
+        // The key is zeroized by finalize()
+        // The reachability fence ensures finalize() isn't called early
+        byte[] result = key.clone();
+        Reference.reachabilityFence(this);
+        return result;
     }
 
     public String getAlgorithm() {
--- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java	Mon Jun 19 11:29:42 2017 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.lang.ref.Reference;
 import java.security.MessageDigest;
 import java.security.KeyRep;
 import java.security.InvalidKeyException;
@@ -79,7 +80,11 @@
     }
 
     public byte[] getEncoded() {
-        return this.key.clone();
+        // The key is zeroized by finalize()
+        // The reachability fence ensures finalize() isn't called early
+        byte[] result = key.clone();
+        Reference.reachabilityFence(this);
+        return result;
     }
 
     public String getAlgorithm() {
--- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -140,7 +140,7 @@
         if (decrypting) {
             result = inputLen - 16; // CHECKSUM_LEN + IV_LEN;
         } else {
-            result = inputLen + 16;
+            result = Math.addExact(inputLen, 16);
         }
         return (result < 0? 0:result);
     }
@@ -449,11 +449,11 @@
         }
 
         byte[] cks = getChecksum(keyVal);
-        byte[] in = new byte[keyVal.length + CHECKSUM_LEN];
+        byte[] in = new byte[Math.addExact(keyVal.length, CHECKSUM_LEN)];
         System.arraycopy(keyVal, 0, in, 0, keyVal.length);
         System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN);
 
-        byte[] out = new byte[iv.length + in.length];
+        byte[] out = new byte[Math.addExact(iv.length, in.length)];
         System.arraycopy(iv, 0, out, 0, iv.length);
 
         cipher.encrypt(in, 0, in.length, out, iv.length);
--- a/src/java.base/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -63,7 +63,8 @@
         if (in == null)
             return;
 
-        if ((off + len) > in.length) {
+        int idx = Math.addExact(off, len);
+        if (idx > in.length) {
             throw new ShortBufferException("Buffer too small to hold padding");
         }
 
@@ -71,7 +72,7 @@
         byte[] padding = new byte[len - 1];
         SunJCE.getRandom().nextBytes(padding);
         System.arraycopy(padding, 0, in, off, len - 1);
-        in[off + len - 1] = paddingOctet;
+        in[idx - 1] = paddingOctet;
         return;
     }
 
@@ -94,14 +95,15 @@
             return 0;
         }
 
-        byte lastByte = in[off + len - 1];
+        int idx = Math.addExact(off, len);
+        byte lastByte = in[idx - 1];
         int padValue = (int)lastByte & 0x0ff;
         if ((padValue < 0x01)
             || (padValue > blockSize)) {
             return -1;
         }
 
-        int start = off + len - padValue;
+        int start = idx - padValue;
         if (start < off) {
             return -1;
         }
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBECipherCore.java	Mon Jun 19 08:16:03 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +0,0 @@
-/*
- * Copyright (c) 2002, 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 com.sun.crypto.provider;
-
-import java.security.*;
-import java.security.spec.*;
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-/**
- * This class represents password-based encryption as defined by the PKCS #5
- * standard.
- *
- * @author Jan Luehe
- *
- *
- * @see javax.crypto.Cipher
- */
-final class PBECipherCore {
-
-    // the encapsulated DES cipher
-    private CipherCore cipher;
-    private MessageDigest md;
-    private int blkSize;
-    private String algo = null;
-    private byte[] salt = null;
-    private int iCount = 10;
-
-    /**
-     * Creates an instance of PBE Cipher using the specified CipherSpi
-     * instance.
-     *
-     */
-    PBECipherCore(String cipherAlg) throws NoSuchAlgorithmException,
-        NoSuchPaddingException {
-        algo = cipherAlg;
-        if (algo.equals("DES")) {
-            cipher = new CipherCore(new DESCrypt(),
-                                    DESConstants.DES_BLOCK_SIZE);
-        } else if (algo.equals("DESede")) {
-
-            cipher = new CipherCore(new DESedeCrypt(),
-                                    DESConstants.DES_BLOCK_SIZE);
-        } else {
-            throw new NoSuchAlgorithmException("No Cipher implementation " +
-                                               "for PBEWithMD5And" + algo);
-        }
-        cipher.setMode("CBC");
-        cipher.setPadding("PKCS5Padding");
-        // get instance of MD5
-        md = MessageDigest.getInstance("MD5");
-    }
-
-    /**
-     * Sets the mode of this cipher. This algorithm can only be run in CBC
-     * mode.
-     *
-     * @param mode the cipher mode
-     *
-     * @exception NoSuchAlgorithmException if the requested cipher mode is
-     * invalid
-     */
-    void setMode(String mode) throws NoSuchAlgorithmException {
-        cipher.setMode(mode);
-    }
-
-     /**
-     * Sets the padding mechanism of this cipher. This algorithm only uses
-     * PKCS #5 padding.
-     *
-     * @param padding the padding mechanism
-     *
-     * @exception NoSuchPaddingException if the requested padding mechanism
-     * is invalid
-     */
-    void setPadding(String paddingScheme) throws NoSuchPaddingException {
-        cipher.setPadding(paddingScheme);
-    }
-
-    /**
-     * Returns the block size (in bytes).
-     *
-     * @return the block size (in bytes)
-     */
-    int getBlockSize() {
-        return DESConstants.DES_BLOCK_SIZE;
-    }
-
-    /**
-     * Returns the length in bytes that an output buffer would need to be in
-     * order to hold the result of the next <code>update</code> or
-     * <code>doFinal</code> operation, given the input length
-     * <code>inputLen</code> (in bytes).
-     *
-     * <p>This call takes into account any unprocessed (buffered) data from a
-     * previous <code>update</code> call, and padding.
-     *
-     * <p>The actual output length of the next <code>update</code> or
-     * <code>doFinal</code> call may be smaller than the length returned by
-     * this method.
-     *
-     * @param inputLen the input length (in bytes)
-     *
-     * @return the required output buffer size (in bytes)
-     *
-     */
-    int getOutputSize(int inputLen) {
-        return cipher.getOutputSize(inputLen);
-    }
-
-    /**
-     * Returns the initialization vector (IV) in a new buffer.
-     *
-     * <p> This is useful in the case where a random IV has been created
-     * (see <a href = "#init">init</a>),
-     * or in the context of password-based encryption or
-     * decryption, where the IV is derived from a user-supplied password.
-     *
-     * @return the initialization vector in a new buffer, or null if the
-     * underlying algorithm does not use an IV, or if the IV has not yet
-     * been set.
-     */
-    byte[] getIV() {
-        return cipher.getIV();
-    }
-
-    /**
-     * Returns the parameters used with this cipher.
-     *
-     * <p>The returned parameters may be the same that were used to initialize
-     * this cipher, or may contain the default set of parameters or a set of
-     * randomly generated parameters used by the underlying cipher
-     * implementation (provided that the underlying cipher implementation
-     * uses a default set of parameters or creates new parameters if it needs
-     * parameters but was not initialized with any).
-     *
-     * @return the parameters used with this cipher, or null if this cipher
-     * does not use any parameters.
-     */
-    AlgorithmParameters getParameters() {
-        AlgorithmParameters params = null;
-        if (salt == null) {
-            salt = new byte[8];
-            SunJCE.getRandom().nextBytes(salt);
-        }
-        PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
-        try {
-            params = AlgorithmParameters.getInstance("PBEWithMD5And" +
-                (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"),
-                    SunJCE.getInstance());
-            params.init(pbeSpec);
-        } catch (NoSuchAlgorithmException nsae) {
-            // should never happen
-            throw new RuntimeException("SunJCE called, but not configured");
-        } catch (InvalidParameterSpecException ipse) {
-            // should never happen
-            throw new RuntimeException("PBEParameterSpec not supported");
-        }
-        return params;
-    }
-
-    /**
-     * Initializes this cipher with a key, a set of
-     * algorithm parameters, and a source of randomness.
-     * The cipher is initialized for one of the following four operations:
-     * encryption, decryption, key wrapping or key unwrapping, depending on
-     * the value of <code>opmode</code>.
-     *
-     * <p>If this cipher (including its underlying feedback or padding scheme)
-     * requires any random bytes, it will get them from <code>random</code>.
-     *
-     * @param opmode the operation mode of this cipher (this is one of
-     * the following:
-     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
-     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
-     * @param key the encryption key
-     * @param params the algorithm parameters
-     * @param random the source of randomness
-     *
-     * @exception InvalidKeyException if the given key is inappropriate for
-     * initializing this cipher
-     * @exception InvalidAlgorithmParameterException if the given algorithm
-     * parameters are inappropriate for this cipher
-     */
-    void init(int opmode, Key key, AlgorithmParameterSpec params,
-              SecureRandom random)
-        throws InvalidKeyException, InvalidAlgorithmParameterException {
-        if (((opmode == Cipher.DECRYPT_MODE) ||
-             (opmode == Cipher.UNWRAP_MODE)) && (params == null)) {
-            throw new InvalidAlgorithmParameterException("Parameters "
-                                                         + "missing");
-        }
-        if ((key == null) ||
-            (key.getEncoded() == null) ||
-            !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
-            throw new InvalidKeyException("Missing password");
-        }
-
-        if (params == null) {
-            // create random salt and use default iteration count
-            salt = new byte[8];
-            random.nextBytes(salt);
-        } else {
-            if (!(params instanceof PBEParameterSpec)) {
-                throw new InvalidAlgorithmParameterException
-                    ("Wrong parameter type: PBE expected");
-            }
-            salt = ((PBEParameterSpec) params).getSalt();
-            // salt must be 8 bytes long (by definition)
-            if (salt.length != 8) {
-                throw new InvalidAlgorithmParameterException
-                    ("Salt must be 8 bytes long");
-            }
-            iCount = ((PBEParameterSpec) params).getIterationCount();
-            if (iCount <= 0) {
-                throw new InvalidAlgorithmParameterException
-                    ("IterationCount must be a positive number");
-            }
-        }
-
-        byte[] derivedKey = deriveCipherKey(key);
-        // use all but the last 8 bytes as the key value
-        SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
-                                                    derivedKey.length-8, algo);
-        // use the last 8 bytes as the IV
-        IvParameterSpec ivSpec = new IvParameterSpec(derivedKey,
-                                                     derivedKey.length-8,
-                                                     8);
-        // initialize the underlying cipher
-        cipher.init(opmode, cipherKey, ivSpec, random);
-    }
-
-    private byte[] deriveCipherKey(Key key) {
-
-        byte[] result = null;
-        byte[] passwdBytes = key.getEncoded();
-
-        if (algo.equals("DES")) {
-            // P || S (password concatenated with salt)
-            byte[] concat = new byte[passwdBytes.length + salt.length];
-            System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
-            java.util.Arrays.fill(passwdBytes, (byte)0x00);
-            System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
-
-            // digest P || S with c iterations
-            byte[] toBeHashed = concat;
-            for (int i = 0; i < iCount; i++) {
-                md.update(toBeHashed);
-                toBeHashed = md.digest(); // this resets the digest
-            }
-            java.util.Arrays.fill(concat, (byte)0x00);
-            result = toBeHashed;
-        } else if (algo.equals("DESede")) {
-            // if the 2 salt halves are the same, invert one of them
-            int i;
-            for (i=0; i<4; i++) {
-                if (salt[i] != salt[i+4])
-                    break;
-            }
-            if (i==4) { // same, invert 1st half
-                for (i=0; i<2; i++) {
-                    byte tmp = salt[i];
-                    salt[i] = salt[3-i];
-                    salt[3-1] = tmp;
-                }
-            }
-
-            // Now digest each half (concatenated with password). For each
-            // half, go through the loop as many times as specified by the
-            // iteration count parameter (inner for loop).
-            // Concatenate the output from each digest round with the
-            // password, and use the result as the input to the next digest
-            // operation.
-            byte[] kBytes = null;
-            IvParameterSpec iv = null;
-            byte[] toBeHashed = null;
-            result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
-                              DESConstants.DES_BLOCK_SIZE];
-            for (i = 0; i < 2; i++) {
-                toBeHashed = new byte[salt.length/2];
-                System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0,
-                                 toBeHashed.length);
-                for (int j=0; j < iCount; j++) {
-                    md.update(toBeHashed);
-                    md.update(passwdBytes);
-                    toBeHashed = md.digest(); // this resets the digest
-                }
-                System.arraycopy(toBeHashed, 0, result, i*16,
-                                 toBeHashed.length);
-            }
-        }
-        return result;
-    }
-
-    void init(int opmode, Key key, AlgorithmParameters params,
-              SecureRandom random)
-        throws InvalidKeyException, InvalidAlgorithmParameterException {
-        PBEParameterSpec pbeSpec = null;
-        if (params != null) {
-            try {
-                pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                throw new InvalidAlgorithmParameterException("Wrong parameter "
-                                                             + "type: PBE "
-                                                             + "expected");
-            }
-        }
-        init(opmode, key, pbeSpec, random);
-    }
-
-    /**
-     * Continues a multiple-part encryption or decryption operation
-     * (depending on how this cipher was initialized), processing another data
-     * part.
-     *
-     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
-     * buffer, starting at <code>inputOffset</code>, are processed, and the
-     * result is stored in a new buffer.
-     *
-     * @param input the input buffer
-     * @param inputOffset the offset in <code>input</code> where the input
-     * starts
-     * @param inputLen the input length
-     *
-     * @return the new buffer with the result
-     *
-     */
-    byte[] update(byte[] input, int inputOffset, int inputLen) {
-        return cipher.update(input, inputOffset, inputLen);
-    }
-
-    /**
-     * Continues a multiple-part encryption or decryption operation
-     * (depending on how this cipher was initialized), processing another data
-     * part.
-     *
-     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
-     * buffer, starting at <code>inputOffset</code>, are processed, and the
-     * result is stored in the <code>output</code> buffer, starting at
-     * <code>outputOffset</code>.
-     *
-     * @param input the input buffer
-     * @param inputOffset the offset in <code>input</code> where the input
-     * starts
-     * @param inputLen the input length
-     * @param output the buffer for the result
-     * @param outputOffset the offset in <code>output</code> where the result
-     * is stored
-     *
-     * @return the number of bytes stored in <code>output</code>
-     *
-     * @exception ShortBufferException if the given output buffer is too small
-     * to hold the result
-     */
-    int update(byte[] input, int inputOffset, int inputLen,
-               byte[] output, int outputOffset)
-        throws ShortBufferException {
-        return cipher.update(input, inputOffset, inputLen,
-                             output, outputOffset);
-    }
-
-    /**
-     * Encrypts or decrypts data in a single-part operation,
-     * or finishes a multiple-part operation.
-     * The data is encrypted or decrypted, depending on how this cipher was
-     * initialized.
-     *
-     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
-     * buffer, starting at <code>inputOffset</code>, and any input bytes that
-     * may have been buffered during a previous <code>update</code> operation,
-     * are processed, with padding (if requested) being applied.
-     * The result is stored in a new buffer.
-     *
-     * <p>The cipher is reset to its initial state (uninitialized) after this
-     * call.
-     *
-     * @param input the input buffer
-     * @param inputOffset the offset in <code>input</code> where the input
-     * starts
-     * @param inputLen the input length
-     *
-     * @return the new buffer with the result
-     *
-     * @exception IllegalBlockSizeException if this cipher is a block cipher,
-     * no padding has been requested (only in encryption mode), and the total
-     * input length of the data processed by this cipher is not a multiple of
-     * block size
-     * @exception BadPaddingException if decrypting and padding is chosen,
-     * but the last input data does not have proper padding bytes.
-     */
-    byte[] doFinal(byte[] input, int inputOffset, int inputLen)
-        throws IllegalBlockSizeException, BadPaddingException {
-        return cipher.doFinal(input, inputOffset, inputLen);
-    }
-
-    /**
-     * Encrypts or decrypts data in a single-part operation,
-     * or finishes a multiple-part operation.
-     * The data is encrypted or decrypted, depending on how this cipher was
-     * initialized.
-     *
-     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
-     * buffer, starting at <code>inputOffset</code>, and any input bytes that
-     * may have been buffered during a previous <code>update</code> operation,
-     * are processed, with padding (if requested) being applied.
-     * The result is stored in the <code>output</code> buffer, starting at
-     * <code>outputOffset</code>.
-     *
-     * <p>The cipher is reset to its initial state (uninitialized) after this
-     * call.
-     *
-     * @param input the input buffer
-     * @param inputOffset the offset in <code>input</code> where the input
-     * starts
-     * @param inputLen the input length
-     * @param output the buffer for the result
-     * @param outputOffset the offset in <code>output</code> where the result
-     * is stored
-     *
-     * @return the number of bytes stored in <code>output</code>
-     *
-     * @exception IllegalBlockSizeException if this cipher is a block cipher,
-     * no padding has been requested (only in encryption mode), and the total
-     * input length of the data processed by this cipher is not a multiple of
-     * block size
-     * @exception ShortBufferException if the given output buffer is too small
-     * to hold the result
-     * @exception BadPaddingException if decrypting and padding is chosen,
-     * but the last input data does not have proper padding bytes.
-     */
-    int doFinal(byte[] input, int inputOffset, int inputLen,
-                byte[] output, int outputOffset)
-        throws ShortBufferException, IllegalBlockSizeException,
-               BadPaddingException {
-        return cipher.doFinal(input, inputOffset, inputLen,
-                                    output, outputOffset);
-    }
-
-    /**
-     * Wrap a key.
-     *
-     * @param key the key to be wrapped.
-     *
-     * @return the wrapped key.
-     *
-     * @exception IllegalBlockSizeException if this cipher is a block
-     * cipher, no padding has been requested, and the length of the
-     * encoding of the key to be wrapped is not a
-     * multiple of the block size.
-     *
-     * @exception InvalidKeyException if it is impossible or unsafe to
-     * wrap the key with this cipher (e.g., a hardware protected key is
-     * being passed to a software only cipher).
-     */
-    byte[] wrap(Key key)
-        throws IllegalBlockSizeException, InvalidKeyException {
-        byte[] result = null;
-
-        try {
-            byte[] encodedKey = key.getEncoded();
-            if ((encodedKey == null) || (encodedKey.length == 0)) {
-                throw new InvalidKeyException("Cannot get an encoding of " +
-                                              "the key to be wrapped");
-            }
-
-            result = doFinal(encodedKey, 0, encodedKey.length);
-        } catch (BadPaddingException e) {
-            // Should never happen
-        }
-
-        return result;
-    }
-
-    /**
-     * Unwrap a previously wrapped key.
-     *
-     * @param wrappedKey the key to be unwrapped.
-     *
-     * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
-     *
-     * @param wrappedKeyType the type of the wrapped key.
-     * This is one of <code>Cipher.SECRET_KEY</code>,
-     * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
-     *
-     * @return the unwrapped key.
-     *
-     * @exception NoSuchAlgorithmException if no installed providers
-     * can create keys of type <code>wrappedKeyType</code> for the
-     * <code>wrappedKeyAlgorithm</code>.
-     *
-     * @exception InvalidKeyException if <code>wrappedKey</code> does not
-     * represent a wrapped key of type <code>wrappedKeyType</code> for
-     * the <code>wrappedKeyAlgorithm</code>.
-     */
-    Key unwrap(byte[] wrappedKey,
-               String wrappedKeyAlgorithm,
-               int wrappedKeyType)
-        throws InvalidKeyException, NoSuchAlgorithmException {
-        byte[] encodedKey;
-        try {
-            encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
-        } catch (BadPaddingException ePadding) {
-            throw new InvalidKeyException("The wrapped key is not padded " +
-                                          "correctly");
-        } catch (IllegalBlockSizeException eBlockSize) {
-            throw new InvalidKeyException("The wrapped key does not have " +
-                                          "the correct length");
-        }
-        return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
-                                          wrappedKeyType);
-    }
-}
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java	Mon Jun 19 11:29:42 2017 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.lang.ref.Reference;
 import java.security.MessageDigest;
 import java.security.KeyRep;
 import java.security.spec.InvalidKeySpecException;
@@ -73,7 +74,11 @@
     }
 
     public byte[] getEncoded() {
-        return this.key.clone();
+        // The key is zeroized by finalize()
+        // The reachability fence ensures finalize() isn't called early
+        byte[] result = key.clone();
+        Reference.reachabilityFence(this);
+        return result;
     }
 
     public String getAlgorithm() {
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -260,7 +260,7 @@
 
         if (algo.equals("DES")) {
             // P || S (password concatenated with salt)
-            byte[] concat = new byte[passwdBytes.length + salt.length];
+            byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
             System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
             java.util.Arrays.fill(passwdBytes, (byte)0x00);
             System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -26,6 +26,7 @@
 package com.sun.crypto.provider;
 
 import java.io.ObjectStreamException;
+import java.lang.ref.Reference;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
@@ -196,7 +197,11 @@
     }
 
     public byte[] getEncoded() {
-        return key.clone();
+        // The key is zeroized by finalize()
+        // The reachability fence ensures finalize() isn't called early
+        byte[] result = key.clone();
+        Reference.reachabilityFence(this);
+        return result;
     }
 
     public String getAlgorithm() {
@@ -208,7 +213,11 @@
     }
 
     public char[] getPassword() {
-        return passwd.clone();
+        // The password is zeroized by finalize()
+        // The reachability fence ensures finalize() isn't called early
+        char[] result = passwd.clone();
+        Reference.reachabilityFence(this);
+        return result;
     }
 
     public byte[] getSalt() {
--- a/src/java.base/share/classes/com/sun/crypto/provider/PKCS5Padding.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PKCS5Padding.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,6 +26,7 @@
 package com.sun.crypto.provider;
 
 import javax.crypto.ShortBufferException;
+import java.util.Arrays;
 
 /**
  * This class implements padding as specified in the PKCS#5 standard.
@@ -63,14 +64,13 @@
         if (in == null)
             return;
 
-        if ((off + len) > in.length) {
+        int idx = Math.addExact(off, len);
+        if (idx > in.length) {
             throw new ShortBufferException("Buffer too small to hold padding");
         }
 
         byte paddingOctet = (byte) (len & 0xff);
-        for (int i = 0; i < len; i++) {
-            in[i + off] = paddingOctet;
-        }
+        Arrays.fill(in, off, idx, paddingOctet);
         return;
     }
 
@@ -92,25 +92,24 @@
             (len == 0)) { // this can happen if input is really a padded buffer
             return 0;
         }
-
-        byte lastByte = in[off + len - 1];
+        int idx = Math.addExact(off, len);
+        byte lastByte = in[idx - 1];
         int padValue = (int)lastByte & 0x0ff;
         if ((padValue < 0x01)
             || (padValue > blockSize)) {
             return -1;
         }
 
-        int start = off + len - ((int)lastByte & 0x0ff);
+        int start = idx - padValue;
         if (start < off) {
             return -1;
         }
 
-        for (int i = 0; i < ((int)lastByte & 0x0ff); i++) {
-            if (in[start+i] != lastByte) {
+        for (int i = start; i < idx; i++) {
+            if (in[i] != lastByte) {
                 return -1;
             }
         }
-
         return start;
     }
 
--- a/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -38,6 +38,7 @@
 import java.net.URL;
 import java.net.Proxy;
 import java.net.ProtocolException;
+import java.net.MalformedURLException;
 import java.io.*;
 import java.net.Authenticator;
 import javax.net.ssl.*;
@@ -78,10 +79,18 @@
         this(u, null, handler);
     }
 
+    static URL checkURL(URL u) throws IOException {
+        if (u != null) {
+            if (u.toExternalForm().indexOf('\n') > -1) {
+                throw new MalformedURLException("Illegal character in URL");
+            }
+        }
+        return u;
+    }
 // For both copies of the file, uncomment one line and comment the other
 //    HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
     HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
-        super(u);
+        super(checkURL(u));
         delegate = new DelegateHttpsURLConnection(url, p, handler, this);
     }
 
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Mon Jun 19 11:29:42 2017 -0700
@@ -44,8 +44,6 @@
 
 import static java.io.ObjectStreamClass.processQueue;
 
-import jdk.internal.misc.ObjectStreamClassValidator;
-import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.Unsafe;
 import sun.reflect.misc.ReflectUtil;
 
@@ -1740,9 +1738,6 @@
                 throw new StreamCorruptedException(
                     String.format("invalid type code: %02X", tc));
         }
-        if (descriptor != null) {
-            validateDescriptor(descriptor);
-        }
         return descriptor;
     }
 
@@ -3977,21 +3972,4 @@
             throw new AssertionError();
         }
     }
-
-    private void validateDescriptor(ObjectStreamClass descriptor) {
-        ObjectStreamClassValidator validating = validator;
-        if (validating != null) {
-            validating.validateDescriptor(descriptor);
-        }
-    }
-
-    // controlled access to ObjectStreamClassValidator
-    private volatile ObjectStreamClassValidator validator;
-
-    private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
-        ois.validator = validator;
-    }
-    static {
-        SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
-    }
 }
--- a/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Jun 19 11:29:42 2017 -0700
@@ -32,14 +32,19 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
+import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.PermissionCollection;
+import java.security.Permissions;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -53,7 +58,8 @@
 import jdk.internal.reflect.Reflection;
 import jdk.internal.reflect.ReflectionFactory;
 import sun.reflect.misc.ReflectUtil;
-
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaSecurityAccess;
 import static java.io.ObjectStreamField.*;
 
 /**
@@ -176,6 +182,9 @@
 
     /** serialization-appropriate constructor, or null if none */
     private Constructor<?> cons;
+    /** protection domains that need to be checked when calling the constructor */
+    private ProtectionDomain[] domains;
+
     /** class-defined writeObject method, or null if none */
     private Method writeObjectMethod;
     /** class-defined readObject method, or null if none */
@@ -508,6 +517,7 @@
                             cl, "readObjectNoData", null, Void.TYPE);
                         hasWriteObjectData = (writeObjectMethod != null);
                     }
+                    domains = getProtectionDomains(cons, cl);
                     writeReplaceMethod = getInheritableMethod(
                         cl, "writeReplace", null, Object.class);
                     readResolveMethod = getInheritableMethod(
@@ -551,6 +561,65 @@
     }
 
     /**
+     * Creates a PermissionDomain that grants no permission.
+     */
+    private ProtectionDomain noPermissionsDomain() {
+        PermissionCollection perms = new Permissions();
+        perms.setReadOnly();
+        return new ProtectionDomain(null, perms);
+    }
+
+    /**
+     * Aggregate the ProtectionDomains of all the classes that separate
+     * a concrete class {@code cl} from its ancestor's class declaring
+     * a constructor {@code cons}.
+     *
+     * If {@code cl} is defined by the boot loader, or the constructor
+     * {@code cons} is declared by {@code cl}, or if there is no security
+     * manager, then this method does nothing and {@code null} is returned.
+     *
+     * @param cons A constructor declared by {@code cl} or one of its
+     *             ancestors.
+     * @param cl A concrete class, which is either the class declaring
+     *           the constructor {@code cons}, or a serializable subclass
+     *           of that class.
+     * @return An array of ProtectionDomain representing the set of
+     *         ProtectionDomain that separate the concrete class {@code cl}
+     *         from its ancestor's declaring {@code cons}, or {@code null}.
+     */
+    private ProtectionDomain[] getProtectionDomains(Constructor<?> cons,
+                                                    Class<?> cl) {
+        ProtectionDomain[] domains = null;
+        if (cons != null && cl.getClassLoader() != null
+                && System.getSecurityManager() != null) {
+            Class<?> cls = cl;
+            Class<?> fnscl = cons.getDeclaringClass();
+            Set<ProtectionDomain> pds = null;
+            while (cls != fnscl) {
+                ProtectionDomain pd = cls.getProtectionDomain();
+                if (pd != null) {
+                    if (pds == null) pds = new HashSet<>();
+                    pds.add(pd);
+                }
+                cls = cls.getSuperclass();
+                if (cls == null) {
+                    // that's not supposed to happen
+                    // make a ProtectionDomain with no permission.
+                    // should we throw instead?
+                    if (pds == null) pds = new HashSet<>();
+                    else pds.clear();
+                    pds.add(noPermissionsDomain());
+                    break;
+                }
+            }
+            if (pds != null) {
+                domains = pds.toArray(new ProtectionDomain[0]);
+            }
+        }
+        return domains;
+    }
+
+    /**
      * Initializes class descriptor representing a proxy class.
      */
     void initProxy(Class<?> cl,
@@ -580,6 +649,7 @@
             writeReplaceMethod = localDesc.writeReplaceMethod;
             readResolveMethod = localDesc.readResolveMethod;
             deserializeEx = localDesc.deserializeEx;
+            domains = localDesc.domains;
             cons = localDesc.cons;
         }
         fieldRefl = getReflector(fields, localDesc);
@@ -666,6 +736,7 @@
             if (deserializeEx == null) {
                 deserializeEx = localDesc.deserializeEx;
             }
+            domains = localDesc.domains;
             cons = localDesc.cons;
         }
 
@@ -1006,7 +1077,35 @@
         requireInitialized();
         if (cons != null) {
             try {
-                return cons.newInstance();
+                if (domains == null || domains.length == 0) {
+                    return cons.newInstance();
+                } else {
+                    JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess();
+                    PrivilegedAction<?> pea = () -> {
+                        try {
+                            return cons.newInstance();
+                        } catch (InstantiationException
+                                 | InvocationTargetException
+                                 | IllegalAccessException x) {
+                            throw new UndeclaredThrowableException(x);
+                        }
+                    }; // Can't use PrivilegedExceptionAction with jsa
+                    try {
+                        return jsa.doIntersectionPrivilege(pea,
+                                   AccessController.getContext(),
+                                   new AccessControlContext(domains));
+                    } catch (UndeclaredThrowableException x) {
+                        Throwable cause = x.getCause();
+                        if (cause instanceof InstantiationException)
+                            throw (InstantiationException) cause;
+                        if (cause instanceof InvocationTargetException)
+                            throw (InvocationTargetException) cause;
+                        if (cause instanceof IllegalAccessException)
+                            throw (IllegalAccessException) cause;
+                        // not supposed to happen
+                        throw x;
+                    }
+                }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
                 throw new InternalError(ex);
--- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Mon Jun 19 11:29:42 2017 -0700
@@ -80,13 +80,20 @@
             mtype = mtype.insertParameterTypes(0, receiver);
         }
         if (!member.isField()) {
-            if (refKind == REF_invokeSpecial) {
-                member = member.asSpecial();
-                LambdaForm lform = preparedLambdaForm(member);
-                return new Special(mtype, lform, member);
-            } else {
-                LambdaForm lform = preparedLambdaForm(member);
-                return new DirectMethodHandle(mtype, lform, member);
+            switch (refKind) {
+                case REF_invokeSpecial: {
+                    member = member.asSpecial();
+                    LambdaForm lform = preparedLambdaForm(member);
+                    return new Special(mtype, lform, member);
+                }
+                case REF_invokeInterface: {
+                    LambdaForm lform = preparedLambdaForm(member);
+                    return new Interface(mtype, lform, member, receiver);
+                }
+                default: {
+                    LambdaForm lform = preparedLambdaForm(member);
+                    return new DirectMethodHandle(mtype, lform, member);
+                }
             }
         } else {
             LambdaForm lform = preparedFieldLambdaForm(member);
@@ -190,6 +197,7 @@
     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
         boolean needsInit = (which == LF_INVSTATIC_INIT);
         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
+        boolean needsReceiverCheck = (which == LF_INVINTERFACE);
         String linkerName;
         LambdaForm.Kind kind;
         switch (which) {
@@ -219,6 +227,7 @@
         int nameCursor = ARG_LIMIT;
         final int NEW_OBJ     = (doesAlloc ? nameCursor++ : -1);
         final int GET_MEMBER  = nameCursor++;
+        final int CHECK_RECEIVER = (needsReceiverCheck ? nameCursor++ : -1);
         final int LINKER_CALL = nameCursor++;
         Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
         assert(names.length == nameCursor);
@@ -233,6 +242,10 @@
         }
         assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
+        if (needsReceiverCheck) {
+            names[CHECK_RECEIVER] = new Name(NF_checkReceiver, names[DMH_THIS], names[ARG_BASE]);
+            outArgs[0] = names[CHECK_RECEIVER];
+        }
         assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
         int result = LAST_RESULT;
         if (doesAlloc) {
@@ -377,6 +390,29 @@
         }
     }
 
+    /** This subclass represents invokeinterface instructions. */
+    static class Interface extends DirectMethodHandle {
+        private final Class<?> refc;
+        private Interface(MethodType mtype, LambdaForm form, MemberName member, Class<?> refc) {
+            super(mtype, form, member);
+            assert refc.isInterface() : refc;
+            this.refc = refc;
+        }
+        @Override
+        MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+            return new Interface(mt, lf, member, refc);
+        }
+
+        Object checkReceiver(Object recv) {
+            if (!refc.isInstance(recv)) {
+                String msg = String.format("Class %s does not implement the requested interface %s",
+                        recv.getClass().getName(), refc.getName());
+                throw new IncompatibleClassChangeError(msg);
+            }
+            return recv;
+        }
+    }
+
     /** This subclass handles constructor references. */
     static class Constructor extends DirectMethodHandle {
         final MemberName initMethod;
@@ -729,7 +765,8 @@
             NF_checkCast,
             NF_allocateInstance,
             NF_constructorMethod,
-            NF_UNSAFE;
+            NF_UNSAFE,
+            NF_checkReceiver;
     static {
         try {
             NamedFunction nfs[] = {
@@ -754,7 +791,9 @@
                     NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
                             .getDeclaredMethod("constructorMethod", Object.class)),
                     NF_UNSAFE = new NamedFunction(new MemberName(MethodHandleStatics.class
-                            .getDeclaredField("UNSAFE")))
+                            .getDeclaredField("UNSAFE"))),
+                    NF_checkReceiver = new NamedFunction(new MemberName(Interface.class
+                            .getDeclaredMethod("checkReceiver", Object.class)))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/src/java.base/share/classes/java/security/CodeSource.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/security/CodeSource.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -560,6 +560,7 @@
     {
         CertificateFactory cf;
         Hashtable<String, CertificateFactory> cfs = null;
+        List<java.security.cert.Certificate> certList = null;
 
         ois.defaultReadObject(); // location
 
@@ -569,7 +570,7 @@
             // we know of 3 different cert types: X.509, PGP, SDSI, which
             // could all be present in the stream at the same time
             cfs = new Hashtable<>(3);
-            this.certs = new java.security.cert.Certificate[size];
+            certList = new ArrayList<>(size > 20 ? 20 : size);
         }
 
         for (int i = 0; i < size; i++) {
@@ -600,13 +601,17 @@
             ois.readFully(encoded);
             ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
             try {
-                this.certs[i] = cf.generateCertificate(bais);
+                certList.add(cf.generateCertificate(bais));
             } catch (CertificateException ce) {
                 throw new IOException(ce.getMessage());
             }
             bais.close();
         }
 
+        if (certList != null) {
+            this.certs = certList.toArray(
+                    new java.security.cert.Certificate[size]);
+        }
         // Deserialize array of code signers (if any)
         try {
             this.signers = ((CodeSigner[])ois.readObject()).clone();
--- a/src/java.base/share/classes/java/util/SimpleTimeZone.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/util/SimpleTimeZone.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -41,6 +41,7 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import sun.util.calendar.CalendarSystem;
 import sun.util.calendar.CalendarUtils;
 import sun.util.calendar.BaseCalendar;
@@ -1278,6 +1279,9 @@
      */
     private int serialVersionOnStream = currentSerialVersion;
 
+    // Maximum number of rules.
+    private static final int MAX_RULE_NUM = 6;
+
     private synchronized void invalidateCache() {
         cacheYear = startYear - 1;
         cacheStart = cacheEnd = 0;
@@ -1569,7 +1573,7 @@
      */
     private byte[] packRules()
     {
-        byte[] rules = new byte[6];
+        byte[] rules = new byte[MAX_RULE_NUM];
         rules[0] = (byte)startDay;
         rules[1] = (byte)startDayOfWeek;
         rules[2] = (byte)endDay;
@@ -1594,7 +1598,7 @@
         endDayOfWeek   = rules[3];
 
         // As of serial version 2, include time modes
-        if (rules.length >= 6) {
+        if (rules.length >= MAX_RULE_NUM) {
             startTimeMode = rules[4];
             endTimeMode   = rules[5];
         }
@@ -1691,9 +1695,13 @@
             // store the actual rules (which have not be made compatible with 1.1)
             // in the optional area.  Read them in here and parse them.
             int length = stream.readInt();
-            byte[] rules = new byte[length];
-            stream.readFully(rules);
-            unpackRules(rules);
+            if (length <= MAX_RULE_NUM) {
+                byte[] rules = new byte[length];
+                stream.readFully(rules);
+                unpackRules(rules);
+            } else {
+                throw new InvalidObjectException("Too many rules: " + length);
+            }
         }
 
         if (serialVersionOnStream >= 2) {
--- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Mon Jun 19 11:29:42 2017 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.ConcurrentModificationException;
 import java.util.HashSet;
@@ -584,6 +587,9 @@
     private static final RuntimePermission shutdownPerm =
         new RuntimePermission("modifyThread");
 
+    /* The context to be used when executing the finalizer, or null. */
+    private final AccessControlContext acc;
+
     /**
      * Class Worker mainly maintains interrupt control state for
      * threads running tasks, along with other minor bookkeeping.
@@ -1326,6 +1332,9 @@
             throw new IllegalArgumentException();
         if (workQueue == null || threadFactory == null || handler == null)
             throw new NullPointerException();
+        this.acc = System.getSecurityManager() == null ?
+                null :
+                AccessController.getContext();
         this.corePoolSize = corePoolSize;
         this.maximumPoolSize = maximumPoolSize;
         this.workQueue = workQueue;
@@ -1491,6 +1500,9 @@
      * Invokes {@code shutdown} when this executor is no longer
      * referenced and it has no threads.
      *
+     * <p>This method is invoked with privileges that are restricted by
+     * the security context of the caller that invokes the constructor.
+     *
      * @deprecated The {@code finalize} method has been deprecated.
      *     Subclasses that override {@code finalize} in order to perform cleanup
      *     should be modified to use alternative cleanup mechanisms and
@@ -1502,7 +1514,13 @@
      */
     @Deprecated(since="9")
     protected void finalize() {
-        shutdown();
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null || acc == null) {
+            shutdown();
+        } else {
+            PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
+            AccessController.doPrivileged(pa, acc);
+        }
     }
 
     /**
--- a/src/java.base/share/classes/java/util/jar/JarVerifier.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -180,10 +180,12 @@
 
         // only set the jev object for entries that have a signature
         // (either verified or not)
-        if (sigFileSigners.get(name) != null ||
-                verifiedSigners.get(name) != null) {
-            mev.setEntry(name, je);
-            return;
+        if (!name.equals(JarFile.MANIFEST_NAME)) {
+            if (sigFileSigners.get(name) != null ||
+                    verifiedSigners.get(name) != null) {
+                mev.setEntry(name, je);
+                return;
+            }
         }
 
         // don't compute the digest for this entry
--- a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Mon Jun 19 11:29:42 2017 -0700
@@ -69,7 +69,6 @@
     private static JavaAWTAccess javaAWTAccess;
     private static JavaAWTFontAccess javaAWTFontAccess;
     private static JavaBeansAccess javaBeansAccess;
-    private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
     private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -304,17 +303,6 @@
         javaUtilResourceBundleAccess = access;
     }
 
-    public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
-        if (javaObjectInputStreamAccess == null) {
-            unsafe.ensureClassInitialized(ObjectInputStream.class);
-        }
-        return javaObjectInputStreamAccess;
-    }
-
-    public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
-        javaObjectInputStreamAccess = access;
-    }
-
     public static void setJavaIORandomAccessFileAccess(JavaIORandomAccessFileAccess jirafa) {
         javaIORandomAccessFileAccess = jirafa;
     }
--- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Jun 19 11:29:42 2017 -0700
@@ -843,18 +843,36 @@
         this(u, null, handler);
     }
 
-    public HttpURLConnection(URL u, String host, int port) {
-        this(u, new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(host, port)));
+    private static String checkHost(String h) throws IOException {
+        if (h != null) {
+            if (h.indexOf('\n') > -1) {
+                throw new MalformedURLException("Illegal character in host");
+            }
+        }
+        return h;
+    }
+    public HttpURLConnection(URL u, String host, int port) throws IOException {
+        this(u, new Proxy(Proxy.Type.HTTP,
+                InetSocketAddress.createUnresolved(checkHost(host), port)));
     }
 
     /** this constructor is used by other protocol handlers such as ftp
         that want to use http to fetch urls on their behalf.*/
-    public HttpURLConnection(URL u, Proxy p) {
+    public HttpURLConnection(URL u, Proxy p) throws IOException {
         this(u, p, new Handler());
     }
 
-    protected HttpURLConnection(URL u, Proxy p, Handler handler) {
-        super(u);
+    private static URL checkURL(URL u) throws IOException {
+        if (u != null) {
+            if (u.toExternalForm().indexOf('\n') > -1) {
+                throw new MalformedURLException("Illegal character in URL");
+            }
+        }
+        return u;
+    }
+    protected HttpURLConnection(URL u, Proxy p, Handler handler)
+            throws IOException {
+        super(checkURL(u));
         requests = new MessageHeader();
         responses = new MessageHeader();
         userHeaders = new MessageHeader();
--- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -38,6 +38,7 @@
 import java.net.URL;
 import java.net.Proxy;
 import java.net.ProtocolException;
+import java.net.MalformedURLException;
 import java.io.*;
 import java.net.Authenticator;
 import javax.net.ssl.*;
@@ -80,10 +81,18 @@
         this(u, null, handler);
     }
 
+    static URL checkURL(URL u) throws IOException {
+        if (u != null) {
+            if (u.toExternalForm().indexOf('\n') > -1) {
+                throw new MalformedURLException("Illegal character in URL");
+            }
+        }
+        return u;
+    }
 // For both copies of the file, uncomment one line and comment the other
     HttpsURLConnectionImpl(URL u, Proxy p, Handler handler) throws IOException {
 //    HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
-        super(u);
+        super(checkURL(u));
         delegate = new DelegateHttpsURLConnection(url, p, handler, this);
     }
 
--- a/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -246,13 +246,16 @@
     abstract void shutdownHandlerTasks();
 
     private void shutdownExecutors() {
-        AccessController.doPrivileged(new PrivilegedAction<>() {
-            public Void run() {
-                pool.executor().shutdown();
-                timeoutExecutor.shutdown();
-                return null;
-            }
-        });
+        AccessController.doPrivileged(
+            new PrivilegedAction<>() {
+                public Void run() {
+                    pool.executor().shutdown();
+                    timeoutExecutor.shutdown();
+                    return null;
+                }
+            },
+            null,
+            new RuntimePermission("modifyThread"));
     }
 
     @Override
--- a/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,6 +32,7 @@
 import java.security.KeyRep;
 import java.security.PrivateKey;
 import java.security.KeyFactory;
+import java.security.MessageDigest;
 import java.security.Security;
 import java.security.Provider;
 import java.security.InvalidKeyException;
@@ -419,18 +420,9 @@
             // that encoding
             byte[] b2 = ((Key)object).getEncoded();
 
-            // do the comparison
-            int i;
-            if (b1.length != b2.length)
-                return false;
-            for (i = 0; i < b1.length; i++) {
-                if (b1[i] != b2[i]) {
-                    return false;
-                }
-            }
-            return true;
+            // time-constant comparison
+            return MessageDigest.isEqual(b1, b2);
         }
-
         return false;
     }
 
--- a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java	Mon Jun 19 11:29:42 2017 -0700
@@ -323,6 +323,12 @@
                 data = content.getContentBytes();
             }
 
+            Timestamp timestamp = null;
+            try {
+                timestamp = getTimestamp();
+            } catch (Exception ignore) {
+            }
+
             ConstraintsParameters cparams =
                     new ConstraintsParameters(timestamp);
             String digestAlgname = getDigestAlgorithmId().getName();
--- a/src/java.base/share/classes/sun/security/provider/DSA.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/provider/DSA.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -64,6 +64,13 @@
     /* Are we debugging? */
     private static final boolean debug = false;
 
+    /* The number of bits used in exponent blinding */
+    private static final int BLINDING_BITS = 7;
+
+    /* The constant component of the exponent blinding value */
+    private static final BigInteger BLINDING_CONSTANT =
+        BigInteger.valueOf(1 << BLINDING_BITS);
+
     /* The parameter object */
     private DSAParams params;
 
@@ -368,8 +375,19 @@
         return null;
     }
 
+
     private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
                          BigInteger k) {
+
+        // exponent blinding to hide information from timing channel
+        SecureRandom random = getSigningRandom();
+        // start with a random blinding component
+        BigInteger blindingValue = new BigInteger(BLINDING_BITS, random);
+        // add the fixed blinding component
+        blindingValue = blindingValue.add(BLINDING_CONSTANT);
+        // replace k with a blinded value that is congruent (mod q)
+        k = k.add(q.multiply(blindingValue));
+
         BigInteger temp = g.modPow(k, p);
         return temp.mod(q);
     }
@@ -434,43 +452,8 @@
         byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
 
         random.nextBytes(kValue);
-        BigInteger k = new BigInteger(1, kValue).mod(
+        return new BigInteger(1, kValue).mod(
                 q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
-
-        // Using an equivalent exponent of fixed length (same as q or 1 bit
-        // less than q) to keep the kG timing relatively constant.
-        //
-        // Note that this is an extra step on top of the approach defined in
-        // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K.
-        k = k.add(q).divide(BigInteger.TWO);
-
-        // An alternative implementation based on FIPS 186-4 AppendixB2.2
-        // with fixed-length K.
-        //
-        // Please keep it here as we may need to switch to it in the future.
-        //
-        // SecureRandom random = getSigningRandom();
-        // byte[] kValue = new byte[(q.bitLength() + 7)/8];
-        // BigInteger d = q.subtract(BigInteger.TWO);
-        // BigInteger k;
-        // do {
-        //     random.nextBytes(kValue);
-        //     BigInteger c = new BigInteger(1, kValue);
-        //     if (c.compareTo(d) <= 0) {
-        //         k = c.add(BigInteger.ONE);
-        //         // Using an equivalent exponent of fixed length to keep
-        //         // the g^k timing relatively constant.
-        //         //
-        //         // Note that this is an extra step on top of the approach
-        //         // defined in FIPS 186-4 AppendixB.2.2 so as to make a
-        //         // fixed length K.
-        //         if (k.bitLength() >= q.bitLength()) {
-        //             break;
-        //         }
-        //     }
-        // } while (true);
-
-        return k;
     }
 
     // Use the application-specified SecureRandom Object if provided.
--- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Mon Jun 19 11:29:42 2017 -0700
@@ -344,7 +344,7 @@
 
                 // add the algorithm checker
                 checkers.add(new AlgorithmChecker(builder.trustAnchor,
-                        buildParams.date(), null));
+                        buildParams.date(), buildParams.variant()));
 
                 BasicChecker basicChecker = null;
                 if (nextState.keyParamsNeeded()) {
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -44,6 +44,7 @@
 import static sun.security.ssl.CipherSuite.MacAlg.*;
 import static sun.security.ssl.CipherSuite.BulkCipher.*;
 import static sun.security.ssl.JsseJce.*;
+import static sun.security.ssl.NamedGroupType.*;
 
 /**
  * An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
@@ -376,38 +377,38 @@
     static enum KeyExchange {
 
         // key exchange algorithms
-        K_NULL       ("NULL",       false,      false),
-        K_RSA        ("RSA",        true,       false),
-        K_RSA_EXPORT ("RSA_EXPORT", true,       false),
-        K_DH_RSA     ("DH_RSA",     false,      false),
-        K_DH_DSS     ("DH_DSS",     false,      false),
-        K_DHE_DSS    ("DHE_DSS",    true,       false),
-        K_DHE_RSA    ("DHE_RSA",    true,       false),
-        K_DH_ANON    ("DH_anon",    true,       false),
+        K_NULL       ("NULL",       false,      NAMED_GROUP_NONE),
+        K_RSA        ("RSA",        true,       NAMED_GROUP_NONE),
+        K_RSA_EXPORT ("RSA_EXPORT", true,       NAMED_GROUP_NONE),
+        K_DH_RSA     ("DH_RSA",     false,      NAMED_GROUP_NONE),
+        K_DH_DSS     ("DH_DSS",     false,      NAMED_GROUP_NONE),
+        K_DHE_DSS    ("DHE_DSS",    true,       NAMED_GROUP_FFDHE),
+        K_DHE_RSA    ("DHE_RSA",    true,       NAMED_GROUP_FFDHE),
+        K_DH_ANON    ("DH_anon",    true,       NAMED_GROUP_FFDHE),
 
-        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC, true),
-        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC, true),
-        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
-        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC, true),
-        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC, true),
+        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC, NAMED_GROUP_ECDHE),
+        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC, NAMED_GROUP_ECDHE),
+        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
+        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC, NAMED_GROUP_ECDHE),
+        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC, NAMED_GROUP_ECDHE),
 
         // Kerberos cipher suites
-        K_KRB5       ("KRB5", true,             false),
-        K_KRB5_EXPORT("KRB5_EXPORT", true,      false),
+        K_KRB5       ("KRB5", true,             NAMED_GROUP_NONE),
+        K_KRB5_EXPORT("KRB5_EXPORT", true,      NAMED_GROUP_NONE),
 
         // renegotiation protection request signaling cipher suite
-        K_SCSV       ("SCSV",        true,      false);
+        K_SCSV       ("SCSV",        true,      NAMED_GROUP_NONE);
 
         // name of the key exchange algorithm, e.g. DHE_DSS
         final String name;
         final boolean allowed;
-        final boolean isEC;
+        final NamedGroupType groupType;
         private final boolean alwaysAvailable;
 
-        KeyExchange(String name, boolean allowed, boolean isEC) {
+        KeyExchange(String name, boolean allowed, NamedGroupType groupType) {
             this.name = name;
             this.allowed = allowed;
-            this.isEC = isEC;
+            this.groupType = groupType;
             this.alwaysAvailable = allowed &&
                 (!name.startsWith("EC")) && (!name.startsWith("KRB"));
         }
@@ -417,7 +418,7 @@
                 return true;
             }
 
-            if (isEC) {
+            if (groupType == NAMED_GROUP_ECDHE) {
                 return (allowed && JsseJce.isEcAvailable());
             } else if (name.startsWith("KRB")) {
                 return (allowed && JsseJce.isKerberosAvailable());
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -30,6 +30,7 @@
 import java.util.*;
 
 import javax.net.ssl.SSLException;
+import static sun.security.ssl.NamedGroupType.*;
 
 /**
  * A list of CipherSuites. Also maintains the lists of supported and
@@ -42,15 +43,16 @@
 
     private final Collection<CipherSuite> cipherSuites;
     private String[] suiteNames;
-
-    // flag indicating whether this list contains any ECC ciphersuites.
-    // null if not yet checked.
-    private volatile Boolean containsEC;
+    private final EnumSet<NamedGroupType> groupsTypes =
+            EnumSet.noneOf(NamedGroupType.class);
 
     // for use by buildAvailableCache() and
     // Handshaker.getKickstartMessage() only
     CipherSuiteList(Collection<CipherSuite> cipherSuites) {
         this.cipherSuites = cipherSuites;
+        for (CipherSuite suite : cipherSuites) {
+            updateGroupTypes(suite);
+        }
     }
 
     /**
@@ -59,6 +61,7 @@
     CipherSuiteList(CipherSuite suite) {
         cipherSuites = new ArrayList<CipherSuite>(1);
         cipherSuites.add(suite);
+        updateGroupTypes(suite);
     }
 
     /**
@@ -82,6 +85,7 @@
                     + suiteName + " with currently installed providers");
             }
             cipherSuites.add(suite);
+            updateGroupTypes(suite);
         }
     }
 
@@ -97,7 +101,20 @@
         }
         cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
         for (int i = 0; i < bytes.length; i += 2) {
-            cipherSuites.add(CipherSuite.valueOf(bytes[i], bytes[i+1]));
+            CipherSuite suite = CipherSuite.valueOf(bytes[i], bytes[i+1]);
+            cipherSuites.add(suite);
+            updateGroupTypes(suite);
+        }
+    }
+
+    // Please don't use this method except constructors.
+    private void updateGroupTypes(CipherSuite cipherSuite) {
+        if (cipherSuite.keyExchange != null && (!cipherSuite.exportable)) {
+            NamedGroupType groupType = cipherSuite.keyExchange.groupType;
+            if ((groupType != NAMED_GROUP_NONE) &&
+                    (!groupsTypes.contains(groupType))) {
+                groupsTypes.add(groupType);
+            }
         }
     }
 
@@ -108,20 +125,9 @@
         return cipherSuites.contains(suite);
     }
 
-    // Return whether this list contains any ECC ciphersuites
-    boolean containsEC() {
-        if (containsEC == null) {
-            for (CipherSuite c : cipherSuites) {
-                if (c.keyExchange.isEC) {
-                    containsEC = true;
-                    return true;
-                }
-            }
-
-            containsEC = false;
-        }
-
-        return containsEC;
+    // Return whether this list contains cipher suites of a named group type.
+    boolean contains(NamedGroupType groupType) {
+        return groupsTypes.contains(groupType);
     }
 
     /**
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -148,6 +148,10 @@
     private static final boolean enableMFLExtension =
             Debug.getBooleanProperty("jsse.enableMFLExtension", false);
 
+    // To switch off the supported_groups extension for DHE cipher suite.
+    private static final boolean enableFFDHE =
+            Debug.getBooleanProperty("jsse.enableFFDHE", true);
+
     // Whether an ALPN extension was sent in the ClientHello
     private boolean alpnActive = false;
 
@@ -767,13 +771,15 @@
                     fatalSE(Alerts.alert_unexpected_message, "Server set " +
                             type + " extension when not requested by client");
                 }
-            } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
+            } else if ((type != ExtensionType.EXT_SUPPORTED_GROUPS)
                     && (type != ExtensionType.EXT_EC_POINT_FORMATS)
                     && (type != ExtensionType.EXT_SERVER_NAME)
                     && (type != ExtensionType.EXT_ALPN)
                     && (type != ExtensionType.EXT_RENEGOTIATION_INFO)
                     && (type != ExtensionType.EXT_STATUS_REQUEST)
                     && (type != ExtensionType.EXT_STATUS_REQUEST_V2)) {
+                // Note: Better to check client requested extensions rather
+                // than all supported extensions.
                 fatalSE(Alerts.alert_unsupported_extension,
                     "Server sent an unsupported extension: " + type);
             }
@@ -823,6 +829,17 @@
      * our own D-H algorithm object so we can defer key calculations
      * until after we've sent the client key exchange message (which
      * gives client and server some useful parallelism).
+     *
+     * Note per section 3 of RFC 7919, if the server is not compatible with
+     * FFDHE specification, the client MAY decide to continue the connection
+     * if the selected DHE group is acceptable under local policy, or it MAY
+     * decide to terminate the connection with a fatal insufficient_security
+     * (71) alert.  The algorithm constraints mechanism is JDK local policy
+     * used for additional DHE parameters checking.  So this implementation
+     * does not check the server compatibility and just pass to the local
+     * algorithm constraints checking.  The client will continue the
+     * connection if the server selected DHE group is acceptable by the
+     * specified algorithm constraints.
      */
     private void serverKeyExchange(DH_ServerKeyExchange mesg)
             throws IOException {
@@ -1495,14 +1512,17 @@
                 sslContext.getSecureRandom(), maxProtocolVersion,
                 sessionId, cipherSuites, isDTLS);
 
-        // add elliptic curves and point format extensions
-        if (cipherSuites.containsEC()) {
-            EllipticCurvesExtension ece =
-                EllipticCurvesExtension.createExtension(algorithmConstraints);
-            if (ece != null) {
-                clientHelloMessage.extensions.add(ece);
+        // Add named groups extension for ECDHE and FFDHE if necessary.
+        SupportedGroupsExtension sge =
+                SupportedGroupsExtension.createExtension(
+                        algorithmConstraints,
+                        cipherSuites, enableFFDHE);
+        if (sge != null) {
+            clientHelloMessage.extensions.add(sge);
+            // Add elliptic point format extensions
+            if (cipherSuites.contains(NamedGroupType.NAMED_GROUP_ECDHE)) {
                 clientHelloMessage.extensions.add(
-                        EllipticPointFormatsExtension.DEFAULT);
+                    EllipticPointFormatsExtension.DEFAULT);
             }
         }
 
--- a/src/java.base/share/classes/sun/security/ssl/DHCrypt.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHCrypt.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,14 +26,8 @@
 
 package sun.security.ssl;
 
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
 import java.math.BigInteger;
 import java.security.*;
-import java.io.IOException;
 import javax.net.ssl.SSLHandshakeException;
 import javax.crypto.SecretKey;
 import javax.crypto.KeyAgreement;
@@ -101,7 +95,7 @@
      */
     DHCrypt(int keyLength, SecureRandom random) {
         this(keyLength,
-                ParametersHolder.definedParams.get(keyLength), random);
+            PredefinedDHParameterSpecs.definedParams.get(keyLength), random);
     }
 
     /**
@@ -116,6 +110,14 @@
     }
 
     /**
+     * Generate a Diffie-Hellman keypair using the named group.
+     */
+    DHCrypt(NamedGroup namedGroup, SecureRandom random) {
+        this(-1,        // The length (-1) is not used in the implementation.
+            SupportedGroupsExtension.getDHParameterSpec(namedGroup), random);
+    }
+
+    /**
      * Generate a Diffie-Hellman keypair using the specified size and
      * parameters.
      */
@@ -272,266 +274,5 @@
 
         return null;
     }
+}
 
-    // lazy initialization holder class idiom for static default parameters
-    //
-    // See Effective Java Second Edition: Item 71.
-    private static class ParametersHolder {
-        private final static boolean debugIsOn =
-                (Debug.getInstance("ssl") != null) && Debug.isOn("sslctx");
-
-        //
-        // Default DH ephemeral parameters
-        //
-        private static final BigInteger p512 = new BigInteger(   // generated
-                "D87780E15FF50B4ABBE89870188B049406B5BEA98AB23A02" +
-                "41D88EA75B7755E669C08093D3F0CA7FC3A5A25CF067DCB9" +
-                "A43DD89D1D90921C6328884461E0B6D3", 16);
-        private static final BigInteger p768 = new BigInteger(   // RFC 2409
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
-
-        private static final BigInteger p1024 = new BigInteger(  // RFC 2409
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
-                "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
-                "FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p1536 = new BigInteger(  // RFC 3526
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
-                "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
-                "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
-                "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
-                "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p2048 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B423861285C97FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p3072 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p4096 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A" +
-                "FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p6144 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
-                "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
-                "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
-                "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
-                "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
-                "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
-                "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
-                "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
-                "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
-                "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
-                "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
-                "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p8192 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
-                "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
-                "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
-                "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
-                "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
-                "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
-                "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
-                "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
-                "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
-                "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
-                "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
-                "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" +
-                "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E" +
-                "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" +
-                "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282" +
-                "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" +
-                "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C" +
-                "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" +
-                "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457" +
-                "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" +
-                "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D" +
-                "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" +
-                "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF", 16);
-
-        private static final BigInteger[] supportedPrimes = {
-                p512, p768, p1024, p1536, p2048, p3072, p4096, p6144, p8192};
-
-        // a measure of the uncertainty that prime modulus p is not a prime
-        //
-        // see BigInteger.isProbablePrime(int certainty)
-        private final static int PRIME_CERTAINTY = 120;
-
-        // the known security property, jdk.tls.server.defaultDHEParameters
-        private final static String PROPERTY_NAME =
-                "jdk.tls.server.defaultDHEParameters";
-
-        private static final Pattern spacesPattern = Pattern.compile("\\s+");
-
-        private final static Pattern syntaxPattern = Pattern.compile(
-                "(\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})" +
-                "(,\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})*");
-
-        private static final Pattern paramsPattern = Pattern.compile(
-                "\\{([0-9A-Fa-f]+),([0-9A-Fa-f]+)\\}");
-
-        // cache of predefined default DH ephemeral parameters
-        private final static Map<Integer,DHParameterSpec> definedParams;
-
-        static {
-            String property = AccessController.doPrivileged(
-                new PrivilegedAction<String>() {
-                    public String run() {
-                        return Security.getProperty(PROPERTY_NAME);
-                    }
-                });
-
-            if (property != null && !property.isEmpty()) {
-                // remove double quote marks from beginning/end of the property
-                if (property.length() >= 2 && property.charAt(0) == '"' &&
-                        property.charAt(property.length() - 1) == '"') {
-                    property = property.substring(1, property.length() - 1);
-                }
-
-                property = property.trim();
-            }
-
-            if (property != null && !property.isEmpty()) {
-                Matcher spacesMatcher = spacesPattern.matcher(property);
-                property = spacesMatcher.replaceAll("");
-
-                if (debugIsOn) {
-                    System.out.println("The Security Property " +
-                            PROPERTY_NAME + ": " + property);
-                }
-            }
-
-            Map<Integer,DHParameterSpec> defaultParams = new HashMap<>();
-            if (property != null && !property.isEmpty()) {
-                Matcher syntaxMatcher = syntaxPattern.matcher(property);
-                if (syntaxMatcher.matches()) {
-                    Matcher paramsFinder = paramsPattern.matcher(property);
-                    while(paramsFinder.find()) {
-                        String primeModulus = paramsFinder.group(1);
-                        BigInteger p = new BigInteger(primeModulus, 16);
-                        if (!p.isProbablePrime(PRIME_CERTAINTY)) {
-                            if (debugIsOn) {
-                                System.out.println(
-                                    "Prime modulus p in Security Property, " +
-                                    PROPERTY_NAME + ", is not a prime: " +
-                                    primeModulus);
-                            }
-
-                            continue;
-                        }
-
-                        String baseGenerator = paramsFinder.group(2);
-                        BigInteger g = new BigInteger(baseGenerator, 16);
-
-                        DHParameterSpec spec = new DHParameterSpec(p, g);
-                        int primeLen = p.bitLength();
-                        defaultParams.put(primeLen, spec);
-                    }
-                } else if (debugIsOn) {
-                    System.out.println("Invalid Security Property, " +
-                            PROPERTY_NAME + ", definition");
-                }
-            }
-
-            for (BigInteger p : supportedPrimes) {
-                int primeLen = p.bitLength();
-                defaultParams.putIfAbsent(primeLen,
-                        new DHParameterSpec(p, BigInteger.TWO));
-            }
-
-            definedParams =
-                    Collections.<Integer,DHParameterSpec>unmodifiableMap(
-                                                                defaultParams);
-        }
-    }
-}
--- a/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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,17 +56,17 @@
     }
 
     // Called by ServerHandshaker for ephemeral ECDH
-    ECDHCrypt(int curveId, SecureRandom random) {
+    ECDHCrypt(NamedGroup namedGroup, SecureRandom random) {
         try {
             KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
             ECGenParameterSpec params =
-                    EllipticCurvesExtension.getECGenParamSpec(curveId);
+                    SupportedGroupsExtension.getECGenParamSpec(namedGroup);
             kpg.initialize(params, random);
             KeyPair kp = kpg.generateKeyPair();
             privateKey = kp.getPrivate();
             publicKey = (ECPublicKey)kp.getPublic();
         } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
+            throw new RuntimeException("Could not generate ECDH keypair", e);
         }
     }
 
@@ -79,7 +79,7 @@
             privateKey = kp.getPrivate();
             publicKey = (ECPublicKey)kp.getPublic();
         } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
+            throw new RuntimeException("Could not generate ECDH keypair", e);
         }
     }
 
--- a/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java	Mon Jun 19 08:16:03 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 2006, 2017, 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.IOException;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.AlgorithmParameters;
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AccessController;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.ArrayList;
-import javax.net.ssl.SSLProtocolException;
-
-import sun.security.action.GetPropertyAction;
-
-final class EllipticCurvesExtension extends HelloExtension {
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private static final int ARBITRARY_PRIME = 0xff01;
-    private static final int ARBITRARY_CHAR2 = 0xff02;
-
-    // speed up the searching
-    private static final Map<String, Integer> oidToIdMap = new HashMap<>();
-    private static final Map<Integer, String> idToOidMap = new HashMap<>();
-
-    // speed up the parameters construction
-    private static final Map<Integer,
-                AlgorithmParameters> idToParams = new HashMap<>();
-
-    // the supported elliptic curves
-    private static final int[] supportedCurveIds;
-
-    // the curves of the extension
-    private final int[] curveIds;
-
-    // See sun.security.util.CurveDB for the OIDs
-    private static enum NamedEllipticCurve {
-        T163_K1(1,  "sect163k1",    "1.3.132.0.1",      true),  // NIST K-163
-        T163_R1(2,  "sect163r1",    "1.3.132.0.2",      false),
-        T163_R2(3,  "sect163r2",    "1.3.132.0.15",     true),  // NIST B-163
-        T193_R1(4,  "sect193r1",    "1.3.132.0.24",     false),
-        T193_R2(5,  "sect193r2",    "1.3.132.0.25",     false),
-        T233_K1(6,  "sect233k1",    "1.3.132.0.26",     true),  // NIST K-233
-        T233_R1(7,  "sect233r1",    "1.3.132.0.27",     true),  // NIST B-233
-        T239_K1(8,  "sect239k1",    "1.3.132.0.3",      false),
-        T283_K1(9,  "sect283k1",    "1.3.132.0.16",     true),  // NIST K-283
-        T283_R1(10, "sect283r1",    "1.3.132.0.17",     true),  // NIST B-283
-        T409_K1(11, "sect409k1",    "1.3.132.0.36",     true),  // NIST K-409
-        T409_R1(12, "sect409r1",    "1.3.132.0.37",     true),  // NIST B-409
-        T571_K1(13, "sect571k1",    "1.3.132.0.38",     true),  // NIST K-571
-        T571_R1(14, "sect571r1",    "1.3.132.0.39",     true),  // NIST B-571
-
-        P160_K1(15, "secp160k1",    "1.3.132.0.9",      false),
-        P160_R1(16, "secp160r1",    "1.3.132.0.8",      false),
-        P160_R2(17, "secp160r2",    "1.3.132.0.30",     false),
-        P192_K1(18, "secp192k1",    "1.3.132.0.31",     false),
-        P192_R1(19, "secp192r1",    "1.2.840.10045.3.1.1", true), // NIST P-192
-        P224_K1(20, "secp224k1",    "1.3.132.0.32",     false),
-        P224_R1(21, "secp224r1",    "1.3.132.0.33",     true),  // NIST P-224
-        P256_K1(22, "secp256k1",    "1.3.132.0.10",     false),
-        P256_R1(23, "secp256r1",    "1.2.840.10045.3.1.7", true), // NIST P-256
-        P384_R1(24, "secp384r1",    "1.3.132.0.34",     true),  // NIST P-384
-        P521_R1(25, "secp521r1",    "1.3.132.0.35",     true);  // NIST P-521
-
-        int          id;
-        String       name;
-        String       oid;
-        boolean      isFips;
-
-        NamedEllipticCurve(int id, String name, String oid, boolean isFips) {
-            this.id = id;
-            this.name = name;
-            this.oid = oid;
-            this.isFips = isFips;
-
-            if (oidToIdMap.put(oid, id) != null ||
-                idToOidMap.put(id, oid) != null) {
-
-                throw new RuntimeException(
-                        "Duplicate named elliptic curve definition: " + name);
-            }
-        }
-
-        static NamedEllipticCurve getCurve(String name, boolean requireFips) {
-            for (NamedEllipticCurve curve : NamedEllipticCurve.values()) {
-                if (curve.name.equals(name) && (!requireFips || curve.isFips)) {
-                    return curve;
-                }
-            }
-
-            return null;
-        }
-    }
-
-    static {
-        boolean requireFips = SunJSSE.isFIPS();
-
-        // hack code to initialize NamedEllipticCurve
-        NamedEllipticCurve nec =
-                NamedEllipticCurve.getCurve("secp256r1", false);
-
-        // The value of the System Property defines a list of enabled named
-        // curves in preference order, separated with comma.  For example:
-        //
-        //      jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1"
-        //
-        // If the System Property is not defined or the value is empty, the
-        // default curves and preferences will be used.
-        String property = AccessController.doPrivileged(
-                    new GetPropertyAction("jdk.tls.namedGroups"));
-        if (property != null && property.length() != 0) {
-            // remove double quote marks from beginning/end of the property
-            if (property.length() > 1 && property.charAt(0) == '"' &&
-                    property.charAt(property.length() - 1) == '"') {
-                property = property.substring(1, property.length() - 1);
-            }
-        }
-
-        ArrayList<Integer> idList;
-        if (property != null && property.length() != 0) {   // customized curves
-            String[] curves = property.split(",");
-            idList = new ArrayList<>(curves.length);
-            for (String curve : curves) {
-                curve = curve.trim();
-                if (!curve.isEmpty()) {
-                    NamedEllipticCurve namedCurve =
-                            NamedEllipticCurve.getCurve(curve, requireFips);
-                    if (namedCurve != null) {
-                        if (isAvailableCurve(namedCurve.id)) {
-                            idList.add(namedCurve.id);
-                        }
-                    }   // ignore unknown curves
-                }
-            }
-            if (idList.isEmpty() && JsseJce.isEcAvailable()) {
-                throw new IllegalArgumentException(
-                    "System property jdk.tls.namedGroups(" + property + ") " +
-                    "contains no supported elliptic curves");
-            }
-        } else {        // default curves
-            int[] ids;
-            if (requireFips) {
-                ids = new int[] {
-                    // only NIST curves in FIPS mode
-                    23, 24, 25, 9, 10, 11, 12, 13, 14,
-                };
-            } else {
-                ids = new int[] {
-                    // NIST curves first
-                    23, 24, 25, 9, 10, 11, 12, 13, 14,
-                    // non-NIST curves
-                    22,
-                };
-            }
-
-            idList = new ArrayList<>(ids.length);
-            for (int curveId : ids) {
-                if (isAvailableCurve(curveId)) {
-                    idList.add(curveId);
-                }
-            }
-        }
-
-        if (debug != null && idList.isEmpty()) {
-            Debug.log(
-                "Initialized [jdk.tls.namedGroups|default] list contains " +
-                "no available elliptic curves. " +
-                (property != null ? "(" + property + ")" : "[Default]"));
-        }
-
-        supportedCurveIds = new int[idList.size()];
-        int i = 0;
-        for (Integer id : idList) {
-            supportedCurveIds[i++] = id;
-        }
-    }
-
-    // check whether the curve is supported by the underlying providers
-    private static boolean isAvailableCurve(int curveId) {
-        String oid = idToOidMap.get(curveId);
-        if (oid != null) {
-            AlgorithmParameters params = null;
-            try {
-                params = JsseJce.getAlgorithmParameters("EC");
-                params.init(new ECGenParameterSpec(oid));
-            } catch (Exception e) {
-                return false;
-            }
-
-            // cache the parameters
-            idToParams.put(curveId, params);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    private EllipticCurvesExtension(int[] curveIds) {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-
-        this.curveIds = curveIds;
-    }
-
-    EllipticCurvesExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-
-        int k = s.getInt16();
-        if (((len & 1) != 0) || (k + 2 != len)) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        // Note: unknown curves will be ignored later.
-        curveIds = new int[k >> 1];
-        for (int i = 0; i < curveIds.length; i++) {
-            curveIds[i] = s.getInt16();
-        }
-    }
-
-    // get the preferred active curve
-    static int getActiveCurves(AlgorithmConstraints constraints) {
-        return getPreferredCurve(supportedCurveIds, constraints);
-    }
-
-    static boolean hasActiveCurves(AlgorithmConstraints constraints) {
-        return getActiveCurves(constraints) >= 0;
-    }
-
-    static EllipticCurvesExtension createExtension(
-                AlgorithmConstraints constraints) {
-
-        ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length);
-        for (int curveId : supportedCurveIds) {
-            if (constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                "EC", idToParams.get(curveId))) {
-                idList.add(curveId);
-            }
-        }
-
-        if (!idList.isEmpty()) {
-            int[] ids = new int[idList.size()];
-            int i = 0;
-            for (Integer id : idList) {
-                ids[i++] = id;
-            }
-
-            return new EllipticCurvesExtension(ids);
-        }
-
-        return null;
-    }
-
-    // get the preferred activated curve
-    int getPreferredCurve(AlgorithmConstraints constraints) {
-        return getPreferredCurve(curveIds, constraints);
-    }
-
-    // get a preferred activated curve
-    private static int getPreferredCurve(int[] curves,
-                AlgorithmConstraints constraints) {
-        for (int curveId : curves) {
-            if (isSupported(curveId) && constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                "EC", idToParams.get(curveId))) {
-                return curveId;
-            }
-        }
-
-        return -1;
-    }
-
-    boolean contains(int index) {
-        for (int curveId : curveIds) {
-            if (index == curveId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    int length() {
-        return 6 + (curveIds.length << 1);
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        int k = curveIds.length << 1;
-        s.putInt16(k + 2);
-        s.putInt16(k);
-        for (int curveId : curveIds) {
-            s.putInt16(curveId);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Extension " + type + ", curve names: {");
-        boolean first = true;
-        for (int curveId : curveIds) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(", ");
-            }
-            // first check if it is a known named curve, then try other cases.
-            String curveName = getCurveName(curveId);
-            if (curveName != null) {
-                sb.append(curveName);
-            } else if (curveId == ARBITRARY_PRIME) {
-                sb.append("arbitrary_explicit_prime_curves");
-            } else if (curveId == ARBITRARY_CHAR2) {
-                sb.append("arbitrary_explicit_char2_curves");
-            } else {
-                sb.append("unknown curve " + curveId);
-            }
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-
-    // Test whether the given curve is supported.
-    static boolean isSupported(int index) {
-        for (int curveId : supportedCurveIds) {
-            if (index == curveId) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    static int getCurveIndex(ECParameterSpec params) {
-        String oid = JsseJce.getNamedCurveOid(params);
-        if (oid == null) {
-            return -1;
-        }
-        Integer n = oidToIdMap.get(oid);
-        return (n == null) ? -1 : n;
-    }
-
-    static String getCurveOid(int index) {
-        return idToOidMap.get(index);
-    }
-
-    static ECGenParameterSpec getECGenParamSpec(int index) {
-        AlgorithmParameters params = idToParams.get(index);
-        try {
-            return params.getParameterSpec(ECGenParameterSpec.class);
-        } catch (InvalidParameterSpecException ipse) {
-            // should be unlikely
-            String curveOid = getCurveOid(index);
-            return new ECGenParameterSpec(curveOid);
-        }
-    }
-
-    private static String getCurveName(int index) {
-        for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) {
-            if (namedCurve.id == index) {
-                return namedCurve.name;
-            }
-        }
-
-        return null;
-    }
-}
--- a/src/java.base/share/classes/sun/security/ssl/ExtensionType.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ExtensionType.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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
@@ -82,9 +82,9 @@
     static final ExtensionType EXT_CERT_TYPE =
             e(0x0009, "cert_type");              // IANA registry value: 9
 
-    // extensions defined in RFC 4492 (ECC)
-    static final ExtensionType EXT_ELLIPTIC_CURVES =
-            e(0x000A, "elliptic_curves");        // IANA registry value: 10
+    // extensions defined in RFC 4492 (ECC) and RFC 7919 (FFDHE)
+    static final ExtensionType EXT_SUPPORTED_GROUPS =
+            e(0x000A, "supported_groups");       // IANA registry value: 10
     static final ExtensionType EXT_EC_POINT_FORMATS =
             e(0x000B, "ec_point_formats");       // IANA registry value: 11
 
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -1369,8 +1369,9 @@
     private static final int CURVE_EXPLICIT_CHAR2 = 2;
     private static final int CURVE_NAMED_CURVE    = 3;
 
-    // id of the curve we are using
-    private int curveId;
+    // id of the named group we are using
+    private int groupId;
+
     // encoded public point
     private byte[] pointBytes;
 
@@ -1389,7 +1390,8 @@
     ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
             byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
             SignatureAndHashAlgorithm signAlgorithm,
-            ProtocolVersion protocolVersion) throws GeneralSecurityException {
+            ProtocolVersion protocolVersion)
+            throws SSLHandshakeException, GeneralSecurityException {
 
         this.protocolVersion = protocolVersion;
 
@@ -1397,7 +1399,14 @@
         ECParameterSpec params = publicKey.getParams();
         ECPoint point = publicKey.getW();
         pointBytes = JsseJce.encodePoint(point, params.getCurve());
-        curveId = EllipticCurvesExtension.getCurveIndex(params);
+
+        NamedGroup namedGroup = NamedGroup.valueOf(params);
+        if ((namedGroup == null) || (namedGroup.oid == null) ){
+            // unlikely
+            throw new SSLHandshakeException(
+                "Unnamed EC parameter spec: " + params);
+        }
+        groupId = namedGroup.id;
 
         if (privateKey == null) {
             // ECDH_anon
@@ -1434,20 +1443,27 @@
         // These parsing errors should never occur as we negotiated
         // the supported curves during the exchange of the Hello messages.
         if (curveType == CURVE_NAMED_CURVE) {
-            curveId = input.getInt16();
-            if (!EllipticCurvesExtension.isSupported(curveId)) {
+            groupId = input.getInt16();
+            NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+            if (namedGroup == null) {
                 throw new SSLHandshakeException(
-                    "Unsupported curveId: " + curveId);
+                    "Unknown named group ID: " + groupId);
             }
-            String curveOid = EllipticCurvesExtension.getCurveOid(curveId);
-            if (curveOid == null) {
+
+            if (!SupportedGroupsExtension.supports(namedGroup)) {
                 throw new SSLHandshakeException(
-                    "Unknown named curve: " + curveId);
+                    "Unsupported named group: " + namedGroup);
             }
-            parameters = JsseJce.getECParameterSpec(curveOid);
+
+            if (namedGroup.oid == null) {
+                throw new SSLHandshakeException(
+                    "Unknown named EC curve: " + namedGroup);
+            }
+
+            parameters = JsseJce.getECParameterSpec(namedGroup.oid);
             if (parameters == null) {
                 throw new SSLHandshakeException(
-                    "Unsupported curve: " + curveOid);
+                    "No supported EC parameter for named group: " + namedGroup);
             }
         } else {
             throw new SSLHandshakeException(
@@ -1530,8 +1546,8 @@
         sig.update(svrNonce);
 
         sig.update((byte)CURVE_NAMED_CURVE);
-        sig.update((byte)(curveId >> 8));
-        sig.update((byte)curveId);
+        sig.update((byte)(groupId >> 8));
+        sig.update((byte)groupId);
         sig.update((byte)pointBytes.length);
         sig.update(pointBytes);
     }
@@ -1552,7 +1568,7 @@
     @Override
     void send(HandshakeOutStream s) throws IOException {
         s.putInt8(CURVE_NAMED_CURVE);
-        s.putInt16(curveId);
+        s.putInt16(groupId);
         s.putBytes8(pointBytes);
 
         if (signatureBytes != null) {
--- a/src/java.base/share/classes/sun/security/ssl/Handshaker.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/Handshaker.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -52,6 +52,7 @@
 
 import static sun.security.ssl.CipherSuite.PRF.*;
 import static sun.security.ssl.CipherSuite.CipherType.*;
+import static sun.security.ssl.NamedGroupType.*;
 
 /**
  * Handshaker ... processes handshake records from an SSL V3.0
@@ -685,42 +686,14 @@
             ArrayList<CipherSuite> suites = new ArrayList<>();
             if (!(activeProtocols.collection().isEmpty()) &&
                     activeProtocols.min.v != ProtocolVersion.NONE.v) {
-                boolean checkedCurves = false;
-                boolean hasCurves = false;
+                Map<NamedGroupType, Boolean> cachedStatus =
+                        new EnumMap<>(NamedGroupType.class);
                 for (CipherSuite suite : enabledCipherSuites.collection()) {
-                    if (!activeProtocols.min.obsoletes(suite) &&
+                    if (suite.isAvailable() &&
+                            (!activeProtocols.min.obsoletes(suite)) &&
                             activeProtocols.max.supports(suite)) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-
-                            boolean available = true;
-                            if (suite.keyExchange.isEC) {
-                                if (!checkedCurves) {
-                                    hasCurves = EllipticCurvesExtension
-                                        .hasActiveCurves(algorithmConstraints);
-                                    checkedCurves = true;
-
-                                    if (!hasCurves && debug != null &&
-                                                Debug.isOn("verbose")) {
-                                        System.out.println(
-                                            "No available elliptic curves");
-                                    }
-                                }
-
-                                available = hasCurves;
-
-                                if (!available && debug != null &&
-                                        Debug.isOn("verbose")) {
-                                    System.out.println(
-                                        "No active elliptic curves, ignore " +
-                                        suite);
-                                }
-                            }
-
-                            if (available) {
-                                suites.add(suite);
-                            }
+                        if (isActivatable(suite, cachedStatus)) {
+                            suites.add(suite);
                         }
                     } else if (debug != null && Debug.isOn("verbose")) {
                         if (activeProtocols.min.obsoletes(suite)) {
@@ -779,46 +752,15 @@
                 }
 
                 boolean found = false;
+                Map<NamedGroupType, Boolean> cachedStatus =
+                        new EnumMap<>(NamedGroupType.class);
                 for (CipherSuite suite : enabledCipherSuites.collection()) {
                     if (suite.isAvailable() && (!protocol.obsoletes(suite)) &&
                                                protocol.supports(suite)) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-
-                            boolean available = true;
-                            if (suite.keyExchange.isEC) {
-                                if (!checkedCurves) {
-                                    hasCurves = EllipticCurvesExtension
-                                        .hasActiveCurves(algorithmConstraints);
-                                    checkedCurves = true;
-
-                                    if (!hasCurves && debug != null &&
-                                                Debug.isOn("verbose")) {
-                                        System.out.println(
-                                            "No activated elliptic curves");
-                                    }
-                                }
-
-                                available = hasCurves;
-
-                                if (!available && debug != null &&
-                                        Debug.isOn("verbose")) {
-                                    System.out.println(
-                                        "No active elliptic curves, ignore " +
-                                        suite + " for " + protocol);
-                                }
-                            }
-
-                            if (available) {
-                                protocols.add(protocol);
-                                found = true;
-                                break;
-                            }
-                        } else if (debug != null && Debug.isOn("verbose")) {
-                            System.out.println(
-                                "Ignoring disabled cipher suite: " + suite +
-                                 " for " + protocol);
+                        if (isActivatable(suite, cachedStatus)) {
+                            protocols.add(protocol);
+                            found = true;
+                            break;
                         }
                     } else if (debug != null && Debug.isOn("verbose")) {
                         System.out.println(
@@ -826,6 +768,7 @@
                                  " for " + protocol);
                     }
                 }
+
                 if (!found && (debug != null) && Debug.isOn("handshake")) {
                     System.out.println(
                         "No available cipher suite for " + protocol);
@@ -842,6 +785,43 @@
         return activeProtocols;
     }
 
+    private boolean isActivatable(CipherSuite suite,
+            Map<NamedGroupType, Boolean> cachedStatus) {
+
+        if (algorithmConstraints.permits(
+                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
+            boolean available = true;
+            NamedGroupType groupType = suite.keyExchange.groupType;
+            if (groupType != NAMED_GROUP_NONE) {
+                Boolean checkedStatus = cachedStatus.get(groupType);
+                if (checkedStatus == null) {
+                    available = SupportedGroupsExtension.isActivatable(
+                            algorithmConstraints, groupType);
+                    cachedStatus.put(groupType, available);
+
+                    if (!available && debug != null && Debug.isOn("verbose")) {
+                        System.out.println("No activated named group");
+                    }
+                } else {
+                    available = checkedStatus.booleanValue();
+                }
+
+                if (!available && debug != null && Debug.isOn("verbose")) {
+                    System.out.println(
+                        "No active named group, ignore " + suite);
+                }
+
+                return available;
+            } else {
+                return true;
+            }
+        } else if (debug != null && Debug.isOn("verbose")) {
+            System.out.println("Ignoring disabled cipher suite: " + suite);
+        }
+
+        return false;
+    }
+
     /**
      * As long as handshaking has not activated, we can
      * change whether session creations are allowed.
--- a/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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
@@ -49,7 +49,7 @@
  *      explicitly support.
  *  . ServerNameExtension: the server_name extension.
  *  . SignatureAlgorithmsExtension: the signature_algorithms extension.
- *  . EllipticCurvesExtension: the ECC supported curves extension.
+ *  . SupportedGroupsExtension: the supported groups extension.
  *  . EllipticPointFormatsExtension: the ECC supported point formats
  *      (compressed/uncompressed) extension.
  *  . ALPNExtension: the application_layer_protocol_negotiation extension.
@@ -79,8 +79,8 @@
                 extension = new ServerNameExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
                 extension = new SignatureAlgorithmsExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
-                extension = new EllipticCurvesExtension(s, extlen);
+            } else if (extType == ExtensionType.EXT_SUPPORTED_GROUPS) {
+                extension = new SupportedGroupsExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
                 extension = new EllipticPointFormatsExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, 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.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import static sun.security.ssl.NamedGroupType.*;
+
+enum NamedGroup {
+    // Elliptic Curves (RFC 4492)
+    //
+    // See sun.security.util.CurveDB for the OIDs
+
+    // NIST K-163
+    SECT163_K1(1, NAMED_GROUP_ECDHE, "sect163k1", "1.3.132.0.1", true),
+
+    SECT163_R1(2, NAMED_GROUP_ECDHE, "sect163r1", "1.3.132.0.2", false),
+
+    // NIST B-163
+    SECT163_R2(3, NAMED_GROUP_ECDHE, "sect163r2", "1.3.132.0.15", true),
+
+    SECT193_R1(4, NAMED_GROUP_ECDHE, "sect193r1", "1.3.132.0.24", false),
+    SECT193_R2(5, NAMED_GROUP_ECDHE, "sect193r2", "1.3.132.0.25", false),
+
+    // NIST K-233
+    SECT233_K1(6, NAMED_GROUP_ECDHE, "sect233k1", "1.3.132.0.26", true),
+
+    // NIST B-233
+    SECT233_R1(7, NAMED_GROUP_ECDHE, "sect233r1", "1.3.132.0.27", true),
+
+    SECT239_K1(8, NAMED_GROUP_ECDHE, "sect239k1", "1.3.132.0.3", false),
+
+    // NIST K-283
+    SECT283_K1(9, NAMED_GROUP_ECDHE, "sect283k1", "1.3.132.0.16", true),
+
+    // NIST B-283
+    SECT283_R1(10, NAMED_GROUP_ECDHE, "sect283r1", "1.3.132.0.17", true),
+
+    // NIST K-409
+    SECT409_K1(11, NAMED_GROUP_ECDHE, "sect409k1", "1.3.132.0.36", true),
+
+    // NIST B-409
+    SECT409_R1(12, NAMED_GROUP_ECDHE, "sect409r1", "1.3.132.0.37", true),
+
+    // NIST K-571
+    SECT571_K1(13, NAMED_GROUP_ECDHE, "sect571k1", "1.3.132.0.38", true),
+
+    // NIST B-571
+    SECT571_R1(14, NAMED_GROUP_ECDHE, "sect571r1", "1.3.132.0.39", true),
+
+    SECP160_K1(15, NAMED_GROUP_ECDHE, "secp160k1", "1.3.132.0.9", false),
+    SECP160_R1(16, NAMED_GROUP_ECDHE, "secp160r1", "1.3.132.0.8", false),
+    SECP160_R2(17, NAMED_GROUP_ECDHE, "secp160r2", "1.3.132.0.30", false),
+    SECP192_K1(18, NAMED_GROUP_ECDHE, "secp192k1", "1.3.132.0.31", false),
+
+    // NIST P-192
+    SECP192_R1(19, NAMED_GROUP_ECDHE, "secp192r1", "1.2.840.10045.3.1.1", true),
+
+    SECP224_K1(20, NAMED_GROUP_ECDHE, "secp224k1", "1.3.132.0.32", false),
+    // NIST P-224
+    SECP224_R1(21, NAMED_GROUP_ECDHE, "secp224r1", "1.3.132.0.33", true),
+
+    SECP256_K1(22, NAMED_GROUP_ECDHE, "secp256k1", "1.3.132.0.10", false),
+
+    // NIST P-256
+    SECP256_R1(23, NAMED_GROUP_ECDHE, "secp256r1", "1.2.840.10045.3.1.7", true),
+
+    // NIST P-384
+    SECP384_R1(24, NAMED_GROUP_ECDHE, "secp384r1", "1.3.132.0.34", true),
+
+    // NIST P-521
+    SECP521_R1(25, NAMED_GROUP_ECDHE, "secp521r1", "1.3.132.0.35", true),
+
+    // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
+    FFDHE_2048(256, NAMED_GROUP_FFDHE, "ffdhe2048",  true),
+    FFDHE_3072(257, NAMED_GROUP_FFDHE, "ffdhe3072",  true),
+    FFDHE_4096(258, NAMED_GROUP_FFDHE, "ffdhe4096",  true),
+    FFDHE_6144(259, NAMED_GROUP_FFDHE, "ffdhe6144",  true),
+    FFDHE_8192(260, NAMED_GROUP_FFDHE, "ffdhe8192",  true);
+
+    int             id;
+    NamedGroupType  type;
+    String          name;
+    String          oid;
+    String          algorithm;
+    boolean         isFips;
+
+    // Constructor used for Elliptic Curve Groups (ECDHE)
+    NamedGroup(int id, NamedGroupType type,
+                String name, String oid, boolean isFips) {
+        this.id = id;
+        this.type = type;
+        this.name = name;
+        this.oid = oid;
+        this.algorithm = "EC";
+        this.isFips = isFips;
+    }
+
+    // Constructor used for Finite Field Diffie-Hellman Groups (FFDHE)
+    NamedGroup(int id, NamedGroupType type, String name, boolean isFips) {
+        this.id = id;
+        this.type = type;
+        this.name = name;
+        this.oid = null;
+        this.algorithm = "DiffieHellman";
+        this.isFips = isFips;
+    }
+
+    static NamedGroup valueOf(int id) {
+        for (NamedGroup group : NamedGroup.values()) {
+            if (group.id == id) {
+                return group;
+            }
+        }
+
+        return null;
+    }
+
+    static NamedGroup nameOf(String name) {
+        for (NamedGroup group : NamedGroup.values()) {
+            if (group.name.equals(name)) {
+                return group;
+            }
+        }
+
+        return null;
+    }
+
+    static NamedGroup valueOf(ECParameterSpec params) {
+        String oid = JsseJce.getNamedCurveOid(params);
+        if ((oid != null) && (!oid.isEmpty())) {
+            for (NamedGroup group : NamedGroup.values()) {
+                if (oid.equals(group.oid)) {
+                    return group;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return this.name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroupType.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 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;
+
+enum NamedGroupType {
+    NAMED_GROUP_ECDHE,          // Elliptic Curve Groups (ECDHE)
+    NAMED_GROUP_FFDHE,          // Finite Field Groups (DHE)
+    NAMED_GROUP_NONE            // No predefined named group
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/PredefinedDHParameterSpecs.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2017, 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.security.*;
+import java.math.BigInteger;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * Predefined default DH ephemeral parameters.
+ */
+final class PredefinedDHParameterSpecs {
+    private final static boolean debugIsOn =
+            (Debug.getInstance("ssl") != null) && Debug.isOn("sslctx");
+
+    //
+    // Default DH ephemeral parameters
+    //
+    private static final BigInteger p512 = new BigInteger(       // generated
+            "D87780E15FF50B4ABBE89870188B049406B5BEA98AB23A02" +
+            "41D88EA75B7755E669C08093D3F0CA7FC3A5A25CF067DCB9" +
+            "A43DD89D1D90921C6328884461E0B6D3", 16);
+    private static final BigInteger p768 = new BigInteger(       // RFC 2409
+            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+            "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+            "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+            "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
+
+    private static final BigInteger p1024 = new BigInteger(      // RFC 2409
+            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+            "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+            "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+            "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+            "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
+            "FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p1536 = new BigInteger(      // RFC 3526
+            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+            "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+            "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+            "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+            "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+            "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+            "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+            "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p2048 = new BigInteger(      // TLS FFDHE
+            "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+            "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+            "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+            "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+            "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+            "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+            "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+            "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+            "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+            "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+            "886B423861285C97FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p3072 = new BigInteger(      // TLS FFDHE
+            "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+            "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+            "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+            "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+            "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+            "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+            "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+            "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+            "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+            "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+            "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+            "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+            "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+            "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+            "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+            "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p4096 = new BigInteger(      // TLS FFDHE
+            "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+            "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+            "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+            "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+            "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+            "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+            "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+            "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+            "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+            "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+            "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+            "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+            "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+            "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+            "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+            "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+            "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+            "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+            "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+            "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+            "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A" +
+            "FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p6144 = new BigInteger(      // TLS FFDHE
+            "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+            "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+            "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+            "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+            "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+            "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+            "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+            "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+            "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+            "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+            "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+            "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+            "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+            "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+            "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+            "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+            "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+            "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+            "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+            "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+            "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
+            "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
+            "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
+            "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
+            "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
+            "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
+            "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
+            "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
+            "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
+            "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
+            "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
+            "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF", 16);
+    private static final BigInteger p8192 = new BigInteger(      // TLS FFDHE
+            "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+            "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+            "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+            "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+            "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+            "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+            "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+            "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+            "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+            "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+            "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+            "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+            "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+            "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+            "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+            "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+            "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+            "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+            "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+            "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+            "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
+            "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
+            "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
+            "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
+            "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
+            "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
+            "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
+            "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
+            "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
+            "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
+            "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
+            "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" +
+            "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E" +
+            "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" +
+            "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282" +
+            "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" +
+            "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C" +
+            "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" +
+            "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457" +
+            "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" +
+            "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D" +
+            "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" +
+            "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF", 16);
+
+    private static final BigInteger[] supportedPrimes = {
+            p512, p768, p1024, p1536, p2048, p3072, p4096, p6144, p8192};
+
+    private static final BigInteger[] ffdhePrimes = {
+            p2048, p3072, p4096, p6144, p8192};
+
+    // a measure of the uncertainty that prime modulus p is not a prime
+    //
+    // see BigInteger.isProbablePrime(int certainty)
+    private final static int PRIME_CERTAINTY = 120;
+
+    // the known security property, jdk.tls.server.defaultDHEParameters
+    private final static String PROPERTY_NAME =
+            "jdk.tls.server.defaultDHEParameters";
+
+    private static final Pattern spacesPattern = Pattern.compile("\\s+");
+
+    private final static Pattern syntaxPattern = Pattern.compile(
+            "(\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})" +
+            "(,\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})*");
+
+    private static final Pattern paramsPattern = Pattern.compile(
+            "\\{([0-9A-Fa-f]+),([0-9A-Fa-f]+)\\}");
+
+    // cache of predefined default DH ephemeral parameters
+    final static Map<Integer, DHParameterSpec> definedParams;
+
+    // cache of Finite Field DH Ephemeral parameters (RFC 7919/FFDHE)
+    final static Map<Integer, DHParameterSpec> ffdheParams;
+
+    static {
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(PROPERTY_NAME);
+                }
+            });
+
+        if (property != null && !property.isEmpty()) {
+            // remove double quote marks from beginning/end of the property
+            if (property.length() >= 2 && property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+
+            property = property.trim();
+        }
+
+        if (property != null && !property.isEmpty()) {
+            Matcher spacesMatcher = spacesPattern.matcher(property);
+            property = spacesMatcher.replaceAll("");
+
+            if (debugIsOn) {
+                System.out.println("The Security Property " +
+                        PROPERTY_NAME + ": " + property);
+            }
+        }
+
+        Map<Integer,DHParameterSpec> defaultParams = new HashMap<>();
+        if (property != null && !property.isEmpty()) {
+            Matcher syntaxMatcher = syntaxPattern.matcher(property);
+            if (syntaxMatcher.matches()) {
+                Matcher paramsFinder = paramsPattern.matcher(property);
+                while(paramsFinder.find()) {
+                    String primeModulus = paramsFinder.group(1);
+                    BigInteger p = new BigInteger(primeModulus, 16);
+                    if (!p.isProbablePrime(PRIME_CERTAINTY)) {
+                        if (debugIsOn) {
+                            System.out.println(
+                                "Prime modulus p in Security Property, " +
+                                PROPERTY_NAME + ", is not a prime: " +
+                                primeModulus);
+                        }
+
+                        continue;
+                    }
+
+                    String baseGenerator = paramsFinder.group(2);
+                    BigInteger g = new BigInteger(baseGenerator, 16);
+
+                    DHParameterSpec spec = new DHParameterSpec(p, g);
+                    int primeLen = p.bitLength();
+                    defaultParams.put(primeLen, spec);
+                }
+            } else if (debugIsOn) {
+                System.out.println("Invalid Security Property, " +
+                        PROPERTY_NAME + ", definition");
+            }
+        }
+
+        Map<Integer,DHParameterSpec> tempFFDHEs = new HashMap<>();
+        for (BigInteger p : ffdhePrimes) {
+            int primeLen = p.bitLength();
+            DHParameterSpec dhps = new DHParameterSpec(p, BigInteger.TWO);
+            tempFFDHEs.put(primeLen, dhps);
+            defaultParams.putIfAbsent(primeLen, dhps);
+        }
+
+        for (BigInteger p : supportedPrimes) {
+            int primeLen = p.bitLength();
+            if (defaultParams.get(primeLen) == null) {
+                defaultParams.put(primeLen,
+                    new DHParameterSpec(p, BigInteger.TWO));
+            }
+        }
+
+        ffdheParams =
+            Collections.<Integer,DHParameterSpec>unmodifiableMap(tempFFDHEs);
+        definedParams =
+            Collections.<Integer,DHParameterSpec>unmodifiableMap(defaultParams);
+    }
+}
--- a/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -96,7 +96,7 @@
     private ProtocolVersion clientRequestedVersion;
 
     // client supported elliptic curves
-    private EllipticCurvesExtension requestedCurves;
+    private SupportedGroupsExtension requestedGroups;
 
     // the preferable signature algorithm used by ServerKeyExchange message
     SignatureAndHashAlgorithm preferableSignatureAlgorithm;
@@ -751,8 +751,8 @@
                 throw new SSLException("Client did not resume a session");
             }
 
-            requestedCurves = (EllipticCurvesExtension)
-                        mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
+            requestedGroups = (SupportedGroupsExtension)
+                    mesg.extensions.get(ExtensionType.EXT_SUPPORTED_GROUPS);
 
             // We only need to handle the "signature_algorithm" extension
             // for full handshakes and TLS 1.2 or later.
@@ -1341,6 +1341,8 @@
             }
         }
 
+        // The named group used for ECDHE and FFDHE.
+        NamedGroup namedGroup = null;
         switch (keyExchange) {
         case K_RSA:
             // need RSA certs for authentication
@@ -1366,6 +1368,37 @@
             }
             break;
         case K_DHE_RSA:
+            // Is ephemeral DH cipher suite usable for the connection?
+            //
+            // [RFC 7919] If a compatible TLS server receives a Supported
+            // Groups extension from a client that includes any FFDHE group
+            // (i.e., any codepoint between 256 and 511, inclusive, even if
+            // unknown to the server), and if none of the client-proposed
+            // FFDHE groups are known and acceptable to the server, then
+            // the server MUST NOT select an FFDHE cipher suite.  In this
+            // case, the server SHOULD select an acceptable non-FFDHE cipher
+            // suite from the client's offered list.  If the extension is
+            // present with FFDHE groups, none of the client's offered
+            // groups are acceptable by the server, and none of the client's
+            // proposed non-FFDHE cipher suites are acceptable to the server,
+            // the server MUST end the connection with a fatal TLS alert
+            // of type insufficient_security(71).
+            //
+            // Note: For compatibility, if an application is customized to
+            // use legacy sizes (512 bits for exportable cipher suites and
+            // 768 bits for others), or the cipher suite is exportable, the
+            // FFDHE extension will not be used.
+            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+                (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+
+                namedGroup = requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+                if (namedGroup == null) {
+                    // no match found, cannot use this cipher suite.
+                    return false;
+                }
+            }
+
             // need RSA certs for authentication
             if (setupPrivateKeyAndChain("RSA") == false) {
                 return false;
@@ -1386,9 +1419,20 @@
                 }
             }
 
-            setupEphemeralDHKeys(suite.exportable, privateKey);
+            setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
             break;
         case K_ECDHE_RSA:
+            // Is ECDHE cipher suite usable for the connection?
+            namedGroup = (requestedGroups != null) ?
+                requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+                SupportedGroupsExtension.getPreferredECGroup(
+                    algorithmConstraints);
+            if (namedGroup == null) {
+                // no match found, cannot use this ciphersuite
+                return false;
+            }
+
             // need RSA certs for authentication
             if (setupPrivateKeyAndChain("RSA") == false) {
                 return false;
@@ -1409,11 +1453,23 @@
                 }
             }
 
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
+            setupEphemeralECDHKeys(namedGroup);
             break;
         case K_DHE_DSS:
+            // Is ephemeral DH cipher suite usable for the connection?
+            //
+            // See comment in K_DHE_RSA case.
+            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+                (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+
+                namedGroup = requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+                if (namedGroup == null) {
+                    // no match found, cannot use this cipher suite.
+                    return false;
+                }
+            }
+
             // get preferable peer signature algorithm for server key exchange
             if (protocolVersion.useTLS12PlusSpec()) {
                 preferableSignatureAlgorithm =
@@ -1434,9 +1490,20 @@
                 return false;
             }
 
-            setupEphemeralDHKeys(suite.exportable, privateKey);
+            setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
             break;
         case K_ECDHE_ECDSA:
+            // Is ECDHE cipher suite usable for the connection?
+            namedGroup = (requestedGroups != null) ?
+                requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+                SupportedGroupsExtension.getPreferredECGroup(
+                    algorithmConstraints);
+            if (namedGroup == null) {
+                // no match found, cannot use this ciphersuite
+                return false;
+            }
+
             // get preferable peer signature algorithm for server key exchange
             if (protocolVersion.useTLS12PlusSpec()) {
                 preferableSignatureAlgorithm =
@@ -1456,9 +1523,8 @@
             if (setupPrivateKeyAndChain("EC") == false) {
                 return false;
             }
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
+
+            setupEphemeralECDHKeys(namedGroup);
             break;
         case K_ECDH_RSA:
             // need EC cert
@@ -1475,14 +1541,36 @@
             setupStaticECDHKeys();
             break;
         case K_DH_ANON:
+            // Is ephemeral DH cipher suite usable for the connection?
+            //
+            // See comment in K_DHE_RSA case.
+            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+                (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+                namedGroup = requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+                if (namedGroup == null) {
+                    // no match found, cannot use this cipher suite.
+                    return false;
+                }
+            }
+
             // no certs needed for anonymous
-            setupEphemeralDHKeys(suite.exportable, null);
+            setupEphemeralDHKeys(namedGroup, suite.exportable, null);
             break;
         case K_ECDH_ANON:
-            // no certs needed for anonymous
-            if (setupEphemeralECDHKeys() == false) {
+            // Is ECDHE cipher suite usable for the connection?
+            namedGroup = (requestedGroups != null) ?
+                requestedGroups.getPreferredGroup(
+                    algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+                SupportedGroupsExtension.getPreferredECGroup(
+                    algorithmConstraints);
+            if (namedGroup == null) {
+                // no match found, cannot use this ciphersuite
                 return false;
             }
+
+            // no certs needed for anonymous
+            setupEphemeralECDHKeys(namedGroup);
             break;
         default:
             ClientKeyExchangeService p =
@@ -1544,7 +1632,15 @@
      * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
      * We don't reuse these, for improved forward secrecy.
      */
-    private void setupEphemeralDHKeys(boolean export, Key key) {
+    private void setupEphemeralDHKeys(
+            NamedGroup namedGroup, boolean export, Key key) {
+        // Are the client and server willing to negotiate FFDHE groups?
+        if ((!useLegacyEphemeralDHKeys) && (!export) && (namedGroup != null)) {
+            dh = new DHCrypt(namedGroup, sslContext.getSecureRandom());
+
+            return;
+        }   // Otherwise, the client is not compatible with FFDHE extension.
+
         /*
          * 768 bits ephemeral DH private keys were used to be used in
          * ServerKeyExchange except that exportable ciphers max out at 512
@@ -1613,20 +1709,11 @@
         dh = new DHCrypt(keySize, sslContext.getSecureRandom());
     }
 
-    // Setup the ephemeral ECDH parameters.
-    // If we cannot continue because we do not support any of the curves that
-    // the client requested, return false. Otherwise (all is well), return true.
-    private boolean setupEphemeralECDHKeys() {
-        int index = (requestedCurves != null) ?
-                requestedCurves.getPreferredCurve(algorithmConstraints) :
-                EllipticCurvesExtension.getActiveCurves(algorithmConstraints);
-        if (index < 0) {
-            // no match found, cannot use this ciphersuite
-            return false;
-        }
-
-        ecdh = new ECDHCrypt(index, sslContext.getSecureRandom());
-        return true;
+    /**
+     * Setup the ephemeral ECDH parameters.
+     */
+    private void setupEphemeralECDHKeys(NamedGroup namedGroup) {
+        ecdh = new ECDHCrypt(namedGroup, sslContext.getSecureRandom());
     }
 
     private void setupStaticECDHKeys() {
@@ -1674,9 +1761,11 @@
                 return false;
             }
             ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
-            int id = EllipticCurvesExtension.getCurveIndex(params);
-            if ((id <= 0) || !EllipticCurvesExtension.isSupported(id) ||
-                ((requestedCurves != null) && !requestedCurves.contains(id))) {
+            NamedGroup namedGroup = NamedGroup.valueOf(params);
+            if ((namedGroup == null) ||
+                (!SupportedGroupsExtension.supports(namedGroup)) ||
+                ((requestedGroups != null) &&
+                        !requestedGroups.contains(namedGroup.id))) {
                 return false;
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2006, 2017, 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.IOException;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.AlgorithmParameters;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AccessController;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.spec.DHParameterSpec;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import javax.net.ssl.SSLProtocolException;
+
+import sun.security.action.GetPropertyAction;
+
+//
+// Note: Since RFC 7919, the extension's semantics are expanded from
+// "Supported Elliptic Curves" to "Supported Groups".  The enum datatype
+// used in the extension has been renamed from NamedCurve to NamedGroup.
+// Its semantics are likewise expanded from "named curve" to "named group".
+//
+final class SupportedGroupsExtension extends HelloExtension {
+
+    /* Class and subclass dynamic debugging support */
+    private static final Debug debug = Debug.getInstance("ssl");
+
+    private static final int ARBITRARY_PRIME = 0xff01;
+    private static final int ARBITRARY_CHAR2 = 0xff02;
+
+    // cache to speed up the parameters construction
+    private static final Map<NamedGroup,
+                AlgorithmParameters> namedGroupParams = new HashMap<>();
+
+    // the supported named groups
+    private static final NamedGroup[] supportedNamedGroups;
+
+    // the named group presented in the extension
+    private final int[] requestedNamedGroupIds;
+
+    static {
+        boolean requireFips = SunJSSE.isFIPS();
+
+        // The value of the System Property defines a list of enabled named
+        // groups in preference order, separated with comma.  For example:
+        //
+        //      jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048"
+        //
+        // If the System Property is not defined or the value is empty, the
+        // default groups and preferences will be used.
+        String property = AccessController.doPrivileged(
+                    new GetPropertyAction("jdk.tls.namedGroups"));
+        if (property != null && property.length() != 0) {
+            // remove double quote marks from beginning/end of the property
+            if (property.length() > 1 && property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+        }
+
+        ArrayList<NamedGroup> groupList;
+        if (property != null && property.length() != 0) {   // customized groups
+            String[] groups = property.split(",");
+            groupList = new ArrayList<>(groups.length);
+            for (String group : groups) {
+                group = group.trim();
+                if (!group.isEmpty()) {
+                    NamedGroup namedGroup = NamedGroup.nameOf(group);
+                    if (namedGroup != null &&
+                            (!requireFips || namedGroup.isFips)) {
+                        if (isAvailableGroup(namedGroup)) {
+                            groupList.add(namedGroup);
+                        }
+                    }   // ignore unknown groups
+                }
+            }
+
+            if (groupList.isEmpty() && JsseJce.isEcAvailable()) {
+                throw new IllegalArgumentException(
+                    "System property jdk.tls.namedGroups(" + property + ") " +
+                    "contains no supported elliptic curves");
+            }
+        } else {        // default groups
+            NamedGroup[] groups;
+            if (requireFips) {
+                groups = new NamedGroup[] {
+                    // only NIST curves in FIPS mode
+                    NamedGroup.SECP256_R1,
+                    NamedGroup.SECP384_R1,
+                    NamedGroup.SECP521_R1,
+                    NamedGroup.SECT283_K1,
+                    NamedGroup.SECT283_R1,
+                    NamedGroup.SECT409_K1,
+                    NamedGroup.SECT409_R1,
+                    NamedGroup.SECT571_K1,
+                    NamedGroup.SECT571_R1,
+
+                    // FFDHE 2048
+                    NamedGroup.FFDHE_2048,
+                    NamedGroup.FFDHE_3072,
+                    NamedGroup.FFDHE_4096,
+                    NamedGroup.FFDHE_6144,
+                    NamedGroup.FFDHE_8192,
+                };
+            } else {
+                groups = new NamedGroup[] {
+                    // NIST curves first
+                    NamedGroup.SECP256_R1,
+                    NamedGroup.SECP384_R1,
+                    NamedGroup.SECP521_R1,
+                    NamedGroup.SECT283_K1,
+                    NamedGroup.SECT283_R1,
+                    NamedGroup.SECT409_K1,
+                    NamedGroup.SECT409_R1,
+                    NamedGroup.SECT571_K1,
+                    NamedGroup.SECT571_R1,
+
+                    // non-NIST curves
+                    NamedGroup.SECP256_K1,
+
+                    // FFDHE 2048
+                    NamedGroup.FFDHE_2048,
+                    NamedGroup.FFDHE_3072,
+                    NamedGroup.FFDHE_4096,
+                    NamedGroup.FFDHE_6144,
+                    NamedGroup.FFDHE_8192,
+                };
+            }
+
+            groupList = new ArrayList<>(groups.length);
+            for (NamedGroup group : groups) {
+                if (isAvailableGroup(group)) {
+                    groupList.add(group);
+                }
+            }
+        }
+
+        if (debug != null && groupList.isEmpty()) {
+            Debug.log(
+                "Initialized [jdk.tls.namedGroups|default] list contains " +
+                "no available elliptic curves. " +
+                (property != null ? "(" + property + ")" : "[Default]"));
+        }
+
+        supportedNamedGroups = new NamedGroup[groupList.size()];
+        int i = 0;
+        for (NamedGroup namedGroup : groupList) {
+            supportedNamedGroups[i++] = namedGroup;
+        }
+    }
+
+    // check whether the group is supported by the underlying providers
+    private static boolean isAvailableGroup(NamedGroup namedGroup) {
+        AlgorithmParameters params = null;
+        AlgorithmParameterSpec spec = null;
+        if ("EC".equals(namedGroup.algorithm)) {
+            if (namedGroup.oid != null) {
+                try {
+                    params = JsseJce.getAlgorithmParameters("EC");
+                    spec = new ECGenParameterSpec(namedGroup.oid);
+                } catch (Exception e) {
+                    return false;
+                }
+            }
+        } else if ("DiffieHellman".equals(namedGroup.algorithm)) {
+            try {
+                params = JsseJce.getAlgorithmParameters("DiffieHellman");
+                spec = getFFDHEDHParameterSpec(namedGroup);
+            } catch (Exception e) {
+                return false;
+            }
+        }
+
+        if ((params != null) && (spec != null)) {
+            try {
+                params.init(spec);
+            } catch (Exception e) {
+                return false;
+            }
+
+            // cache the parameters
+            namedGroupParams.put(namedGroup, params);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    private static DHParameterSpec getFFDHEDHParameterSpec(
+            NamedGroup namedGroup) {
+        DHParameterSpec spec = null;
+        switch (namedGroup) {
+            case FFDHE_2048:
+                spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
+                break;
+            case FFDHE_3072:
+                spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
+                break;
+            case FFDHE_4096:
+                spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
+                break;
+            case FFDHE_6144:
+                spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
+                break;
+            case FFDHE_8192:
+                spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
+        }
+
+        return spec;
+    }
+
+    private static DHParameterSpec getPredefinedDHParameterSpec(
+            NamedGroup namedGroup) {
+        DHParameterSpec spec = null;
+        switch (namedGroup) {
+            case FFDHE_2048:
+                spec = PredefinedDHParameterSpecs.definedParams.get(2048);
+                break;
+            case FFDHE_3072:
+                spec = PredefinedDHParameterSpecs.definedParams.get(3072);
+                break;
+            case FFDHE_4096:
+                spec = PredefinedDHParameterSpecs.definedParams.get(4096);
+                break;
+            case FFDHE_6144:
+                spec = PredefinedDHParameterSpecs.definedParams.get(6144);
+                break;
+            case FFDHE_8192:
+                spec = PredefinedDHParameterSpecs.definedParams.get(8192);
+        }
+
+        return spec;
+    }
+
+    private SupportedGroupsExtension(int[] requestedNamedGroupIds) {
+        super(ExtensionType.EXT_SUPPORTED_GROUPS);
+
+        this.requestedNamedGroupIds = requestedNamedGroupIds;
+    }
+
+    SupportedGroupsExtension(HandshakeInStream s, int len) throws IOException {
+        super(ExtensionType.EXT_SUPPORTED_GROUPS);
+
+        int k = s.getInt16();
+        if (((len & 1) != 0) || (k == 0) || (k + 2 != len)) {
+            throw new SSLProtocolException("Invalid " + type + " extension");
+        }
+
+        // Note: unknown named group will be ignored later.
+        requestedNamedGroupIds = new int[k >> 1];
+        for (int i = 0; i < requestedNamedGroupIds.length; i++) {
+            requestedNamedGroupIds[i] = s.getInt16();
+        }
+    }
+
+    // Get a local preferred supported ECDHE group permitted by the constraints.
+    static NamedGroup getPreferredECGroup(AlgorithmConstraints constraints) {
+        for (NamedGroup namedGroup : supportedNamedGroups) {
+            if ((namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) &&
+                constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                    namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+                return namedGroup;
+            }
+        }
+
+        return null;
+    }
+
+    // Is there any supported group permitted by the constraints?
+    static boolean isActivatable(
+            AlgorithmConstraints constraints, NamedGroupType type) {
+
+        boolean hasFFDHEGroups = false;
+        for (NamedGroup namedGroup : supportedNamedGroups) {
+            if (namedGroup.type == type) {
+                if (constraints.permits(
+                        EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                        namedGroup.algorithm,
+                        namedGroupParams.get(namedGroup))) {
+
+                    return true;
+                }
+
+                if (!hasFFDHEGroups &&
+                        (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+
+                    hasFFDHEGroups = true;
+                }
+            }
+        }
+
+        // For compatibility, if no FFDHE groups are defined, the non-FFDHE
+        // compatible mode (using DHE cipher suite without FFDHE extension)
+        // is allowed.
+        //
+        // Note that the constraints checking on DHE parameters will be
+        // performed during key exchanging in a handshake.
+        if (!hasFFDHEGroups && (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    // Create the default supported groups extension.
+    static SupportedGroupsExtension createExtension(
+            AlgorithmConstraints constraints,
+            CipherSuiteList cipherSuites, boolean enableFFDHE) {
+
+        ArrayList<Integer> groupList =
+                new ArrayList<>(supportedNamedGroups.length);
+        for (NamedGroup namedGroup : supportedNamedGroups) {
+            if ((!enableFFDHE) &&
+                (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                continue;
+            }
+
+            if (cipherSuites.contains(namedGroup.type) &&
+                constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                    namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+                groupList.add(namedGroup.id);
+            }
+        }
+
+        if (!groupList.isEmpty()) {
+            int[] ids = new int[groupList.size()];
+            int i = 0;
+            for (Integer id : groupList) {
+                ids[i++] = id;
+            }
+
+            return new SupportedGroupsExtension(ids);
+        }
+
+        return null;
+    }
+
+    // get the preferred activated named group
+    NamedGroup getPreferredGroup(
+            AlgorithmConstraints constraints, NamedGroupType type) {
+
+        for (int groupId : requestedNamedGroupIds) {
+            NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+            if ((namedGroup != null) && (namedGroup.type == type) &&
+                SupportedGroupsExtension.supports(namedGroup) &&
+                constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                    namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+                return namedGroup;
+            }
+        }
+
+        return null;
+    }
+
+    boolean hasFFDHEGroup() {
+        for (int groupId : requestedNamedGroupIds) {
+            /*
+             * [RFC 7919] Codepoints in the "Supported Groups Registry"
+             * with a high byte of 0x01 (that is, between 256 and 511,
+             * inclusive) are set aside for FFDHE groups.
+             */
+            if ((groupId >= 256) && (groupId <= 511)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    boolean contains(int index) {
+        for (int groupId : requestedNamedGroupIds) {
+            if (index == groupId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    int length() {
+        return 6 + (requestedNamedGroupIds.length << 1);
+    }
+
+    @Override
+    void send(HandshakeOutStream s) throws IOException {
+        s.putInt16(type.id);
+        int k = requestedNamedGroupIds.length << 1;
+        s.putInt16(k + 2);
+        s.putInt16(k);
+        for (int groupId : requestedNamedGroupIds) {
+            s.putInt16(groupId);
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Extension " + type + ", group names: {");
+        boolean first = true;
+        for (int groupId : requestedNamedGroupIds) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            // first check if it is a known named group, then try other cases.
+            NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+            if (namedGroup != null) {
+                sb.append(namedGroup.name);
+            } else if (groupId == ARBITRARY_PRIME) {
+                sb.append("arbitrary_explicit_prime_curves");
+            } else if (groupId == ARBITRARY_CHAR2) {
+                sb.append("arbitrary_explicit_char2_curves");
+            } else {
+                sb.append("unknown named group " + groupId);
+            }
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    static boolean supports(NamedGroup namedGroup) {
+        for (NamedGroup group : supportedNamedGroups) {
+            if (namedGroup.id == group.id) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
+        if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
+            throw new RuntimeException("Not a named EC group: " + namedGroup);
+        }
+
+        AlgorithmParameters params = namedGroupParams.get(namedGroup);
+        try {
+            return params.getParameterSpec(ECGenParameterSpec.class);
+        } catch (InvalidParameterSpecException ipse) {
+            // should be unlikely
+            return new ECGenParameterSpec(namedGroup.oid);
+        }
+    }
+
+    static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
+        if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+            throw new RuntimeException("Not a named DH group: " + namedGroup);
+        }
+
+        AlgorithmParameters params = namedGroupParams.get(namedGroup);
+        try {
+            return params.getParameterSpec(DHParameterSpec.class);
+        } catch (InvalidParameterSpecException ipse) {
+            // should be unlikely
+            return getPredefinedDHParameterSpec(namedGroup);
+        }
+    }
+}
--- a/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,6 +27,8 @@
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.regex.Pattern;
 
 /**
@@ -134,6 +136,23 @@
         return elements;
     }
 
+    /**
+     * Get aliases of the specified algorithm.
+     *
+     * May support more algorithms in the future.
+     */
+    public static Collection<String> getAliases(String algorithm) {
+        String[] aliases;
+        if (algorithm.equalsIgnoreCase("DH") ||
+                algorithm.equalsIgnoreCase("DiffieHellman")) {
+            aliases = new String[] {"DH", "DiffieHellman"};
+        } else {
+            aliases = new String[] {algorithm};
+        }
+
+        return Arrays.asList(aliases);
+    }
+
     private static void hasLoop(Set<String> elements, String find, String replace) {
         if (elements.contains(find)) {
             if (!elements.contains(replace)) {
--- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Mon Jun 19 11:29:42 2017 -0700
@@ -45,6 +45,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.Collection;
 import java.util.StringTokenizer;
 import java.util.TimeZone;
 import java.util.regex.Pattern;
@@ -106,7 +107,15 @@
     @Override
     public final boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, AlgorithmParameters parameters) {
-        return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
+        if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) {
+            return false;
+        }
+
+        if (parameters != null) {
+            return algorithmConstraints.permits(algorithm, parameters);
+        }
+
+        return true;
     }
 
     /*
@@ -242,7 +251,12 @@
                 List<Constraint> constraintList =
                         constraintsMap.getOrDefault(algorithm,
                                 new ArrayList<>(1));
-                constraintsMap.putIfAbsent(algorithm, constraintList);
+
+                // Consider the impact of algorithm aliases.
+                for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
+                    constraintsMap.putIfAbsent(alias, constraintList);
+                }
+
                 if (space <= 0) {
                     constraintList.add(new DisabledConstraint(algorithm));
                     continue;
@@ -351,6 +365,27 @@
             return true;
         }
 
+        // Check if constraints permit this AlgorithmParameters.
+        public boolean permits(String algorithm, AlgorithmParameters aps) {
+            List<Constraint> list = getConstraints(algorithm);
+            if (list == null) {
+                return true;
+            }
+
+            for (Constraint constraint : list) {
+                if (!constraint.permits(aps)) {
+                    if (debug != null) {
+                        debug.println("keySizeConstraint: failed algorithm " +
+                                "parameters constraint check " + aps);
+                    }
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
         // Check if constraints permit this cert.
         public void permits(String algorithm, ConstraintsParameters cp)
                 throws CertPathValidatorException {
@@ -445,6 +480,18 @@
         }
 
         /**
+         * Check if the algorithm constraint permits a given cryptographic
+         * parameters.
+         *
+         * @param parameters the cryptographic parameters
+         * @return 'true' if the cryptographic parameters is allowed,
+         *         'false' ortherwise.
+         */
+        public boolean permits(AlgorithmParameters parameters) {
+            return true;
+        }
+
+        /**
          * Check if an algorithm constraint is permitted with a given
          * ConstraintsParameters.
          *
@@ -528,6 +575,7 @@
          * call next() for any following constraints. If it does not, exit
          * as this constraint(s) does not restrict the operation.
          */
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             if (debug != null) {
@@ -551,100 +599,101 @@
      * This class handles the denyAfter constraint.  The date is in the UTC/GMT
      * timezone.
      */
-     private static class DenyAfterConstraint extends Constraint {
-         private Date denyAfterDate;
-         private static final SimpleDateFormat dateFormat =
-                 new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
+    private static class DenyAfterConstraint extends Constraint {
+        private Date denyAfterDate;
+        private static final SimpleDateFormat dateFormat =
+                new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
 
-         DenyAfterConstraint(String algo, int year, int month, int day) {
-             Calendar c;
+        DenyAfterConstraint(String algo, int year, int month, int day) {
+            Calendar c;
 
-             algorithm = algo;
+            algorithm = algo;
 
-             if (debug != null) {
-                 debug.println("DenyAfterConstraint read in as:  year " +
-                         year + ", month = " + month + ", day = " + day);
-             }
+            if (debug != null) {
+                debug.println("DenyAfterConstraint read in as:  year " +
+                        year + ", month = " + month + ", day = " + day);
+            }
 
-             c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
-                     .setDate(year, month - 1, day).build();
+            c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
+                    .setDate(year, month - 1, day).build();
 
-             if (year > c.getActualMaximum(Calendar.YEAR) ||
-                     year < c.getActualMinimum(Calendar.YEAR)) {
-                 throw new IllegalArgumentException(
-                         "Invalid year given in constraint: " + year);
-             }
-             if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
-                     (month - 1) < c.getActualMinimum(Calendar.MONTH)) {
-                 throw new IllegalArgumentException(
-                         "Invalid month given in constraint: " + month);
-             }
-             if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
-                     day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
-                 throw new IllegalArgumentException(
-                         "Invalid Day of Month given in constraint: " + day);
-             }
+            if (year > c.getActualMaximum(Calendar.YEAR) ||
+                    year < c.getActualMinimum(Calendar.YEAR)) {
+                throw new IllegalArgumentException(
+                        "Invalid year given in constraint: " + year);
+            }
+            if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
+                    (month - 1) < c.getActualMinimum(Calendar.MONTH)) {
+                throw new IllegalArgumentException(
+                        "Invalid month given in constraint: " + month);
+            }
+            if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
+                    day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
+                throw new IllegalArgumentException(
+                        "Invalid Day of Month given in constraint: " + day);
+            }
 
-             denyAfterDate = c.getTime();
-             if (debug != null) {
-                 debug.println("DenyAfterConstraint date set to: " +
-                         dateFormat.format(denyAfterDate));
-             }
-         }
+            denyAfterDate = c.getTime();
+            if (debug != null) {
+                debug.println("DenyAfterConstraint date set to: " +
+                        dateFormat.format(denyAfterDate));
+            }
+        }
 
-         /*
-          * Checking that the provided date is not beyond the constraint date.
-          * The provided date can be the PKIXParameter date if given,
-          * otherwise it is the current date.
-          *
-          * If the constraint disallows, call next() for any following
-          * constraints. Throw an exception if this is the last constraint.
-          */
-         @Override
-         public void permits(ConstraintsParameters cp)
-                 throws CertPathValidatorException {
-             Date currentDate;
-             String errmsg;
+        /*
+         * Checking that the provided date is not beyond the constraint date.
+         * The provided date can be the PKIXParameter date if given,
+         * otherwise it is the current date.
+         *
+         * If the constraint disallows, call next() for any following
+         * constraints. Throw an exception if this is the last constraint.
+         */
+        @Override
+        public void permits(ConstraintsParameters cp)
+                throws CertPathValidatorException {
+            Date currentDate;
+            String errmsg;
 
-             if (cp.getJARTimestamp() != null) {
-                 currentDate = cp.getJARTimestamp().getTimestamp();
-                 errmsg = "JAR Timestamp date: ";
-             } else if (cp.getPKIXParamDate() != null) {
-                 currentDate = cp.getPKIXParamDate();
-                 errmsg = "PKIXParameter date: ";
-             } else {
-                 currentDate = new Date();
-                 errmsg = "Current date: ";
-             }
+            if (cp.getJARTimestamp() != null) {
+                currentDate = cp.getJARTimestamp().getTimestamp();
+                errmsg = "JAR Timestamp date: ";
+            } else if (cp.getPKIXParamDate() != null) {
+                currentDate = cp.getPKIXParamDate();
+                errmsg = "PKIXParameter date: ";
+            } else {
+                currentDate = new Date();
+                errmsg = "Current date: ";
+            }
 
-             if (!denyAfterDate.after(currentDate)) {
-                 if (next(cp)) {
-                     return;
-                 }
-                 throw new CertPathValidatorException(
-                         "denyAfter constraint check failed: " + algorithm +
-                         " used with Constraint date: " +
-                         dateFormat.format(denyAfterDate) + "; " + errmsg +
-                         dateFormat.format(currentDate) + extendedMsg(cp),
-                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
-             }
-         }
+            if (!denyAfterDate.after(currentDate)) {
+                if (next(cp)) {
+                    return;
+                }
+                throw new CertPathValidatorException(
+                        "denyAfter constraint check failed: " + algorithm +
+                        " used with Constraint date: " +
+                        dateFormat.format(denyAfterDate) + "; " + errmsg +
+                        dateFormat.format(currentDate) + extendedMsg(cp),
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
+        }
 
-         /*
-          * Return result if the constraint's date is beyond the current date
-          * in UTC timezone.
-          */
-         public boolean permits(Key key) {
-             if (next(key)) {
-                 return true;
-             }
-             if (debug != null) {
-                 debug.println("DenyAfterConstraints.permits(): " + algorithm);
-             }
+        /*
+         * Return result if the constraint's date is beyond the current date
+         * in UTC timezone.
+         */
+        @Override
+        public boolean permits(Key key) {
+            if (next(key)) {
+                return true;
+            }
+            if (debug != null) {
+                debug.println("DenyAfterConstraints.permits(): " + algorithm);
+            }
 
-             return denyAfterDate.after(new Date());
-         }
-     }
+            return denyAfterDate.after(new Date());
+        }
+    }
 
     /*
      * The usage constraint is for the "usage" keyword.  It checks against the
@@ -658,6 +707,7 @@
             this.usages = usages;
         }
 
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             for (String usage : usages) {
@@ -703,7 +753,6 @@
         private int minSize;            // the minimal available key size
         private int maxSize;            // the maximal available key size
         private int prohibitedSize = -1;    // unavailable key sizes
-        private int size;
 
         public KeySizeConstraint(String algo, Operator operator, int length) {
             algorithm = algo;
@@ -747,6 +796,7 @@
          * constraint  Any permitted constraint will exit the linked list
          * to allow the operation.
          */
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             Key key = null;
@@ -761,8 +811,9 @@
                     return;
                 }
                 throw new CertPathValidatorException(
-                        "Algorithm constraints check failed on keysize limits. "
-                        + algorithm + " " + size + "bit key" + extendedMsg(cp),
+                        "Algorithm constraints check failed on keysize limits. " +
+                        algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
+                        extendedMsg(cp),
                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
             }
         }
@@ -770,6 +821,7 @@
 
         // Check if key constraint disable the specified key
         // Uses old style permit()
+        @Override
         public boolean permits(Key key) {
             // If we recursively find a constraint that permits us to use
             // this key, return true and skip any other constraint checks.
@@ -783,13 +835,37 @@
             return permitsImpl(key);
         }
 
+        @Override
+        public boolean permits(AlgorithmParameters parameters) {
+            String paramAlg = parameters.getAlgorithm();
+            if (!algorithm.equalsIgnoreCase(parameters.getAlgorithm())) {
+                // Consider the impact of the algorithm aliases.
+                Collection<String> aliases =
+                        AlgorithmDecomposer.getAliases(algorithm);
+                if (!aliases.contains(paramAlg)) {
+                    return true;
+                }
+            }
+
+            int keySize = KeyUtil.getKeySize(parameters);
+            if (keySize == 0) {
+                return false;
+            } else if (keySize > 0) {
+                return !((keySize < minSize) || (keySize > maxSize) ||
+                    (prohibitedSize == keySize));
+            }   // Otherwise, the key size is not accessible or determined.
+                // Conservatively, please don't disable such keys.
+
+            return true;
+        }
+
         private boolean permitsImpl(Key key) {
             // Verify this constraint is for this public key algorithm
             if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
                 return true;
             }
 
-            size = KeyUtil.getKeySize(key);
+            int size = KeyUtil.getKeySize(key);
             if (size == 0) {
                 return false;    // we don't allow any key of size 0.
             } else if (size > 0) {
@@ -810,6 +886,7 @@
             algorithm = algo;
         }
 
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             throw new CertPathValidatorException(
@@ -818,6 +895,7 @@
                     null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
 
+        @Override
         public boolean permits(Key key) {
             return false;
         }
--- a/src/java.base/share/classes/sun/security/util/HostnameChecker.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/util/HostnameChecker.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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,6 +32,7 @@
 import java.security.cert.*;
 import java.util.*;
 import javax.security.auth.x500.X500Principal;
+import javax.net.ssl.SNIHostName;
 
 import sun.net.util.IPAddressUtil;
 import sun.security.ssl.ClientKeyExchangeService;
@@ -201,6 +202,15 @@
     private void matchDNS(String expectedName, X509Certificate cert,
                           boolean chainsToPublicCA)
             throws CertificateException {
+        // Check that the expected name is a valid domain name.
+        try {
+            // Using the checking implemented in SNIHostName
+            SNIHostName sni = new SNIHostName(expectedName);
+        } catch (IllegalArgumentException iae) {
+            throw new CertificateException(
+                "Illegal given domain name: " + expectedName, iae);
+        }
+
         Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
         if (subjAltNames != null) {
             boolean foundDNS = false;
@@ -277,6 +287,19 @@
         if (hasIllegalWildcard(name, template, chainsToPublicCA)) {
             return false;
         }
+
+        // check the validity of the domain name template.
+        try {
+            // Replacing wildcard character '*' with 'x' so as to check
+            // the domain name template validity.
+            //
+            // Using the checking implemented in SNIHostName
+            SNIHostName sni = new SNIHostName(template.replace('*', 'x'));
+        } catch (IllegalArgumentException iae) {
+            // It would be nice to add debug log if not matching.
+            return false;
+        }
+
         if (checkType == TYPE_TLS) {
             return matchAllWildcards(name, template);
         } else if (checkType == TYPE_LDAP) {
--- a/src/java.base/share/classes/sun/security/util/KeyUtil.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/util/KeyUtil.java	Mon Jun 19 11:29:42 2017 -0700
@@ -25,6 +25,7 @@
 
 package sun.security.util;
 
+import java.security.AlgorithmParameters;
 import java.security.Key;
 import java.security.PrivilegedAction;
 import java.security.AccessController;
@@ -35,6 +36,8 @@
 import java.security.interfaces.DSAParams;
 import java.security.SecureRandom;
 import java.security.spec.KeySpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.SecretKey;
 import javax.crypto.interfaces.DHKey;
 import javax.crypto.interfaces.DHPublicKey;
@@ -100,6 +103,61 @@
     }
 
     /**
+     * Returns the key size of the given cryptographic parameters in bits.
+     *
+     * @param parameters the cryptographic parameters, cannot be null
+     * @return the key size of the given cryptographic parameters in bits,
+     *       or -1 if the key size is not accessible
+     */
+    public static final int getKeySize(AlgorithmParameters parameters) {
+
+        String algorithm = parameters.getAlgorithm();
+        switch (algorithm) {
+            case "EC":
+                try {
+                    ECKeySizeParameterSpec ps = parameters.getParameterSpec(
+                            ECKeySizeParameterSpec.class);
+                    if (ps != null) {
+                        return ps.getKeySize();
+                    }
+                } catch (InvalidParameterSpecException ipse) {
+                    // ignore
+                }
+
+                try {
+                    ECParameterSpec ps = parameters.getParameterSpec(
+                            ECParameterSpec.class);
+                    if (ps != null) {
+                        return ps.getOrder().bitLength();
+                    }
+                } catch (InvalidParameterSpecException ipse) {
+                    // ignore
+                }
+
+                // Note: the ECGenParameterSpec case should be covered by the
+                // ECParameterSpec case above.
+                // See ECUtil.getECParameterSpec(Provider, String).
+
+                break;
+            case "DiffieHellman":
+                try {
+                    DHParameterSpec ps = parameters.getParameterSpec(
+                            DHParameterSpec.class);
+                    if (ps != null) {
+                        return ps.getP().bitLength();
+                    }
+                } catch (InvalidParameterSpecException ipse) {
+                    // ignore
+                }
+                break;
+
+            // May support more AlgorithmParameters algorithms in the future.
+        }
+
+        return -1;
+    }
+
+    /**
      * Returns whether the key is valid or not.
      * <P>
      * Note that this method is only apply to DHPublicKey at present.
--- a/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -107,6 +107,8 @@
         /* get the headers from the manifest for this entry */
         /* if there aren't any, we can't verify any digests for this entry */
 
+        skip = false;
+
         Attributes attr = man.getAttributes(name);
         if (attr == null) {
             // ugh. we should be able to remove this at some point.
@@ -141,7 +143,6 @@
                 }
 
                 if (digest != null) {
-                    skip = false;
                     digest.reset();
                     digests.add(digest);
                     manifestHashes.add(
@@ -197,6 +198,10 @@
             return null;
         }
 
+        if (digests.isEmpty()) {
+            throw new SecurityException("digest missing for " + name);
+        }
+
         if (signers != null)
             return signers;
 
--- a/src/java.base/share/classes/sun/security/x509/NameConstraintsExtension.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/classes/sun/security/x509/NameConstraintsExtension.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -33,6 +33,7 @@
 
 import javax.security.auth.x500.X500Principal;
 
+import sun.net.util.IPAddressUtil;
 import sun.security.util.*;
 import sun.security.pkcs.PKCS9Attribute;
 
@@ -440,6 +441,7 @@
         X500Principal subjectPrincipal = cert.getSubjectX500Principal();
         X500Name subject = X500Name.asX500Name(subjectPrincipal);
 
+        // Check subject as an X500Name
         if (subject.isEmpty() == false) {
             if (verify(subject) == false) {
                 return false;
@@ -465,12 +467,51 @@
                         "certificate: " + ce.getMessage());
         }
 
-        // If there are no subjectAlternativeNames, perform the special-case
-        // check where if the subjectName contains any EMAILADDRESS
-        // attributes, they must be checked against RFC822 constraints.
-        // If that passes, we're fine.
         if (altNames == null) {
-            return verifyRFC822SpecialCase(subject);
+            altNames = new GeneralNames();
+
+            // RFC 5280 4.2.1.10:
+            // When constraints are imposed on the rfc822Name name form,
+            // but the certificate does not include a subject alternative name,
+            // the rfc822Name constraint MUST be applied to the attribute of
+            // type emailAddress in the subject distinguished name.
+            for (AVA ava : subject.allAvas()) {
+                ObjectIdentifier attrOID = ava.getObjectIdentifier();
+                if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
+                    String attrValue = ava.getValueString();
+                    if (attrValue != null) {
+                        try {
+                            altNames.add(new GeneralName(
+                                    new RFC822Name(attrValue)));
+                        } catch (IOException ioe) {
+                            continue;
+                        }
+                    }
+                }
+            }
+        }
+
+        // If there is no IPAddressName or DNSName in subjectAlternativeNames,
+        // see if the last CN inside subjectName can be used instead.
+        DerValue derValue = subject.findMostSpecificAttribute
+                (X500Name.commonName_oid);
+        String cn = derValue == null ? null : derValue.getAsString();
+
+        if (cn != null) {
+            try {
+                if (IPAddressUtil.isIPv4LiteralAddress(cn) ||
+                        IPAddressUtil.isIPv6LiteralAddress(cn)) {
+                    if (!hasNameType(altNames, GeneralNameInterface.NAME_IP)) {
+                        altNames.add(new GeneralName(new IPAddressName(cn)));
+                    }
+                } else {
+                    if (!hasNameType(altNames, GeneralNameInterface.NAME_DNS)) {
+                        altNames.add(new GeneralName(new DNSName(cn)));
+                    }
+                }
+            } catch (IOException ioe) {
+                // OK, cn is neither IP nor DNS
+            }
         }
 
         // verify each subjectAltName
@@ -485,6 +526,15 @@
         return true;
     }
 
+    private static boolean hasNameType(GeneralNames names, int type) {
+        for (GeneralName name : names.names()) {
+            if (name.getType() == type) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * check whether a name conforms to these NameConstraints.
      * This involves verifying that the name is consistent with the
@@ -567,37 +617,6 @@
     }
 
     /**
-     * Perform the RFC 822 special case check. We have a certificate
-     * that does not contain any subject alternative names. Check that
-     * any EMAILADDRESS attributes in its subject name conform to these
-     * NameConstraints.
-     *
-     * @param subject the certificate's subject name
-     * @return true if certificate verifies successfully
-     * @throws IOException on error
-     */
-    public boolean verifyRFC822SpecialCase(X500Name subject) throws IOException {
-        for (AVA ava : subject.allAvas()) {
-            ObjectIdentifier attrOID = ava.getObjectIdentifier();
-            if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
-                String attrValue = ava.getValueString();
-                if (attrValue != null) {
-                    RFC822Name emailName;
-                    try {
-                        emailName = new RFC822Name(attrValue);
-                    } catch (IOException ioe) {
-                        continue;
-                    }
-                    if (!verify(emailName)) {
-                        return(false);
-                    }
-                }
-             }
-        }
-        return true;
-    }
-
-    /**
      * Clone all objects that may be modified during certificate validation.
      */
     public Object clone() {
--- a/src/java.base/share/conf/security/java.security	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/conf/security/java.security	Mon Jun 19 11:29:42 2017 -0700
@@ -545,21 +545,21 @@
 #     jdkCA
 #       This constraint prohibits the specified algorithm only if the
 #       algorithm is used in a certificate chain that terminates at a marked
-#       trust anchor in the lib/security/cacerts keystore.  If the jdkCA
-#       constraint is not set, then all chains using the specified algorithm
+#       trust anchor in the lib/security/cacerts keystore.  If the jdkCA
+#       constraint is not set, then all chains using the specified algorithm
 #       are restricted.  jdkCA may only be used once in a DisabledAlgorithm
 #       expression.
-#       Example:  To apply this constraint to SHA-1 certificates, include
-#       the following:  "SHA1 jdkCA"
+#       Example:  To apply this constraint to SHA-1 certificates, include
+#       the following:  "SHA1 jdkCA"
 #
 #   DenyAfterConstraint:
 #     denyAfter YYYY-MM-DD
 #       This constraint prohibits a certificate with the specified algorithm
 #       from being used after the date regardless of the certificate's
-#       validity.  JAR files that are signed and timestamped before the
+#       validity.  JAR files that are signed and timestamped before the
 #       constraint date with certificates containing the disabled algorithm
-#       will not be restricted.  The date is processed in the UTC timezone.
-#       This constraint can only be used once in a DisabledAlgorithm
+#       will not be restricted.  The date is processed in the UTC timezone.
+#       This constraint can only be used once in a DisabledAlgorithm
 #       expression.
 #       Example:  To deny usage of RSA 2048 bit certificates after Feb 3 2020,
 #       use the following:  "RSA keySize == 2048 & denyAfter 2020-02-03"
--- a/src/java.base/share/native/libjimage/imageFile.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/native/libjimage/imageFile.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -205,12 +205,19 @@
 // Manage a table of open image files.  This table allows multiple access points
 // to share an open image.
 ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
-    _table = new ImageFileReader*[_max];
+    _table = static_cast<ImageFileReader**>(calloc(_max, sizeof(ImageFileReader*)));
     assert(_table != NULL && "allocation failed");
 }
 
 ImageFileReaderTable::~ImageFileReaderTable() {
-    delete[] _table;
+    for (u4 i = 0; i < _count; i++) {
+        ImageFileReader* image = _table[i];
+
+        if (image != NULL) {
+            delete image;
+        }
+    }
+    free(_table);
 }
 
 // Add a new image entry to the table.
--- a/src/java.base/share/native/libjimage/imageFile.hpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/native/libjimage/imageFile.hpp	Mon Jun 19 11:29:42 2017 -0700
@@ -402,6 +402,7 @@
 // 'opened' by reference point and decremented when 'closed'.    Use of zero
 // leads the ImageFileReader to be actually closed and discarded.
 class ImageFileReader {
+friend class ImageFileReaderTable;
 private:
     // Manage a number of image files such that an image can be shared across
     // multiple uses (ex. loader.)
--- a/src/java.base/share/native/libverify/check_code.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.base/share/native/libverify/check_code.c	Mon Jun 19 11:29:42 2017 -0700
@@ -459,6 +459,8 @@
 
 static fullinfo_type cp_index_to_class_fullinfo(context_type *, int, int);
 
+static const char* get_result_signature(const char* signature);
+
 static char signature_to_fieldtype(context_type *context,
                                    const char **signature_p, fullinfo_type *info);
 
@@ -2789,7 +2791,7 @@
                                                                 operand);
             const char *result_signature;
             check_and_push(context, signature, VM_STRING_UTF);
-            result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC);
+            result_signature = get_result_signature(signature);
             if (result_signature++ == NULL) {
                 CCerror(context, "Illegal signature %s", signature);
             }
@@ -3712,6 +3714,42 @@
     longjmp(context->jump_buffer, 1);
 }
 
+/*
+ * Need to scan the entire signature to find the result type because
+ * types in the arg list and the result type could contain embedded ')'s.
+ */
+static const char* get_result_signature(const char* signature) {
+    const char *p;
+    for (p = signature; *p != JVM_SIGNATURE_ENDFUNC; p++) {
+        switch (*p) {
+          case JVM_SIGNATURE_BOOLEAN:
+          case JVM_SIGNATURE_BYTE:
+          case JVM_SIGNATURE_CHAR:
+          case JVM_SIGNATURE_SHORT:
+          case JVM_SIGNATURE_INT:
+          case JVM_SIGNATURE_FLOAT:
+          case JVM_SIGNATURE_DOUBLE:
+          case JVM_SIGNATURE_LONG:
+          case JVM_SIGNATURE_FUNC:  /* ignore initial (, if given */
+            break;
+          case JVM_SIGNATURE_CLASS:
+            while (*p != JVM_SIGNATURE_ENDCLASS) p++;
+            break;
+          case JVM_SIGNATURE_ARRAY:
+            while (*p == JVM_SIGNATURE_ARRAY) p++;
+            /* If an array of classes, skip over class name, too. */
+            if (*p == JVM_SIGNATURE_CLASS) {
+                while (*p != JVM_SIGNATURE_ENDCLASS) p++;
+            }
+            break;
+          default:
+            /* Indicate an error. */
+            return NULL;
+        }
+    }
+    return p++; /* skip over ')'. */
+}
+
 static char
 signature_to_fieldtype(context_type *context,
                        const char **signature_p, fullinfo_type *full_info_p)
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Mon Jun 19 11:29:42 2017 -0700
@@ -392,6 +392,17 @@
         }
     }
 
+    private void skipPastImage(int imageIndex) {
+        cbLock.lock();
+        try {
+            gotoImage(imageIndex);
+            skipImage();
+        } catch (IOException | IndexOutOfBoundsException e) {
+        } finally {
+            cbLock.unlock();
+        }
+    }
+
     @SuppressWarnings("fallthrough")
     private int getNumImagesOnThread(boolean allowSearch)
       throws IOException {
@@ -1340,7 +1351,8 @@
          * just a 1-line intermediate data transfer buffer that will not
          * affect the acceleration of the resulting image.
          */
-        boolean aborted = readImage(structPointer,
+        boolean aborted = readImage(imageIndex,
+                                    structPointer,
                                     buffer.getData(),
                                     numRasterBands,
                                     srcBands,
@@ -1502,7 +1514,8 @@
     /**
      * Returns {@code true} if the read was aborted.
      */
-    private native boolean readImage(long structPointer,
+    private native boolean readImage(int imageIndex,
+                                     long structPointer,
                                      byte [] buffer,
                                      int numRasterBands,
                                      int [] srcBands,
--- a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java	Mon Jun 19 11:29:42 2017 -0700
@@ -26,6 +26,9 @@
 package javax.imageio.spi;
 
 import java.io.File;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -755,13 +758,14 @@
 
     Class<?> category;
 
-    // Provider Objects organized by partial oridering
-    PartiallyOrderedSet<Object> poset = new PartiallyOrderedSet<>();
+    // Provider Objects organized by partial ordering
+    final PartiallyOrderedSet<Object> poset = new PartiallyOrderedSet<>();
 
     // Class -> Provider Object of that class
     // No way to express heterogeneous map, we want
     // Map<Class<T>, T>, where T is ?
-    Map<Class<?>, Object> map = new HashMap<>();
+    final Map<Class<?>, Object> map = new HashMap<>();
+    final Map<Class<?>, AccessControlContext> accMap = new HashMap<>();
 
     public SubRegistry(ServiceRegistry registry, Class<?> category) {
         this.registry = registry;
@@ -776,6 +780,7 @@
             deregisterServiceProvider(oprovider);
         }
         map.put(provider.getClass(), provider);
+        accMap.put(provider.getClass(), AccessController.getContext());
         poset.add(provider);
         if (provider instanceof RegisterableService) {
             RegisterableService rs = (RegisterableService)provider;
@@ -800,6 +805,7 @@
 
         if (provider == oprovider) {
             map.remove(provider.getClass());
+            accMap.remove(provider.getClass());
             poset.remove(provider);
             if (provider instanceof RegisterableService) {
                 RegisterableService rs = (RegisterableService)provider;
@@ -849,10 +855,17 @@
 
             if (provider instanceof RegisterableService) {
                 RegisterableService rs = (RegisterableService)provider;
-                rs.onDeregistration(registry, category);
+                AccessControlContext acc = accMap.get(provider.getClass());
+                if (acc != null || System.getSecurityManager() == null) {
+                    AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    rs.onDeregistration(registry, category);
+                        return null;
+                    }, acc);
+                }
             }
         }
         poset.clear();
+        accMap.clear();
     }
 
     @SuppressWarnings("deprecation")
--- a/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java	Mon Jun 19 11:29:42 2017 -0700
@@ -110,7 +110,7 @@
      * @return the command list
      */
     public Action[] getActions() {
-        return defaultActions;
+        return defaultActions.clone();
     }
 
     /**
--- a/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java	Mon Jun 19 11:29:42 2017 -0700
@@ -29,6 +29,10 @@
 import java.awt.Image;
 import java.awt.image.ImageObserver;
 
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 public abstract class ImageWatched {
     public static Link endlink = new Link();
 
@@ -85,16 +89,26 @@
         }
     }
 
+    static class AccWeakReference<T> extends WeakReference<T> {
+
+         private final AccessControlContext acc;
+
+         AccWeakReference(T ref) {
+             super(ref);
+             acc = AccessController.getContext();
+         }
+    }
+
     /*
      * Standard Link implementation to manage a Weak Reference
      * to an ImageObserver.
      */
     public static class WeakLink extends Link {
-        private WeakReference<ImageObserver> myref;
+        private final AccWeakReference<ImageObserver> myref;
         private Link next;
 
         public WeakLink(ImageObserver obs, Link next) {
-            myref = new WeakReference<ImageObserver>(obs);
+            myref = new AccWeakReference<ImageObserver>(obs);
             this.next = next;
         }
 
@@ -120,6 +134,19 @@
             return this;
         }
 
+        private static boolean update(ImageObserver iw, AccessControlContext acc,
+                                      Image img, int info,
+                                      int x, int y, int w, int h) {
+
+            if (acc != null || System.getSecurityManager() != null) {
+                return AccessController.doPrivileged(
+                       (PrivilegedAction<Boolean>) () -> {
+                            return iw.imageUpdate(img, info, x, y, w, h);
+                      }, acc);
+            }
+            return false;
+        }
+
         public boolean newInfo(Image img, int info,
                                int x, int y, int w, int h)
         {
@@ -129,7 +156,7 @@
             if (myiw == null) {
                 // My referent is null so we must prune in a second pass.
                 ret = true;
-            } else if (myiw.imageUpdate(img, info, x, y, w, h) == false) {
+            } else if (update(myiw, myref.acc, img, info, x, y, w, h) == false) {
                 // My referent has lost interest so clear it and ask
                 // for a pruning pass to remove it later.
                 myref.clear();
--- a/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c	Mon Jun 19 11:29:42 2017 -0700
@@ -72,6 +72,7 @@
 static jmethodID JPEGImageReader_pushBackID;
 static jmethodID JPEGImageReader_passStartedID;
 static jmethodID JPEGImageReader_passCompleteID;
+static jmethodID JPEGImageReader_skipPastImageID;
 static jmethodID JPEGImageWriter_writeOutputDataID;
 static jmethodID JPEGImageWriter_warningOccurredID;
 static jmethodID JPEGImageWriter_warningWithMessageID;
@@ -1472,6 +1473,10 @@
                                                      cls,
                                                      "pushBack",
                                                      "(I)V"));
+    CHECK_NULL(JPEGImageReader_skipPastImageID = (*env)->GetMethodID(env,
+                                                     cls,
+                                                     "skipPastImage",
+                                                     "(I)V"));
     CHECK_NULL(JPEGQTable_tableID = (*env)->GetFieldID(env,
                                             qTableClass,
                                             "qTable",
@@ -1853,6 +1858,7 @@
 Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
     (JNIEnv *env,
      jobject this,
+     jint imageIndex,
      jlong ptr,
      jbyteArray buffer,
      jint numBands,
@@ -2181,12 +2187,23 @@
      * We are done, but we might not have read all the lines, or all
      * the passes, so use jpeg_abort instead of jpeg_finish_decompress.
      */
-    if (cinfo->output_scanline == cinfo->output_height) {
-        //    if ((cinfo->output_scanline == cinfo->output_height) &&
-        //(jpeg_input_complete(cinfo))) {  // We read the whole file
+    if ((cinfo->output_scanline != cinfo->output_height) ||
+        data->abortFlag == JNI_TRUE)
+     {
+        jpeg_abort_decompress(cinfo);
+     } else if ((!jpeg_input_complete(cinfo)) &&
+                (progressive &&
+                 (cinfo->input_scan_number > maxProgressivePass))) {
+        /* We haven't reached EOI, but we need to skip to there */
+        (*cinfo->src->term_source) (cinfo);
+        /* We can use jpeg_abort to release memory and reset global_state */
+        jpeg_abort((j_common_ptr) cinfo);
+        (*env)->CallVoidMethod(env,
+                               this,
+                               JPEGImageReader_skipPastImageID,
+                               imageIndex);
+    } else {
         jpeg_finish_decompress(cinfo);
-    } else {
-        jpeg_abort_decompress(cinfo);
     }
 
     free(scanLinePtr);
--- a/src/java.desktop/share/native/liblcms/cmscgats.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/liblcms/cmscgats.c	Mon Jun 19 11:29:42 2017 -0700
@@ -900,7 +900,7 @@
             k = 0;
             NextCh(it8);
 
-            while (k < MAXSTR && it8->ch != sng) {
+            while (k < (MAXSTR-1) && it8->ch != sng) {
 
                 if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1;
                 else {
@@ -2053,14 +2053,18 @@
 static
 void ReadType(cmsIT8* it8, char* SheetTypePtr)
 {
+    cmsInt32Number cnt = 0;
+
     // First line is a very special case.
 
     while (isseparator(it8->ch))
             NextCh(it8);
 
-    while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
+    while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != 0) {
 
         *SheetTypePtr++= (char) it8 ->ch;
+        if (cnt++ < MAXSTR)
+            *SheetTypePtr++= (char) it8 ->ch;
         NextCh(it8);
     }
 
@@ -2253,7 +2257,7 @@
 // that should be something like some printable characters plus a \n
 // returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?
 static
-int IsMyBlock(cmsUInt8Number* Buffer, int n)
+int IsMyBlock(const cmsUInt8Number* Buffer, int n)
 {
     int words = 1, space = 0, quot = 0;
     int i;
@@ -2317,7 +2321,7 @@
 // ---------------------------------------------------------- Exported routines
 
 
-cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len)
+cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cmsUInt32Number len)
 {
     cmsHANDLE hIT8;
     cmsIT8*  it8;
@@ -2326,7 +2330,7 @@
     _cmsAssert(Ptr != NULL);
     _cmsAssert(len != 0);
 
-    type = IsMyBlock((cmsUInt8Number*)Ptr, len);
+    type = IsMyBlock((const cmsUInt8Number*)Ptr, len);
     if (type == 0) return NULL;
 
     hIT8 = cmsIT8Alloc(ContextID);
--- a/src/java.desktop/share/native/liblcms/cmsnamed.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/liblcms/cmsnamed.c	Mon Jun 19 11:29:42 2017 -0700
@@ -546,7 +546,11 @@
         size = v ->Allocated * 2;
 
     // Keep a maximum color lists can grow, 100K entries seems reasonable
-    if (size > 1024*100) return FALSE;
+    if (size > 1024 * 100) {
+        _cmsFree(v->ContextID, (void*) v->List);
+        v->List = NULL;
+        return FALSE;
+    }
 
     NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR));
     if (NewPtr == NULL)
@@ -568,8 +572,11 @@
     v ->nColors   = 0;
     v ->ContextID  = ContextID;
 
-    while (v -> Allocated < n){
-        if (!GrowNamedColorList(v)) return NULL;
+    while (v -> Allocated < n) {
+        if (!GrowNamedColorList(v)) {
+            _cmsFree(ContextID, (void*) v);
+            return NULL;
+        }
     }
 
     strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
--- a/src/java.desktop/share/native/liblcms/cmsopt.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/liblcms/cmsopt.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1483,6 +1483,7 @@
 
         // LUT optimizes to nothing. Set the identity LUT
         cmsStageFree(ObtainedCurves);
+        ObtainedCurves = NULL;
 
         if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
             goto Error;
--- a/src/java.desktop/share/native/liblcms/cmstypes.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/liblcms/cmstypes.c	Mon Jun 19 11:29:42 2017 -0700
@@ -4460,7 +4460,8 @@
     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
     if (NewLUT == NULL) return NULL;
 
-    if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
+    if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error;
+    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error;
 
     if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
         if (NewLUT != NULL) cmsPipelineFree(NewLUT);
@@ -4472,6 +4473,12 @@
     *nItems = 1;
     return NewLUT;
 
+    // Error
+Error:
+    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
+    *nItems = 0;
+    return NULL;
+
     cmsUNUSED_PARAMETER(SizeOfTag);
 }
 
--- a/src/java.desktop/share/native/liblcms/lcms2.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/share/native/liblcms/lcms2.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1836,7 +1836,7 @@
 
 // Persistence
 CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName);
-CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len);
+CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cmsUInt32Number len);
 // CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromIOhandler(cmsContext ContextID, cmsIOHANDLER* io);
 
 CMSAPI cmsBool          CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName);
--- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -98,7 +98,7 @@
 
     jstring ret = JNU_NewStringPlatform(env, pAdapterId);
 
-    delete pAdapterId;
+    delete[] pAdapterId;
 
     return ret;
 }
--- a/src/java.desktop/windows/native/libawt/windows/CmdIDList.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/CmdIDList.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -61,29 +61,36 @@
     m_first_free = first_index; // head of the free list
 }
 
+
+jboolean AwtCmdIDList::isFreeIDAvailable() {
+    CriticalSection::Lock l(m_lock);
+
+    if (m_first_free == -1) {   // out of free ids
+        if (m_capacity == ARRAY_MAXIMUM_SIZE) {
+            return JNI_FALSE;
+        }
+    }
+    return JNI_TRUE;
+}
+
 // Assign an id to the object.  Recycle the first free entry from the
 // head of the free list or allocate more memory for a new free list.
 UINT AwtCmdIDList::Add(AwtObject* obj)
 {
     CriticalSection::Lock l(m_lock);
+    if (!isFreeIDAvailable()) {
+        throw std::bad_alloc(); // fatal error
+    }
 
     if (m_first_free == -1) {   // out of free ids
-        if (m_capacity == ARRAY_MAXIMUM_SIZE) {
-            // Really bad - out of ids.  Since we hardly can have *so*
-            // many items simultaneously in existence, we have an id
-            // leak somewhere.
-            DASSERT(FALSE);
-            return 0;
-        }
-        else {                  // snarf a bigger arena
-            UINT old_capacity = m_capacity; // will be the first free entry
-            m_capacity += ARRAY_SIZE_INCREMENT;
-            if (m_capacity > ARRAY_MAXIMUM_SIZE)
-                m_capacity = ARRAY_MAXIMUM_SIZE;
-            m_array = (CmdIDEntry *)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_array,
-                                        m_capacity, sizeof(CmdIDEntry*));
-            BuildFreeList(old_capacity);
-        }
+        // snarf a bigger arena
+        UINT old_capacity = m_capacity; // will be the first free entry
+        m_capacity += ARRAY_SIZE_INCREMENT;
+        if (m_capacity > ARRAY_MAXIMUM_SIZE)
+            m_capacity = ARRAY_MAXIMUM_SIZE;
+        m_array = (CmdIDEntry *)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_array,
+                                    m_capacity, sizeof(CmdIDEntry*));
+        BuildFreeList(old_capacity);
     }
 
     DASSERT(m_first_free != -1);
--- a/src/java.desktop/windows/native/libawt/windows/CmdIDList.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/CmdIDList.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -38,6 +38,7 @@
     UINT Add(AwtObject* obj);
     AwtObject* Lookup(UINT id);
     void Remove(UINT id);
+    jboolean isFreeIDAvailable();
 
     CriticalSection    m_lock;
 
--- a/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -508,14 +508,14 @@
           names = env->NewObjectArray(cReturned, cls, NULL);
       }
       if (names == NULL || cls == NULL) {
-          delete buf;
+          delete[] buf;
           return names;
       }
 
       for (int i = 0; i < cReturned; i++) {
           utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i));
             if (utf_str == NULL) {
-                delete buf;
+                delete[] buf;
                 return names;
             }
             env->SetObjectArrayElement(names, i, utf_str);
--- a/src/java.desktop/windows/native/libawt/windows/awt.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt.h	Mon Jun 19 11:29:42 2017 -0700
@@ -57,15 +57,6 @@
     }                                                                     \
 }
 
-#define JNI_CHECK_PEER_GOTO(peer, where) {                                \
-    JNI_CHECK_NULL_GOTO(peer, "peer", where);                             \
-    pData = JNI_GET_PDATA(peer);                                          \
-    if (pData == NULL) {                                                  \
-        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
-        goto where;                                                       \
-    }                                                                     \
-}
-
 #define JNI_CHECK_NULL_RETURN(obj, msg) {                                 \
     if (obj == NULL) {                                                    \
         env->ExceptionClear();                                            \
@@ -74,15 +65,6 @@
     }                                                                     \
 }
 
-#define JNI_CHECK_PEER_RETURN(peer) {                                     \
-    JNI_CHECK_NULL_RETURN(peer, "peer");                                  \
-    pData = JNI_GET_PDATA(peer);                                          \
-    if (pData == NULL) {                                                  \
-        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
-        return;                                                           \
-    }                                                                     \
-}
-
 #define JNI_CHECK_PEER_CREATION_RETURN(peer) {                            \
     if (peer == NULL ) {                                                  \
         return;                                                           \
@@ -109,6 +91,33 @@
     }                                                                     \
 }
 
+/**
+ * This macros must be used under SyncCall or on the Toolkit thread.
+ */
+#define JNI_CHECK_PEER_GOTO(peer, where) {                                \
+    JNI_CHECK_NULL_GOTO(peer, "peer", where);                             \
+    pData = JNI_GET_PDATA(peer);                                          \
+    if (pData == NULL) {                                                  \
+        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
+        goto where;                                                       \
+    }                                                                     \
+}
+
+/**
+ * This macros must be used under SyncCall or on the Toolkit thread.
+ */
+#define JNI_CHECK_PEER_RETURN(peer) {                                     \
+    JNI_CHECK_NULL_RETURN(peer, "peer");                                  \
+    pData = JNI_GET_PDATA(peer);                                          \
+    if (pData == NULL) {                                                  \
+        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
+        return;                                                           \
+    }                                                                     \
+}
+
+/**
+ * This macros must be used under SyncCall or on the Toolkit thread.
+ */
 #define JNI_CHECK_PEER_RETURN_NULL(peer) {                                \
     JNI_CHECK_NULL_RETURN_NULL(peer, "peer");                             \
     pData = JNI_GET_PDATA(peer);                                          \
@@ -118,6 +127,9 @@
     }                                                                     \
 }
 
+/**
+ * This macros must be used under SyncCall or on the Toolkit thread.
+ */
 #define JNI_CHECK_PEER_RETURN_VAL(peer, val) {                            \
     JNI_CHECK_NULL_RETURN_VAL(peer, "peer", val);                         \
     pData = JNI_GET_PDATA(peer);                                          \
--- a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -65,6 +65,7 @@
 /* Create a new AwtButton object and window. */
 AwtButton* AwtButton::Create(jobject self, jobject parent)
 {
+    DASSERT(AwtToolkit::IsMainThread());
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     /* the result */
@@ -88,7 +89,6 @@
 
         JNI_CHECK_PEER_GOTO(parent, done);
         awtParent = (AwtCanvas*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "awtParent", done);
 
         target = env->GetObjectField(self, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "target", done);
@@ -375,9 +375,6 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(self);
-
     SetLabelStruct *sls = new SetLabelStruct;
     sls->button = env->NewGlobalRef(self);
     sls->label = (label != NULL) ? (jstring)env->NewGlobalRef(label) : NULL;
@@ -399,14 +396,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
-
     AwtToolkit::CreateComponent(
         self, parent, (AwtToolkit::ComponentFactory)AwtButton::Create);
 
-    JNI_CHECK_PEER_CREATION_RETURN(self);
-
     CATCH_BAD_ALLOC;
 }
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Canvas.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Canvas.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -59,6 +59,7 @@
  */
 AwtCanvas* AwtCanvas::Create(jobject self, jobject hParent)
 {
+    DASSERT(AwtToolkit::IsMainThread());
     TRY;
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
@@ -74,12 +75,11 @@
             return NULL;
         }
 
+        PDATA pData;
         AwtComponent* parent;
 
-        JNI_CHECK_NULL_GOTO(hParent, "null hParent", done);
-
-        parent = (AwtComponent*)JNI_GET_PDATA(hParent);
-        JNI_CHECK_NULL_GOTO(parent, "null parent", done);
+        JNI_CHECK_PEER_GOTO(hParent, done);
+        parent = (AwtCanvas*)pData;
 
         target = env->GetObjectField(self, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
@@ -236,12 +236,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtCanvas::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -70,6 +70,7 @@
 
 AwtCheckbox* AwtCheckbox::Create(jobject peer, jobject parent)
 {
+    DASSERT(AwtToolkit::IsMainThread());
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     jstring label = NULL;
@@ -81,11 +82,10 @@
             return NULL;
         }
 
+        PDATA pData;
         AwtComponent* awtParent;
-        JNI_CHECK_NULL_GOTO(parent, "null parent", done);
-
-        awtParent = (AwtComponent*)JNI_GET_PDATA(parent);
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
+        JNI_CHECK_PEER_GOTO(parent, done);
+        awtParent = (AwtCanvas*)pData;
 
         target = env->GetObjectField(peer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
@@ -669,11 +669,10 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtCheckbox::Create);
+    PDATA pData;
     JNI_CHECK_PEER_CREATION_RETURN(self);
 
 #ifdef DEBUG
--- a/src/java.desktop/windows/native/libawt/windows/awt_Choice.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Choice.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -104,7 +104,7 @@
 }
 
 AwtChoice* AwtChoice::Create(jobject peer, jobject parent) {
-
+    DASSERT(AwtToolkit::IsMainThread());
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     jobject target = NULL;
@@ -115,12 +115,10 @@
         if (env->EnsureLocalCapacity(1) < 0) {
             return NULL;
         }
+        PDATA pData;
         AwtCanvas* awtParent;
-
-        JNI_CHECK_NULL_GOTO(parent, "null parent", done);
-
-        awtParent = (AwtCanvas*)JNI_GET_PDATA(parent);
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
+        JNI_CHECK_PEER_GOTO(parent, done);
+        awtParent = (AwtCanvas*)pData;
 
         target = env->GetObjectField(peer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
@@ -830,12 +828,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtChoice::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -151,6 +151,11 @@
     jobject component;
     jboolean doSetFocus;
 };
+// Struct for _SetParent function
+struct SetParentStruct {
+    jobject component;
+    jobject parentComp;
+};
 /************************************************************************/
 
 //////////////////////////////////////////////////////////////////////////
@@ -265,9 +270,6 @@
 {
     DASSERT(AwtToolkit::IsMainThread());
 
-    /* Disconnect all links. */
-    UnlinkObjects();
-
     /*
      * All the messages for this component are processed, native
      * resources are freed, and Java object is not connected to
@@ -279,6 +281,8 @@
 
 void AwtComponent::Dispose()
 {
+    DASSERT(AwtToolkit::IsMainThread());
+
     // NOTE: in case the component/toplevel was focused, Java should
     // have already taken care of proper transferring it or clearing.
 
@@ -297,8 +301,10 @@
     /* Release global ref to input method */
     SetInputMethod(NULL, TRUE);
 
-    if (m_childList != NULL)
+    if (m_childList != NULL) {
         delete m_childList;
+        m_childList = NULL;
+    }
 
     DestroyDropTarget();
     ReleaseDragCapture(0);
@@ -321,6 +327,9 @@
         m_brushBackground = NULL;
     }
 
+    /* Disconnect all links. */
+    UnlinkObjects();
+
     if (m_bPauseDestroy) {
         // AwtComponent::WmNcDestroy could be released now
         m_bPauseDestroy = FALSE;
@@ -6222,21 +6231,36 @@
     return result;
 }
 
-void AwtComponent::SetParent(void * param) {
+void AwtComponent::_SetParent(void * param)
+{
     if (AwtToolkit::IsMainThread()) {
-        AwtComponent** comps = (AwtComponent**)param;
-        if ((comps[0] != NULL) && (comps[1] != NULL)) {
-            HWND selfWnd = comps[0]->GetHWnd();
-            HWND parentWnd = comps[1]->GetHWnd();
-            if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
-                // Shouldn't trigger native focus change
-                // (only the proxy may be the native focus owner).
-                ::SetParent(selfWnd, parentWnd);
-            }
+        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+        SetParentStruct *data = (SetParentStruct*) param;
+        jobject self = data->component;
+        jobject parent = data->parentComp;
+
+        AwtComponent *awtComponent = NULL;
+        AwtComponent *awtParent = NULL;
+
+        PDATA pData;
+        JNI_CHECK_PEER_GOTO(self, ret);
+        awtComponent = (AwtComponent *)pData;
+        JNI_CHECK_PEER_GOTO(parent, ret);
+        awtParent = (AwtComponent *)pData;
+
+        HWND selfWnd = awtComponent->GetHWnd();
+        HWND parentWnd = awtParent->GetHWnd();
+        if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
+            // Shouldn't trigger native focus change
+            // (only the proxy may be the native focus owner).
+            ::SetParent(selfWnd, parentWnd);
         }
-        delete[] comps;
+ret:
+        env->DeleteGlobalRef(self);
+        env->DeleteGlobalRef(parent);
+        delete data;
     } else {
-        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param);
+        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetParent, param);
     }
 }
 
@@ -7063,15 +7087,12 @@
 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
     TRY;
 
-    typedef AwtComponent* PComponent;
-    AwtComponent** comps = new PComponent[2];
-    AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self);
-    AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent);
-    comps[0] = comp;
-    comps[1] = parentComp;
-
-    AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps);
-    // comps is deleted in SetParent
+    SetParentStruct * data = new SetParentStruct;
+    data->component = env->NewGlobalRef(self);
+    data->parentComp = env->NewGlobalRef(parent);
+
+    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetParent, data);
+    // global refs and data are deleted in SetParent
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.h	Mon Jun 19 11:29:42 2017 -0700
@@ -668,6 +668,7 @@
     static void _RemoveNativeDropTarget(void *param);
     static jintArray _CreatePrintedPixels(void *param);
     static jboolean _NativeHandlesWheelScrolling(void *param);
+    static void _SetParent(void * param);
     static void _SetRectangularShape(void *param);
     static void _SetZOrder(void *param);
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -111,12 +111,13 @@
         PDATA pData;
         AwtWindow* awtParent = NULL;
         HWND hwndParent = NULL;
+
         target = env->GetObjectField(peer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
 
         if (parent != NULL) {
             JNI_CHECK_PEER_GOTO(parent, done);
-            awtParent = (AwtWindow *)(JNI_GET_PDATA(parent));
+            awtParent = (AwtWindow *)pData;
             hwndParent = awtParent->GetHWnd();
         } else {
             // There is no way to prevent a parentless dialog from showing on
@@ -775,11 +776,9 @@
 {
     TRY;
 
-    PDATA pData;
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtDialog::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -691,7 +691,7 @@
     jobject peerRef = env->NewGlobalRef(peer);
     jobject resultRef = (jobject)AwtToolkit::GetInstance().SyncCall(
         (void*(*)(void*))AwtFileDialog::_GetLocationOnScreen, (void *)peerRef);
-    env->DeleteLocalRef(peerRef);
+    env->DeleteGlobalRef(peerRef);
 
     if (resultRef != NULL)
     {
--- a/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -878,11 +878,16 @@
 
     if (str == NULL) {
         JNU_ThrowNullPointerException(env, "str argument");
-        return NULL;
+        return 0;
     }
-    if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
+    if ((len < 0) || (off < 0) || (len + off < 0) ||
+        (len + off > (env->GetArrayLength(str)))) {
         JNU_ThrowArrayIndexOutOfBoundsException(env, "off/len argument");
-        return NULL;
+        return 0;
+    }
+
+    if (off == env->GetArrayLength(str)) {
+        return 0;
     }
 
     jchar *strp = new jchar[len];
@@ -914,12 +919,18 @@
 
     if (str == NULL) {
         JNU_ThrowNullPointerException(env, "bytes argument");
-        return NULL;
+        return 0;
     }
-    if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
+    if ((len < 0) || (off < 0) || (len + off < 0) ||
+        (len + off > (env->GetArrayLength(str)))) {
         JNU_ThrowArrayIndexOutOfBoundsException(env, "off or len argument");
-        return NULL;
+        return 0;
     }
+
+    if (off == env->GetArrayLength(str)) {
+        return 0;
+    }
+
     char *pStrBody = NULL;
     jint result = 0;
     try {
@@ -927,12 +938,12 @@
                                                          AwtFont::widthsID);
         if (array == NULL) {
             JNU_ThrowNullPointerException(env, "Can't access widths array.");
-            return NULL;
+            return 0;
         }
         pStrBody = (char *)env->GetPrimitiveArrayCritical(str, 0);
         if (pStrBody == NULL) {
             JNU_ThrowNullPointerException(env, "Can't access str bytes.");
-            return NULL;
+            return 0;
         }
         char *pStr = pStrBody + off;
 
@@ -942,7 +953,7 @@
             if (widths == NULL) {
                 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
                 JNU_ThrowNullPointerException(env, "Can't access widths.");
-                return NULL;
+                return 0;
             }
             for (; len; len--) {
                 result += widths[*pStr++];
--- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -1580,12 +1580,12 @@
 
     PDATA pData;
 
-    pData = JNI_GET_PDATA(peer);
+    JNI_CHECK_PEER_GOTO(peer, ret);
     AwtFrame *f = (AwtFrame *)pData;
 
     // dialog here may be NULL, for example, if the blocker is a native dialog
     // however, we need to install/unistall modal hooks anyway
-    pData = JNI_GET_PDATA(blockerPeer);
+    JNI_CHECK_PEER_GOTO(blockerPeer, ret);
     AwtDialog *d = (AwtDialog *)pData;
 
     if ((f != NULL) && ::IsWindow(f->GetHWnd()))
@@ -1637,7 +1637,7 @@
             }
         }
     }
-
+ret:
     env->DeleteGlobalRef(self);
     env->DeleteGlobalRef(peer);
     env->DeleteGlobalRef(blockerPeer);
@@ -1809,8 +1809,6 @@
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtFrame::Create);
-    PDATA pData;
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
@@ -1924,8 +1922,6 @@
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtFrame::Create);
-    PDATA pData;
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -80,7 +80,7 @@
 
         JNI_CHECK_PEER_GOTO(parent, done);
         awtParent = (AwtCanvas*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "awtParent", done);
+
         target  = env->GetObjectField(labelPeer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "target", done);
 
@@ -392,12 +392,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtLabel::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -89,10 +89,9 @@
 
         PDATA pData;
         AwtCanvas* awtParent;
+
         JNI_CHECK_PEER_GOTO(parent, done);
-
         awtParent = (AwtCanvas*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
 
         /* target is Hjava_awt_List * */
         target = env->GetObjectField(peer, AwtObject::targetID);
@@ -928,9 +927,6 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(self);
-
     SelectElementStruct *ses = new SelectElementStruct;
     ses->list = env->NewGlobalRef(self);
     ses->index = pos;
@@ -994,11 +990,8 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)AwtList::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -217,6 +217,10 @@
         if (env->EnsureLocalCapacity(1) < 0) {
             return NULL;
         }
+        if (!AwtToolkit::GetInstance().isFreeIDAvailable()) {
+            return NULL;
+        }
+
         JNI_CHECK_NULL_RETURN_NULL(menuPeer, "peer");
 
         /* target is a java.awt.MenuItem  */
--- a/src/java.desktop/windows/native/libawt/windows/awt_Palette.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Palette.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -148,7 +148,7 @@
         pEntry->peFlags = PC_EXPLICIT;
     }
     hPal = ::CreatePalette(pLogPal);
-    delete pLogPal;
+    delete[] pLogPal;
     if ( hPal == 0 ) {
         return 0;
     }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -285,7 +285,7 @@
 
     // copy pixels into Java array
     env->SetIntArrayRegion(pixelArray, 0, numPixels, (jint *)pixelData);
-    delete pinfo;
+    delete[] pinfo;
 
     // free all the GDI objects we made
     ::SelectObject(hdcMem, hOldBitmap);
--- a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -96,10 +96,9 @@
 
         PDATA pData;
         AwtComponent* awtParent;
+
         JNI_CHECK_PEER_GOTO(parent, done);
-
         awtParent = (AwtComponent*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
 
         target = env->GetObjectField(self, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
@@ -679,11 +678,10 @@
 
     DTRACE_PRINTLN2("%x: WScrollPanePeer.create(%x)", self, parent);
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtScrollPane::Create);
+    PDATA pData;
     JNI_CHECK_PEER_CREATION_RETURN(self);
     ((AwtScrollPane*)pData)->VerifyState();
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -38,7 +38,11 @@
     jint value;
     jint visible;
     jint min, max;
-
+};
+// struct for _SetLineIncrement()/_SetPageIncrement() methods
+struct SetIncrementStruct {
+    jobject scrollbar;
+    jint increment;
 };
 /************************************************************************
  * AwtScrollbar fields
@@ -108,10 +112,9 @@
 
         PDATA pData;
         AwtCanvas* awtParent;
+
         JNI_CHECK_PEER_GOTO(parent, done);
-
         awtParent = (AwtCanvas*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
 
         target = env->GetObjectField(peer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
@@ -471,6 +474,52 @@
     delete svs;
 }
 
+void AwtScrollbar::_SetLineIncrement(void *param)
+{
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+    SetIncrementStruct *sis = (SetIncrementStruct *)param;
+    jobject self = sis->scrollbar;
+    jint increment = sis->increment;
+
+    AwtScrollbar *sb = NULL;
+
+    PDATA pData;
+    JNI_CHECK_PEER_GOTO(self, ret);
+    sb = (AwtScrollbar *)pData;
+    if (::IsWindow(sb->GetHWnd()))
+    {
+        sb->SetLineIncrement(increment);
+    }
+ret:
+    env->DeleteGlobalRef(self);
+
+    delete sis;
+}
+
+void AwtScrollbar::_SetPageIncrement(void *param)
+{
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+    SetIncrementStruct *sis = (SetIncrementStruct *)param;
+    jobject self = sis->scrollbar;
+    jint increment = sis->increment;
+
+    AwtScrollbar *sb = NULL;
+
+    PDATA pData;
+    JNI_CHECK_PEER_GOTO(self, ret);
+    sb = (AwtScrollbar *)pData;
+    if (::IsWindow(sb->GetHWnd()))
+    {
+        sb->SetPageIncrement(increment);
+    }
+ret:
+    env->DeleteGlobalRef(self);
+
+    delete sis;
+}
+
 /************************************************************************
  * Scrollbar native methods
  */
@@ -546,10 +595,12 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(self);
-    AwtScrollbar* c = (AwtScrollbar*)pData;
-    c->SetLineIncrement(increment);
+    SetIncrementStruct *sis = new SetIncrementStruct;
+    sis->scrollbar = env->NewGlobalRef(self);
+    sis->increment = increment;
+
+    AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetLineIncrement, sis);
+    // global ref and svs are deleted in _SetValues
 
     CATCH_BAD_ALLOC;
 }
@@ -565,10 +616,12 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(self);
-    AwtScrollbar* c = (AwtScrollbar*)pData;
-    c->SetPageIncrement(increment);
+    SetIncrementStruct *sis = new SetIncrementStruct;
+    sis->scrollbar = env->NewGlobalRef(self);
+    sis->increment = increment;
+
+    AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetPageIncrement, sis);
+    // global ref and svs are deleted in _SetValues
 
     CATCH_BAD_ALLOC;
 }
@@ -584,12 +637,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtScrollbar::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h	Mon Jun 19 11:29:42 2017 -0700
@@ -77,6 +77,8 @@
 
     INLINE virtual BOOL IsScrollbar() { return TRUE; }
 
+    static void _SetLineIncrement(void *param);
+    static void _SetPageIncrement(void *param);
     // invoked on Toolkit thread
     static void _SetValues(void *param);
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -505,12 +505,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtTextArea::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -95,10 +95,9 @@
 
         PDATA pData;
         AwtCanvas* awtParent;
+
         JNI_CHECK_PEER_GOTO(parent, done);
-
         awtParent = (AwtCanvas*)pData;
-        JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
 
         target = env->GetObjectField(peer, AwtObject::targetID);
         JNI_CHECK_NULL_GOTO(target, "null target", done);
--- a/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -260,12 +260,9 @@
 {
     TRY;
 
-    PDATA pData;
-    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtTextField::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -1663,6 +1663,11 @@
     }
 }
 
+jboolean AwtToolkit::isFreeIDAvailable()
+{
+    return m_cmdIDs->isFreeIDAvailable();
+}
+
 UINT AwtToolkit::CreateCmdID(AwtObject* object)
 {
     return m_cmdIDs->Add(object);
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -320,6 +320,8 @@
     BOOL PreProcessMouseMsg(class AwtComponent* p, MSG& msg);
     BOOL PreProcessKeyMsg(class AwtComponent* p, MSG& msg);
 
+    /* Checks that an free ID exists. */
+    jboolean isFreeIDAvailable();
     /* Create an ID which maps to an AwtObject pointer, such as a menu. */
     UINT CreateCmdID(AwtObject* object);
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -3400,12 +3400,9 @@
 {
     TRY;
 
-    PDATA pData;
-//    JNI_CHECK_PEER_RETURN(parent);
     AwtToolkit::CreateComponent(self, parent,
                                 (AwtToolkit::ComponentFactory)
                                 AwtWindow::Create);
-    JNI_CHECK_PEER_CREATION_RETURN(self);
 
     CATCH_BAD_ALLOC;
 }
--- a/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -25,6 +25,7 @@
 
 package com.sun.jmx.remote.internal.rmi;
 
+import java.io.ObjectInputFilter;
 import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
@@ -51,7 +52,8 @@
     public Remote exportObject(Remote obj,
                                int port,
                                RMIClientSocketFactory csf,
-                               RMIServerSocketFactory ssf)
+                               RMIServerSocketFactory ssf,
+                               ObjectInputFilter filter)
             throws RemoteException;
 
     public boolean unexportObject(Remote obj, boolean force)
--- a/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Mon Jun 19 11:29:42 2017 -0700
@@ -32,6 +32,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.ObjectInputFilter;
 import java.io.ObjectOutputStream;
 import java.net.MalformedURLException;
 import java.rmi.server.RMIClientSocketFactory;
@@ -101,19 +102,59 @@
         "jmx.remote.rmi.server.socket.factory";
 
     /**
-    * Name of the attribute that specifies a list of class names acceptable
-    * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
+    * Name of the attribute that specifies an
+    * {@link ObjectInputFilter} pattern string to filter classes acceptable
+    * for {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
     * remote method call.
     * <p>
-    * This list of classes should correspond to the transitive closure of the
-    * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
-    * associated with the {@linkplain RMIServer} implementation.
+    * The filter pattern must be in same format as used in
+    * {@link java.io.ObjectInputFilter.Config#createFilter}
     * <p>
-    * If the attribute is not set, or is null, then any class is
-    * deemed acceptable.
+    * This list of classes allowed by filter should correspond to the
+    * transitive closure of the credentials class (or classes) used by the
+    * installed {@linkplain JMXAuthenticator} associated with the
+    * {@linkplain RMIServer} implementation.
+    * If the attribute is not set then any class is deemed acceptable.
+    * @see ObjectInputFilter
     */
-    public static final String CREDENTIAL_TYPES =
-            "jmx.remote.rmi.server.credential.types";
+    public static final String CREDENTIALS_FILTER_PATTERN =
+        "jmx.remote.rmi.server.credentials.filter.pattern";
+
+    /**
+     * This attribute defines a pattern from which to create a
+     * {@link java.io.ObjectInputFilter} that will be used when deserializing
+     * objects sent to the {@code JMXConnectorServer} by any client.
+     * <p>
+     * The filter will be called for any class found in the serialized
+     * stream sent to server by client, including all JMX defined classes
+     * (such as {@link javax.management.ObjectName}), all method parameters,
+     * and, if present in the stream, all classes transitively referred by
+     * the serial form of any deserialized object.
+     * The pattern must be in same format as used in
+     * {@link java.io.ObjectInputFilter.Config#createFilter}.
+     * It may define a white list of permitted classes, a black list of
+     * rejected classes, a maximum depth for the deserialized objects,
+     * etc.
+     * <p>
+     * To be functional, the filter should allow at least all the
+     * concrete types in the transitive closure of all objects that
+     * might get serialized when serializing all JMX classes referred
+     * as parameters in the {@link
+     * javax.management.remote.rmi.RMIConnection} interface,
+     * plus all classes that a {@link javax.management.remote.rmi.RMIConnector client}
+     * might need to transmit wrapped in {@linkplain java.rmi.MarshalledObject
+     * marshalled objects} in order to interoperate with the MBeans registered
+     * in the {@code MBeanServer}. That would potentially include all the
+     * concrete {@linkplain javax.management.openmbean  JMX OpenTypes} and the
+     * classes they use in their serial form.
+     * <p>
+     * Care must be taken when defining such a filter, as defining
+     * a white list too restrictive or a too wide a black list may
+     * prevent legitimate clients from interoperating with the
+     * {@code JMXConnectorServer}.
+     */
+    public static final String SERIAL_FILTER_PATTERN =
+       "jmx.remote.rmi.server.serial.filter.pattern";
 
     /**
      * <p>Makes an <code>RMIConnectorServer</code>.
--- a/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -26,6 +26,7 @@
 package javax.management.remote.rmi;
 
 import java.io.IOException;
+import java.io.ObjectInputFilter;
 import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
@@ -39,15 +40,13 @@
 
 import com.sun.jmx.remote.internal.rmi.RMIExporter;
 import com.sun.jmx.remote.util.EnvHelp;
-import java.io.ObjectStreamClass;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 import sun.reflect.misc.ReflectUtil;
-import sun.rmi.server.DeserializationChecker;
 import sun.rmi.server.UnicastServerRef;
 import sun.rmi.server.UnicastServerRef2;
+import sun.rmi.transport.LiveRef;
 
 /**
  * <p>An {@link RMIServer} object that is exported through JRMP and that
@@ -60,8 +59,6 @@
  */
 public class RMIJRMPServerImpl extends RMIServerImpl {
 
-    private final ExportedWrapper exportedWrapper;
-
     /**
      * <p>Creates a new {@link RMIServer} object that will be exported
      * on the given port using the given socket factories.</p>
@@ -100,33 +97,48 @@
         this.ssf = ssf;
         this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
 
+        // This attribute was represented by RMIConnectorServer.CREDENTIALS_TYPES.
+        // This attribute is superceded by
+        // RMIConnectorServer.CREDENTIALS_FILTER_PATTERN.
+        // Retaining this for backward compatibility.
         String[] credentialsTypes
-                = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
-        List<String> types = null;
-        if (credentialsTypes != null) {
-            types = new ArrayList<>();
-            for (String type : credentialsTypes) {
-                if (type == null) {
-                    throw new IllegalArgumentException("A credential type is null.");
-                }
-                ReflectUtil.checkPackageAccess(type);
-                types.add(type);
-            }
+                = (String[]) this.env.get("jmx.remote.rmi.server.credential.types");
+
+        String credentialsFilter
+                = (String) this.env.get(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN);
+
+        // It is impossible for both attributes to be specified
+        if(credentialsTypes != null && credentialsFilter != null)
+            throw new IllegalArgumentException("Cannot specify both \""
+                    + "jmx.remote.rmi.server.credential.types" + "\" and \""
+           + RMIConnectorServer.CREDENTIALS_FILTER_PATTERN + "\"");
+        else if(credentialsFilter != null){
+            cFilter = ObjectInputFilter.Config.createFilter(credentialsFilter);
+            allowedTypes = null;
         }
-        exportedWrapper = types != null ?
-                new ExportedWrapper(this, types) :
-                null;
+        else if (credentialsTypes != null) {
+            allowedTypes = Arrays.stream(credentialsTypes).filter(
+                    s -> s!= null).collect(Collectors.toSet());
+            allowedTypes.stream().forEach(ReflectUtil::checkPackageAccess);
+            cFilter = this::newClientCheckInput;
+        } else {
+            allowedTypes = null;
+            cFilter = null;
+        }
+
+        String userJmxFilter =
+                (String) this.env.get(RMIConnectorServer.SERIAL_FILTER_PATTERN);
+        if(userJmxFilter != null && !userJmxFilter.isEmpty())
+            jmxRmiFilter = ObjectInputFilter.Config.createFilter(userJmxFilter);
+        else
+            jmxRmiFilter = null;
     }
 
     protected void export() throws IOException {
-        if (exportedWrapper != null) {
-            export(exportedWrapper);
-        } else {
-            export(this);
-        }
+        export(this, cFilter);
     }
 
-    private void export(Remote obj) throws RemoteException {
+    private void export(Remote obj, ObjectInputFilter typeFilter) throws RemoteException {
         final RMIExporter exporter =
             (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
         final boolean daemon = EnvHelp.isServerDaemon(env);
@@ -137,16 +149,14 @@
                     " cannot be used to specify an exporter!");
         }
 
-        if (daemon) {
+        if (exporter != null) {
+            exporter.exportObject(obj, port, csf, ssf, typeFilter);
+        } else {
             if (csf == null && ssf == null) {
-                new UnicastServerRef(port).exportObject(obj, null, true);
+                new UnicastServerRef(new LiveRef(port), typeFilter).exportObject(obj, null, daemon);
             } else {
-                new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
+                new UnicastServerRef2(port, csf, ssf, typeFilter).exportObject(obj, null, daemon);
             }
-        } else if (exporter != null) {
-            exporter.exportObject(obj, port, csf, ssf);
-        } else {
-            UnicastRemoteObject.exportObject(obj, port, csf, ssf);
         }
     }
 
@@ -173,11 +183,7 @@
      *            RMIJRMPServerImpl has not been exported yet.
      */
     public Remote toStub() throws IOException {
-        if (exportedWrapper != null) {
-            return RemoteObject.toStub(exportedWrapper);
-        } else {
-            return RemoteObject.toStub(this);
-        }
+        return RemoteObject.toStub(this);
     }
 
     /**
@@ -207,7 +213,7 @@
         RMIConnection client =
             new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
                                   subject, env);
-        export(client);
+        export(client, jmxRmiFilter);
         return client;
     }
 
@@ -224,56 +230,39 @@
      * server failed.
      */
     protected void closeServer() throws IOException {
-        if (exportedWrapper != null) {
-            unexport(exportedWrapper, true);
-        } else {
-            unexport(this, true);
+        unexport(this, true);
+    }
+
+    /**
+     * Check that a type in the remote invocation of {@link RMIServerImpl#newClient}
+     * is one of the {@code allowedTypes}.
+     *
+     * @param clazz       the class; may be null
+     * @param size        the size for arrays, otherwise is 0
+     * @param nObjectRefs the current number of object references
+     * @param depth       the current depth
+     * @param streamBytes the current number of bytes consumed
+     * @return {@code ObjectInputFilter.Status.ALLOWED} if the class is allowed,
+     *          otherwise {@code ObjectInputFilter.Status.REJECTED}
+     */
+    ObjectInputFilter.Status newClientCheckInput(ObjectInputFilter.FilterInfo filterInfo) {
+        ObjectInputFilter.Status status = ObjectInputFilter.Status.UNDECIDED;
+        if (allowedTypes != null && filterInfo.serialClass() != null) {
+            // If enabled, check type
+            String type = filterInfo.serialClass().getName();
+            if (allowedTypes.contains(type))
+                status = ObjectInputFilter.Status.ALLOWED;
+            else
+                status = ObjectInputFilter.Status.REJECTED;
         }
+        return status;
     }
 
     private final int port;
     private final RMIClientSocketFactory csf;
     private final RMIServerSocketFactory ssf;
     private final Map<String, ?> env;
-
-    private static class ExportedWrapper implements RMIServer, DeserializationChecker {
-        private final RMIServer impl;
-        private final List<String> allowedTypes;
-
-        private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
-            this.impl = impl;
-            allowedTypes = credentialsTypes;
-        }
-
-        @Override
-        public String getVersion() throws RemoteException {
-            return impl.getVersion();
-        }
-
-        @Override
-        public RMIConnection newClient(Object credentials) throws IOException {
-            return impl.newClient(credentials);
-        }
-
-        @Override
-        public void check(Method method, ObjectStreamClass descriptor,
-                int paramIndex, int callID) {
-            String type = descriptor.getName();
-            if (!allowedTypes.contains(type)) {
-                throw new ClassCastException("Unsupported type: " + type);
-            }
-        }
-
-        @Override
-        public void checkProxyClass(Method method, String[] ifaces,
-                int paramIndex, int callID) {
-            if (ifaces != null && ifaces.length > 0) {
-                for (String iface : ifaces) {
-                    if (!allowedTypes.contains(iface)) {
-                        throw new ClassCastException("Unsupported type: " + iface);
-                    }
-                }
-            }
-        }
-    }
+    private final Set<String> allowedTypes;
+    private final ObjectInputFilter jmxRmiFilter;
+    private final ObjectInputFilter cFilter;
 }
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1234,6 +1234,7 @@
     static final int LDAP_REF_FOLLOW = 0x01;            // follow referrals
     static final int LDAP_REF_THROW = 0x02;             // throw referral ex.
     static final int LDAP_REF_IGNORE = 0x03;            // ignore referrals
+    static final int LDAP_REF_FOLLOW_SCHEME = 0x04;     // follow referrals of the same scheme
 
     static final String LDAP_URL = "ldap://";           // LDAPv3
     static final String LDAPS_URL = "ldaps://";         // LDAPv3
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Mon Jun 19 11:29:42 2017 -0700
@@ -2414,6 +2414,9 @@
         // First determine the referral mode
         if (ref != null) {
             switch (ref) {
+                case "follow-scheme":
+                    handleReferrals = LdapClient.LDAP_REF_FOLLOW_SCHEME;
+                    break;
                 case "follow":
                     handleReferrals = LdapClient.LDAP_REF_FOLLOW;
                     break;
@@ -2979,8 +2982,23 @@
             r = new LdapReferralException(resolvedName, resolvedObj, remainName,
                 msg, envprops, fullDN, handleReferrals, reqCtls);
             // only one set of URLs is present
-            r.setReferralInfo(res.referrals == null ? null :
-                    res.referrals.elementAt(0), false);
+            Vector<String> refs;
+            if (res.referrals == null) {
+                refs = null;
+            } else if (handleReferrals == LdapClient.LDAP_REF_FOLLOW_SCHEME) {
+                refs = new Vector<>();
+                for (String s : res.referrals.elementAt(0)) {
+                    if (s.startsWith("ldap:")) {
+                        refs.add(s);
+                    }
+                }
+                if (refs.isEmpty()) {
+                    refs = null;
+                }
+            } else {
+                refs = res.referrals.elementAt(0);
+            }
+            r.setReferralInfo(refs, false);
 
             if (hopCount > 1) {
                 r.setHopCount(hopCount);
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralException.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralException.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -117,7 +117,8 @@
 
         // If following referral, request controls are passed to referral ctx
         this.reqCtls =
-            (handleReferrals == LdapClient.LDAP_REF_FOLLOW ? reqCtls : null);
+            (handleReferrals == LdapClient.LDAP_REF_FOLLOW ||
+                    handleReferrals == LdapClient.LDAP_REF_FOLLOW_SCHEME ? reqCtls : null);
     }
 
     /**
--- a/src/java.naming/share/classes/javax/naming/directory/BasicAttribute.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.naming/share/classes/javax/naming/directory/BasicAttribute.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -515,7 +515,7 @@
             throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();  // read in the attrID
         int n = s.readInt();    // number of values
-        values = new Vector<>(n);
+        values = new Vector<>(Math.min(1024, n));
         while (--n >= 0) {
             values.addElement(s.readObject());
         }
--- a/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -186,7 +186,7 @@
              */
             Hashtable<?,?> currentEnv = ctx.getEnvironment();
             if (currentEnv.get(Context.REFERRAL) == null) {
-                ctx.addToEnvironment(Context.REFERRAL, "follow");
+                ctx.addToEnvironment(Context.REFERRAL, "follow-scheme");
             }
         } catch (NamingException e) {
             if (debug != null) {
--- a/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,6 +40,12 @@
 import java.rmi.server.RemoteObjectInvocationHandler;
 import java.rmi.server.RemoteRef;
 import java.rmi.server.UID;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
 
 /**
  * Activation makes use of special identifiers to denote remote
@@ -81,6 +87,14 @@
     /** indicate compatibility with the Java 2 SDK v1.2 version of class */
     private static final long serialVersionUID = -4608673054848209235L;
 
+    /** an AccessControlContext with no permissions */
+    private static final AccessControlContext NOPERMS_ACC;
+    static {
+        Permissions perms = new Permissions();
+        ProtectionDomain[] pd = { new ProtectionDomain(null, perms) };
+        NOPERMS_ACC = new AccessControlContext(pd);
+    }
+
     /**
      * The constructor for <code>ActivationID</code> takes a single
      * argument, activator, that specifies a remote reference to the
@@ -116,13 +130,19 @@
         try {
             MarshalledObject<? extends Remote> mobj =
                 activator.activate(this, force);
-            return mobj.get();
-        } catch (RemoteException e) {
-            throw e;
-        } catch (IOException e) {
-            throw new UnmarshalException("activation failed", e);
-        } catch (ClassNotFoundException e) {
-            throw new UnmarshalException("activation failed", e);
+            return AccessController.doPrivileged(
+                new PrivilegedExceptionAction<Remote>() {
+                    public Remote run() throws IOException, ClassNotFoundException {
+                        return mobj.get();
+                    }
+                }, NOPERMS_ACC);
+        } catch (PrivilegedActionException pae) {
+            Exception ex = pae.getException();
+            if (ex instanceof RemoteException) {
+                throw (RemoteException) ex;
+            } else {
+                throw new UnmarshalException("activation failed", ex);
+            }
         }
 
     }
--- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -75,6 +75,10 @@
  * registry.
  *
  * The LocateRegistry class is used to obtain registry for different hosts.
+ * <p>
+ * The default RegistryImpl exported restricts access to clients on the local host
+ * for the methods {@link #bind}, {@link #rebind}, {@link #unbind} by checking
+ * the client host in the skeleton.
  *
  * @see java.rmi.registry.LocateRegistry
  */
@@ -144,13 +148,27 @@
                         RMIServerSocketFactory ssf)
         throws RemoteException
     {
+        this(port, csf, ssf, RegistryImpl::registryFilter);
+    }
+
+
+    /**
+     * Construct a new RegistryImpl on the specified port with the
+     * given custom socket factory pair and ObjectInputFilter.
+     */
+    public RegistryImpl(int port,
+                        RMIClientSocketFactory csf,
+                        RMIServerSocketFactory ssf,
+                        ObjectInputFilter serialFilter)
+        throws RemoteException
+    {
         if (port == Registry.REGISTRY_PORT && System.getSecurityManager() != null) {
             // grant permission for default port only.
             try {
                 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                     public Void run() throws RemoteException {
                         LiveRef lref = new LiveRef(id, port, csf, ssf);
-                        setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
+                        setup(new UnicastServerRef2(lref, serialFilter));
                         return null;
                     }
                 }, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -226,7 +244,8 @@
     public void bind(String name, Remote obj)
         throws RemoteException, AlreadyBoundException, AccessException
     {
-        checkAccess("Registry.bind");
+        // The access check preventing remote access is done in the skeleton
+        // and is not applicable to local access.
         synchronized (bindings) {
             Remote curr = bindings.get(name);
             if (curr != null)
@@ -243,7 +262,8 @@
     public void unbind(String name)
         throws RemoteException, NotBoundException, AccessException
     {
-        checkAccess("Registry.unbind");
+        // The access check preventing remote access is done in the skeleton
+        // and is not applicable to local access.
         synchronized (bindings) {
             Remote obj = bindings.get(name);
             if (obj == null)
@@ -259,7 +279,8 @@
     public void rebind(String name, Remote obj)
         throws RemoteException, AccessException
     {
-        checkAccess("Registry.rebind");
+        // The access check preventing remote access is done in the skeleton
+        // and is not applicable to local access.
         bindings.put(name, obj);
     }
 
@@ -312,7 +333,7 @@
 
                 if (clientHost.isAnyLocalAddress()) {
                     throw new AccessException(
-                        "Registry." + op + " disallowed; origin unknown");
+                        op + " disallowed; origin unknown");
                 }
 
                 try {
@@ -335,7 +356,7 @@
                     // must have been an IOException
 
                     throw new AccessException(
-                        "Registry." + op + " disallowed; origin " +
+                        op + " disallowed; origin " +
                         clientHost + " is non-local host");
                 }
             }
@@ -344,8 +365,7 @@
              * Local call from this VM: allow access.
              */
         } catch (java.net.UnknownHostException ex) {
-            throw new AccessException("Registry." + op +
-                                      " disallowed; origin is unknown host");
+            throw new AccessException(op + " disallowed; origin is unknown host");
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, 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.rmi.registry;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.AccessException;
+import java.rmi.server.RemoteCall;
+
+import sun.rmi.transport.Connection;
+import sun.rmi.transport.StreamRemoteCall;
+import sun.rmi.transport.tcp.TCPConnection;
+
+/**
+ * Skeleton to dispatch RegistryImpl methods.
+ * Originally generated by RMIC but frozen to match the stubs.
+ */
+@SuppressWarnings({"deprecation", "serial"})
+public final class RegistryImpl_Skel
+        implements java.rmi.server.Skeleton {
+    private static final java.rmi.server.Operation[] operations = {
+            new java.rmi.server.Operation("void bind(java.lang.String, java.rmi.Remote)"),
+            new java.rmi.server.Operation("java.lang.String list()[]"),
+            new java.rmi.server.Operation("java.rmi.Remote lookup(java.lang.String)"),
+            new java.rmi.server.Operation("void rebind(java.lang.String, java.rmi.Remote)"),
+            new java.rmi.server.Operation("void unbind(java.lang.String)")
+    };
+
+    private static final long interfaceHash = 4905912898345647071L;
+
+    public java.rmi.server.Operation[] getOperations() {
+        return operations.clone();
+    }
+
+    public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
+            throws java.lang.Exception {
+        if (hash != interfaceHash)
+            throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+
+        sun.rmi.registry.RegistryImpl server = (sun.rmi.registry.RegistryImpl) obj;
+        switch (opnum) {
+            case 0: // bind(String, Remote)
+            {
+                // Check access before reading the arguments
+                RegistryImpl.checkAccess("Registry.bind");
+
+                java.lang.String $param_String_1;
+                java.rmi.Remote $param_Remote_2;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_String_1 = (java.lang.String) in.readObject();
+                    $param_Remote_2 = (java.rmi.Remote) in.readObject();
+                } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                server.bind($param_String_1, $param_Remote_2);
+                try {
+                    call.getResultStream(true);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            case 1: // list()
+            {
+                call.releaseInputStream();
+                java.lang.String[] $result = server.list();
+                try {
+                    java.io.ObjectOutput out = call.getResultStream(true);
+                    out.writeObject($result);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            case 2: // lookup(String)
+            {
+                java.lang.String $param_String_1;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_String_1 = (java.lang.String) in.readObject();
+                } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                java.rmi.Remote $result = server.lookup($param_String_1);
+                try {
+                    java.io.ObjectOutput out = call.getResultStream(true);
+                    out.writeObject($result);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            case 3: // rebind(String, Remote)
+            {
+                // Check access before reading the arguments
+                RegistryImpl.checkAccess("Registry.rebind");
+
+                java.lang.String $param_String_1;
+                java.rmi.Remote $param_Remote_2;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_String_1 = (java.lang.String) in.readObject();
+                    $param_Remote_2 = (java.rmi.Remote) in.readObject();
+                } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                server.rebind($param_String_1, $param_Remote_2);
+                try {
+                    call.getResultStream(true);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            case 4: // unbind(String)
+            {
+                // Check access before reading the arguments
+                RegistryImpl.checkAccess("Registry.unbind");
+
+                java.lang.String $param_String_1;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_String_1 = (java.lang.String) in.readObject();
+                } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                server.unbind($param_String_1);
+                try {
+                    call.getResultStream(true);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            default:
+                throw new java.rmi.UnmarshalException("invalid method number");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Stub.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017, 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.rmi.registry;
+/**
+ * Stubs to invoke RegistryImpl remote methods.
+ * Originally generated from RMIC but frozen to match RegistryImpl_Skel.
+ */
+@SuppressWarnings({"deprecation", "serial"})
+public final class RegistryImpl_Stub
+        extends java.rmi.server.RemoteStub
+        implements java.rmi.registry.Registry, java.rmi.Remote {
+    private static final java.rmi.server.Operation[] operations = {
+            new java.rmi.server.Operation("void bind(java.lang.String, java.rmi.Remote)"),
+            new java.rmi.server.Operation("java.lang.String list()[]"),
+            new java.rmi.server.Operation("java.rmi.Remote lookup(java.lang.String)"),
+            new java.rmi.server.Operation("void rebind(java.lang.String, java.rmi.Remote)"),
+            new java.rmi.server.Operation("void unbind(java.lang.String)")
+    };
+
+    private static final long interfaceHash = 4905912898345647071L;
+
+    // constructors
+    public RegistryImpl_Stub() {
+        super();
+    }
+
+    public RegistryImpl_Stub(java.rmi.server.RemoteRef ref) {
+        super(ref);
+    }
+
+    // methods from remote interfaces
+
+    // implementation of bind(String, Remote)
+    public void bind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2)
+            throws java.rmi.AccessException, java.rmi.AlreadyBoundException, java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_String_1);
+                out.writeObject($param_Remote_2);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            ref.done(call);
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.rmi.AlreadyBoundException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    // implementation of list()
+    public java.lang.String[] list()
+            throws java.rmi.AccessException, java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash);
+            ref.invoke(call);
+            java.lang.String[] $result;
+            try {
+                java.io.ObjectInput in = call.getInputStream();
+                $result = (java.lang.String[]) in.readObject();
+            } catch (java.io.IOException e) {
+                throw new java.rmi.UnmarshalException("error unmarshalling return", e);
+            } catch (java.lang.ClassNotFoundException e) {
+                throw new java.rmi.UnmarshalException("error unmarshalling return", e);
+            } finally {
+                ref.done(call);
+            }
+            return $result;
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    // implementation of lookup(String)
+    public java.rmi.Remote lookup(java.lang.String $param_String_1)
+            throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 2, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_String_1);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            java.rmi.Remote $result;
+            try {
+                java.io.ObjectInput in = call.getInputStream();
+                $result = (java.rmi.Remote) in.readObject();
+            } catch (java.io.IOException e) {
+                throw new java.rmi.UnmarshalException("error unmarshalling return", e);
+            } catch (java.lang.ClassNotFoundException e) {
+                throw new java.rmi.UnmarshalException("error unmarshalling return", e);
+            } finally {
+                ref.done(call);
+            }
+            return $result;
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.rmi.NotBoundException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    // implementation of rebind(String, Remote)
+    public void rebind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2)
+            throws java.rmi.AccessException, java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 3, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_String_1);
+                out.writeObject($param_Remote_2);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            ref.done(call);
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    // implementation of unbind(String)
+    public void unbind(java.lang.String $param_String_1)
+            throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 4, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_String_1);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            ref.done(call);
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.rmi.NotBoundException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+}
--- a/src/java.rmi/share/classes/sun/rmi/server/Activation.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/Activation.java	Mon Jun 19 11:29:42 2017 -0700
@@ -30,6 +30,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.ObjectInput;
 import java.io.ObjectInputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
@@ -105,7 +106,6 @@
 import sun.rmi.log.ReliableLog;
 import sun.rmi.registry.RegistryImpl;
 import sun.rmi.runtime.NewThreadAction;
-import sun.rmi.server.UnicastServerRef;
 import sun.rmi.transport.LiveRef;
 import sun.security.provider.PolicyFile;
 import com.sun.rmi.rmid.ExecPermission;
@@ -375,6 +375,7 @@
                 throw new AccessException(
                     "binding ActivationSystem is disallowed");
             } else {
+                RegistryImpl.checkAccess("ActivationSystem.bind");
                 super.bind(name, obj);
             }
         }
@@ -386,6 +387,7 @@
                 throw new AccessException(
                     "unbinding ActivationSystem is disallowed");
             } else {
+                RegistryImpl.checkAccess("ActivationSystem.unbind");
                 super.unbind(name);
             }
         }
@@ -398,6 +400,7 @@
                 throw new AccessException(
                     "binding ActivationSystem is disallowed");
             } else {
+                RegistryImpl.checkAccess("ActivationSystem.rebind");
                 super.rebind(name, obj);
             }
         }
@@ -488,6 +491,33 @@
     }
 
 
+    /**
+     * SameHostOnlyServerRef checks that access is from a local client
+     * before the parameters are deserialized.  The unmarshalCustomCallData
+     * hook is used to check the network address of the caller
+     * with RegistryImpl.checkAccess().
+     * The kind of access is retained for an exception if one is thrown.
+     */
+    static class SameHostOnlyServerRef extends UnicastServerRef {
+        private static final long serialVersionUID = 1234L;
+        private String accessKind;      // an exception message
+
+        /**
+         * Construct a new SameHostOnlyServerRef from a LiveRef.
+         * @param lref a LiveRef
+         */
+        SameHostOnlyServerRef(LiveRef lref, String accessKind) {
+            super(lref);
+            this.accessKind = accessKind;
+        }
+
+        @Override
+        protected void unmarshalCustomCallData(ObjectInput in) throws IOException, ClassNotFoundException {
+            RegistryImpl.checkAccess(accessKind);
+            super.unmarshalCustomCallData(in);
+        }
+    }
+
     class ActivationSystemImpl
         extends RemoteServer
         implements ActivationSystem
@@ -505,7 +535,8 @@
              * 'this' can be exported.
              */
             LiveRef lref = new LiveRef(new ObjID(4), port, null, ssf);
-            UnicastServerRef uref = new UnicastServerRef(lref);
+            UnicastServerRef uref = new SameHostOnlyServerRef(lref,
+                    "ActivationSystem.nonLocalAccess");
             ref = uref;
             uref.exportObject(this, null);
         }
@@ -514,8 +545,8 @@
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.registerObject");
-
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
             ActivationGroupID groupID = desc.getGroupID();
             ActivationID id = new ActivationID(activatorStub);
             getGroupEntry(groupID).registerObject(id, desc, true);
@@ -526,7 +557,8 @@
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.unregisterObject");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
             getGroupEntry(id).unregisterObject(id, true);
         }
 
@@ -534,7 +566,8 @@
             throws ActivationException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.registerGroup");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
             checkArgs(desc, null);
 
             ActivationGroupID id = new ActivationGroupID(systemStub);
@@ -551,7 +584,8 @@
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.activeGroup");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             getGroupEntry(id).activeGroup(group, incarnation);
             return monitor;
@@ -561,7 +595,8 @@
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.unregisterGroup");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             // remove entry before unregister so state is updated before
             // logged
@@ -573,7 +608,8 @@
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.setActivationDesc");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             if (!getGroupID(id).equals(desc.getGroupID())) {
                 throw new ActivationException(
@@ -587,8 +623,8 @@
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess(
-                "ActivationSystem.setActivationGroupDesc");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             checkArgs(desc, null);
             return getGroupEntry(id).setActivationGroupDesc(id, desc, true);
@@ -598,7 +634,8 @@
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.getActivationDesc");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             return getGroupEntry(id).getActivationDesc(id);
         }
@@ -607,8 +644,8 @@
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess
-                ("ActivationSystem.getActivationGroupDesc");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             return getGroupEntry(id).desc;
         }
@@ -618,7 +655,8 @@
          * the activation daemon and exits the activation daemon.
          */
         public void shutdown() throws AccessException {
-            RegistryImpl.checkAccess("ActivationSystem.shutdown");
+            // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef
+            // during unmarshallCustomData and is not applicable to local access.
 
             Object lock = startupLock;
             if (lock != null) {
--- a/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Mon Jun 19 11:29:42 2017 -0700
@@ -35,8 +35,6 @@
 import java.security.Permission;
 import java.rmi.server.RMIClassLoader;
 import java.security.PrivilegedAction;
-import jdk.internal.misc.ObjectStreamClassValidator;
-import jdk.internal.misc.SharedSecrets;
 
 /**
  * MarshalInputStream is an extension of ObjectInputStream.  When resolving
@@ -54,11 +52,6 @@
  * @author      Peter Jones
  */
 public class MarshalInputStream extends ObjectInputStream {
-    interface StreamChecker extends ObjectStreamClassValidator {
-        void checkProxyInterfaceNames(String[] ifaces);
-    }
-
-    private volatile StreamChecker streamChecker = null;
 
     /**
      * Value of "java.rmi.server.useCodebaseOnly" property,
@@ -245,11 +238,6 @@
     protected Class<?> resolveProxyClass(String[] interfaces)
         throws IOException, ClassNotFoundException
     {
-        StreamChecker checker = streamChecker;
-        if (checker != null) {
-            checker.checkProxyInterfaceNames(interfaces);
-        }
-
         /*
          * Always read annotation written by MarshalOutputStream.
          */
@@ -330,28 +318,4 @@
     void useCodebaseOnly() {
         useCodebaseOnly = true;
     }
-
-    synchronized void setStreamChecker(StreamChecker checker) {
-        streamChecker = checker;
-        SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker);
-    }
-    @Override
-    protected ObjectStreamClass readClassDescriptor() throws IOException,
-            ClassNotFoundException {
-        ObjectStreamClass descriptor = super.readClassDescriptor();
-
-        validateDesc(descriptor);
-
-        return descriptor;
-    }
-
-    private void validateDesc(ObjectStreamClass descriptor) {
-        StreamChecker checker;
-        synchronized (this) {
-            checker = streamChecker;
-        }
-        if (checker != null) {
-            checker.validateDescriptor(descriptor);
-        }
-    }
 }
--- a/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,7 +32,6 @@
 import java.rmi.MarshalException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
-import java.rmi.ServerException;
 import java.rmi.UnmarshalException;
 import java.rmi.server.Operation;
 import java.rmi.server.RemoteCall;
@@ -187,14 +186,11 @@
 
                 return returnValue;
 
-            } catch (IOException e) {
+            } catch (IOException | ClassNotFoundException e) {
+                // disable saving any refs in the inputStream for GC
+                ((StreamRemoteCall)call).discardPendingRefs();
                 clientRefLog.log(Log.BRIEF,
-                                 "IOException unmarshalling return: ", e);
-                throw new UnmarshalException("error unmarshalling return", e);
-            } catch (ClassNotFoundException e) {
-                clientRefLog.log(Log.BRIEF,
-                    "ClassNotFoundException unmarshalling return: ", e);
-
+                                 e.getClass().getName() + " unmarshalling return: ", e);
                 throw new UnmarshalException("error unmarshalling return", e);
             } finally {
                 try {
--- a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -30,9 +30,9 @@
 import java.io.ObjectInputFilter;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
-import java.io.ObjectStreamClass;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.rmi.AccessException;
 import java.rmi.MarshalException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
@@ -57,6 +57,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import sun.rmi.runtime.Log;
 import sun.rmi.transport.LiveRef;
+import sun.rmi.transport.StreamRemoteCall;
 import sun.rmi.transport.Target;
 import sun.rmi.transport.tcp.TCPTransport;
 
@@ -287,20 +288,25 @@
             try {
                 in = call.getInputStream();
                 num = in.readInt();
-                if (num >= 0) {
-                    if (skel != null) {
-                        oldDispatch(obj, call, num);
-                        return;
-                    } else {
-                        throw new UnmarshalException(
-                            "skeleton class not found but required " +
-                            "for client version");
-                    }
+            } catch (Exception readEx) {
+                throw new UnmarshalException("error unmarshalling call header",
+                                             readEx);
+            }
+            if (num >= 0) {
+                if (skel != null) {
+                    oldDispatch(obj, call, num);
+                    return;
+                } else {
+                    throw new UnmarshalException(
+                        "skeleton class not found but required " +
+                        "for client version");
                 }
+            }
+            try {
                 op = in.readLong();
             } catch (Exception readEx) {
                 throw new UnmarshalException("error unmarshalling call header",
-                                             readEx);
+                        readEx);
             }
 
             /*
@@ -323,15 +329,24 @@
             logCall(obj, method);
 
             // unmarshal parameters
-            Object[] params = null;
+            Class<?>[] types = method.getParameterTypes();
+            Object[] params = new Object[types.length];
 
             try {
                 unmarshalCustomCallData(in);
-                params = unmarshalParameters(obj, method, marshalStream);
-            } catch (java.io.IOException e) {
-                throw new UnmarshalException(
-                    "error unmarshalling arguments", e);
-            } catch (ClassNotFoundException e) {
+                // Unmarshal the parameters
+                for (int i = 0; i < types.length; i++) {
+                    params[i] = unmarshalValue(types[i], in);
+                }
+
+            } catch (AccessException aex) {
+                // For compatibility, AccessException is not wrapped in UnmarshalException
+                // disable saving any refs in the inputStream for GC
+                ((StreamRemoteCall) call).discardPendingRefs();
+                throw aex;
+            } catch (java.io.IOException | ClassNotFoundException e) {
+                // disable saving any refs in the inputStream for GC
+                ((StreamRemoteCall) call).discardPendingRefs();
                 throw new UnmarshalException(
                     "error unmarshalling arguments", e);
             } finally {
@@ -365,6 +380,7 @@
                  */
             }
         } catch (Throwable e) {
+            Throwable origEx = e;
             logCallException(e);
 
             ObjectOutput out = call.getResultStream(false);
@@ -380,6 +396,12 @@
                 clearStackTraces(e);
             }
             out.writeObject(e);
+
+            // AccessExceptions should cause Transport.serviceCall
+            // to flag the connection as unusable.
+            if (origEx instanceof AccessException) {
+                throw new IOException("Connection is not reusable", origEx);
+            }
         } finally {
             call.releaseInputStream(); // in case skeleton doesn't
             call.releaseOutputStream();
@@ -408,62 +430,41 @@
      * Handle server-side dispatch using the RMI 1.1 stub/skeleton
      * protocol, given a non-negative operation number that has
      * already been read from the call stream.
+     * Exceptions are handled by the caller to be sent to the remote client.
      *
      * @param obj the target remote object for the call
      * @param call the "remote call" from which operation and
      * method arguments can be obtained.
      * @param op the operation number
-     * @exception IOException if unable to marshal return result or
+     * @throws Exception if unable to marshal return result or
      * release input or output streams
      */
-    public void oldDispatch(Remote obj, RemoteCall call, int op)
-        throws IOException
+    private void oldDispatch(Remote obj, RemoteCall call, int op)
+        throws Exception
     {
         long hash;              // hash for matching stub with skeleton
 
+        // read remote call header
+        ObjectInput in;
+        in = call.getInputStream();
         try {
-            // read remote call header
-            ObjectInput in;
-            try {
-                in = call.getInputStream();
-                try {
-                    Class<?> clazz = Class.forName("sun.rmi.transport.DGCImpl_Skel");
-                    if (clazz.isAssignableFrom(skel.getClass())) {
-                        ((MarshalInputStream)in).useCodebaseOnly();
-                    }
-                } catch (ClassNotFoundException ignore) { }
-                hash = in.readLong();
-            } catch (Exception readEx) {
-                throw new UnmarshalException("error unmarshalling call header",
-                                             readEx);
+            Class<?> clazz = Class.forName("sun.rmi.transport.DGCImpl_Skel");
+            if (clazz.isAssignableFrom(skel.getClass())) {
+                ((MarshalInputStream)in).useCodebaseOnly();
             }
+        } catch (ClassNotFoundException ignore) { }
 
-            // if calls are being logged, write out object id and operation
-            logCall(obj, skel.getOperations()[op]);
-            unmarshalCustomCallData(in);
-            // dispatch to skeleton for remote object
-            skel.dispatch(obj, call, op, hash);
+        try {
+            hash = in.readLong();
+        } catch (Exception ioe) {
+            throw new UnmarshalException("error unmarshalling call header", ioe);
+        }
 
-        } catch (Throwable e) {
-            logCallException(e);
-
-            ObjectOutput out = call.getResultStream(false);
-            if (e instanceof Error) {
-                e = new ServerError(
-                    "Error occurred in server thread", (Error) e);
-            } else if (e instanceof RemoteException) {
-                e = new ServerException(
-                    "RemoteException occurred in server thread",
-                    (Exception) e);
-            }
-            if (suppressStackTraces) {
-                clearStackTraces(e);
-            }
-            out.writeObject(e);
-        } finally {
-            call.releaseInputStream(); // in case skeleton doesn't
-            call.releaseOutputStream();
-        }
+        // if calls are being logged, write out object id and operation
+        logCall(obj, skel.getOperations()[op]);
+        unmarshalCustomCallData(in);
+        // dispatch to skeleton for remote object
+        skel.dispatch(obj, call, op, hash);
     }
 
     /**
@@ -603,84 +604,4 @@
         }
     }
 
-    /**
-     * Unmarshal parameters for the given method of the given instance over
-     * the given marshalinputstream. Perform any necessary checks.
-     */
-    private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in)
-    throws IOException, ClassNotFoundException {
-        return (obj instanceof DeserializationChecker) ?
-            unmarshalParametersChecked((DeserializationChecker)obj, method, in) :
-            unmarshalParametersUnchecked(method, in);
-    }
-
-    /**
-     * Unmarshal parameters for the given method of the given instance over
-     * the given marshalinputstream. Do not perform any additional checks.
-     */
-    private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in)
-    throws IOException, ClassNotFoundException {
-        Class<?>[] types = method.getParameterTypes();
-        Object[] params = new Object[types.length];
-        for (int i = 0; i < types.length; i++) {
-            params[i] = unmarshalValue(types[i], in);
-        }
-        return params;
-    }
-
-    /**
-     * Unmarshal parameters for the given method of the given instance over
-     * the given marshalinputstream. Do perform all additional checks.
-     */
-    private Object[] unmarshalParametersChecked(
-        DeserializationChecker checker,
-        Method method, MarshalInputStream in)
-    throws IOException, ClassNotFoundException {
-        int callID = methodCallIDCount.getAndIncrement();
-        MyChecker myChecker = new MyChecker(checker, method, callID);
-        in.setStreamChecker(myChecker);
-        try {
-            Class<?>[] types = method.getParameterTypes();
-            Object[] values = new Object[types.length];
-            for (int i = 0; i < types.length; i++) {
-                myChecker.setIndex(i);
-                values[i] = unmarshalValue(types[i], in);
-            }
-            myChecker.end(callID);
-            return values;
-        } finally {
-            in.setStreamChecker(null);
-        }
-    }
-
-    private static class MyChecker implements MarshalInputStream.StreamChecker {
-        private final DeserializationChecker descriptorCheck;
-        private final Method method;
-        private final int callID;
-        private int parameterIndex;
-
-        MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) {
-            this.descriptorCheck = descriptorCheck;
-            this.method = method;
-            this.callID = callID;
-        }
-
-        @Override
-        public void validateDescriptor(ObjectStreamClass descriptor) {
-            descriptorCheck.check(method, descriptor, parameterIndex, callID);
-        }
-
-        @Override
-        public void checkProxyInterfaceNames(String[] ifaces) {
-            descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID);
-        }
-
-        void setIndex(int parameterIndex) {
-            this.parameterIndex = parameterIndex;
-        }
-
-        void end(int callId) {
-            descriptorCheck.end(callId);
-        }
-    }
 }
--- a/src/java.rmi/share/classes/sun/rmi/transport/ConnectionInputStream.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/transport/ConnectionInputStream.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -82,6 +82,14 @@
     }
 
     /**
+     * Discard the saved incoming refs so there is nothing to register
+     * when {@code registerRefs} is called.
+     */
+    void discardRefs() {
+        incomingRefTable.clear();
+    }
+
+    /**
      * Add references to DGC table (and possibly send dirty call).
      * RegisterRefs now calls DGCClient.referenced on all
      * refs with the same endpoint at once to achieve batching of
--- a/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java	Mon Jun 19 11:29:42 2017 -0700
@@ -24,9 +24,11 @@
  */
 package sun.rmi.transport;
 
+import java.io.InvalidClassException;
 import java.lang.ref.PhantomReference;
 import java.lang.ref.ReferenceQueue;
 import java.net.SocketPermission;
+import java.rmi.UnmarshalException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
@@ -41,6 +43,8 @@
 import java.rmi.dgc.Lease;
 import java.rmi.dgc.VMID;
 import java.rmi.server.ObjID;
+
+import sun.rmi.runtime.Log;
 import sun.rmi.runtime.NewThreadAction;
 import sun.rmi.server.UnicastRef;
 import sun.rmi.server.Util;
@@ -388,6 +392,12 @@
                 synchronized (this) {
                     dirtyFailures++;
 
+                    if (e instanceof UnmarshalException
+                            && e.getCause() instanceof InvalidClassException) {
+                        DGCImpl.dgcLog.log(Log.BRIEF, "InvalidClassException exception in DGC dirty call", e);
+                        return;             // protocol error, do not register these refs
+                    }
+
                     if (dirtyFailures == 1) {
                         /*
                          * If this was the first recent failed dirty call,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Skel.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, 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.rmi.transport;
+
+/**
+ * Skeleton to dispatch DGC methods.
+ * Originally generated by RMIC but frozen to match the stubs.
+ */
+@SuppressWarnings({"deprecation", "serial"})
+public final class DGCImpl_Skel
+        implements java.rmi.server.Skeleton {
+    private static final java.rmi.server.Operation[] operations = {
+            new java.rmi.server.Operation("void clean(java.rmi.server.ObjID[], long, java.rmi.dgc.VMID, boolean)"),
+            new java.rmi.server.Operation("java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)")
+    };
+
+    private static final long interfaceHash = -669196253586618813L;
+
+    public java.rmi.server.Operation[] getOperations() {
+        return operations.clone();
+    }
+
+    public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
+            throws java.lang.Exception {
+        if (hash != interfaceHash)
+            throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+
+        sun.rmi.transport.DGCImpl server = (sun.rmi.transport.DGCImpl) obj;
+        switch (opnum) {
+            case 0: // clean(ObjID[], long, VMID, boolean)
+            {
+                java.rmi.server.ObjID[] $param_arrayOf_ObjID_1;
+                long $param_long_2;
+                java.rmi.dgc.VMID $param_VMID_3;
+                boolean $param_boolean_4;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_arrayOf_ObjID_1 = (java.rmi.server.ObjID[]) in.readObject();
+                    $param_long_2 = in.readLong();
+                    $param_VMID_3 = (java.rmi.dgc.VMID) in.readObject();
+                    $param_boolean_4 = in.readBoolean();
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } catch (java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                server.clean($param_arrayOf_ObjID_1, $param_long_2, $param_VMID_3, $param_boolean_4);
+                try {
+                    call.getResultStream(true);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            case 1: // dirty(ObjID[], long, Lease)
+            {
+                java.rmi.server.ObjID[] $param_arrayOf_ObjID_1;
+                long $param_long_2;
+                java.rmi.dgc.Lease $param_Lease_3;
+                try {
+                    java.io.ObjectInput in = call.getInputStream();
+                    $param_arrayOf_ObjID_1 = (java.rmi.server.ObjID[]) in.readObject();
+                    $param_long_2 = in.readLong();
+                    $param_Lease_3 = (java.rmi.dgc.Lease) in.readObject();
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } catch (java.lang.ClassNotFoundException e) {
+                    throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
+                } finally {
+                    call.releaseInputStream();
+                }
+                java.rmi.dgc.Lease $result = server.dirty($param_arrayOf_ObjID_1, $param_long_2, $param_Lease_3);
+                try {
+                    java.io.ObjectOutput out = call.getResultStream(true);
+                    out.writeObject($result);
+                } catch (java.io.IOException e) {
+                    throw new java.rmi.MarshalException("error marshalling return", e);
+                }
+                break;
+            }
+
+            default:
+                throw new java.rmi.UnmarshalException("invalid method number");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Stub.java	Mon Jun 19 11:29:42 2017 -0700
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2017, 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.rmi.transport;
+
+import java.io.ObjectInputFilter;
+import java.io.ObjectInputStream;
+import java.rmi.dgc.Lease;
+import java.rmi.dgc.VMID;
+import java.rmi.server.UID;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import sun.rmi.server.UnicastRef;
+import sun.rmi.transport.tcp.TCPConnection;
+
+/**
+ * Stubs to invoke DGC remote methods.
+ * Originally generated from RMIC but frozen to insert serialFilter.
+ */
+@SuppressWarnings({"deprecation", "serial"})
+public final class DGCImpl_Stub
+        extends java.rmi.server.RemoteStub
+        implements java.rmi.dgc.DGC {
+    private static final java.rmi.server.Operation[] operations = {
+            new java.rmi.server.Operation("void clean(java.rmi.server.ObjID[], long, java.rmi.dgc.VMID, boolean)"),
+            new java.rmi.server.Operation("java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)")
+    };
+
+    private static final long interfaceHash = -669196253586618813L;
+
+    /** Registry max depth of remote invocations. **/
+    private static int DGCCLIENT_MAX_DEPTH = 6;
+
+    /** Registry maximum array size in remote invocations. **/
+    private static int DGCCLIENT_MAX_ARRAY_SIZE = 10000;
+
+    // constructors
+    public DGCImpl_Stub() {
+        super();
+    }
+
+    public DGCImpl_Stub(java.rmi.server.RemoteRef ref) {
+        super(ref);
+    }
+
+    // methods from remote interfaces
+
+    // implementation of clean(ObjID[], long, VMID, boolean)
+    public void clean(java.rmi.server.ObjID[] $param_arrayOf_ObjID_1, long $param_long_2, java.rmi.dgc.VMID $param_VMID_3, boolean $param_boolean_4)
+            throws java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_arrayOf_ObjID_1);
+                out.writeLong($param_long_2);
+                out.writeObject($param_VMID_3);
+                out.writeBoolean($param_boolean_4);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            ref.done(call);
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    // implementation of dirty(ObjID[], long, Lease)
+    public java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[] $param_arrayOf_ObjID_1, long $param_long_2, java.rmi.dgc.Lease $param_Lease_3)
+            throws java.rmi.RemoteException {
+        try {
+            java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash);
+            try {
+                java.io.ObjectOutput out = call.getOutputStream();
+                out.writeObject($param_arrayOf_ObjID_1);
+                out.writeLong($param_long_2);
+                out.writeObject($param_Lease_3);
+            } catch (java.io.IOException e) {
+                throw new java.rmi.MarshalException("error marshalling arguments", e);
+            }
+            ref.invoke(call);
+            java.rmi.dgc.Lease $result;
+            Connection connection = ((StreamRemoteCall) call).getConnection();
+            try {
+                java.io.ObjectInput in = call.getInputStream();
+
+                if (in instanceof ObjectInputStream) {
+                    /**
+                     * Set a filter on the stream for the return value.
+                     */
+                    ObjectInputStream ois = (ObjectInputStream) in;
+                    AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+                        ois.setObjectInputFilter(DGCImpl_Stub::leaseFilter);
+                        return null;
+                    });
+                }
+                $result = (java.rmi.dgc.Lease) in.readObject();
+            } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+                if (connection instanceof TCPConnection) {
+                    // Modified to prevent re-use of the connection after an exception
+                    ((TCPConnection) connection).getChannel().free(connection, false);
+                }
+                throw new java.rmi.UnmarshalException("error unmarshalling return", e);
+            } finally {
+                ref.done(call);
+            }
+            return $result;
+        } catch (java.lang.RuntimeException e) {
+            throw e;
+        } catch (java.rmi.RemoteException e) {
+            throw e;
+        } catch (java.lang.Exception e) {
+            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
+        }
+    }
+
+    /**
+     * ObjectInputFilter to filter DGCClient return value (a Lease).
+     * The list of acceptable classes is very short and explicit.
+     * The depth and array sizes are limited.
+     *
+     * @param filterInfo access to class, arrayLength, etc.
+     * @return  {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+     *          {@link ObjectInputFilter.Status#REJECTED} if rejected,
+     *          otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+     */
+    private static ObjectInputFilter.Status leaseFilter(ObjectInputFilter.FilterInfo filterInfo) {
+
+        if (filterInfo.depth() > DGCCLIENT_MAX_DEPTH) {
+            return ObjectInputFilter.Status.REJECTED;
+        }
+        Class<?> clazz = filterInfo.serialClass();
+        if (clazz != null) {
+            while (clazz.isArray()) {
+                if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > DGCCLIENT_MAX_ARRAY_SIZE) {
+                    return ObjectInputFilter.Status.REJECTED;
+                }
+                // Arrays are allowed depending on the component type
+                clazz = clazz.getComponentType();
+            }
+            if (clazz.isPrimitive()) {
+                // Arrays of primitives are allowed
+                return ObjectInputFilter.Status.ALLOWED;
+            }
+            return (clazz == UID.class ||
+                    clazz == VMID.class ||
+                    clazz == Lease.class)
+                    ? ObjectInputFilter.Status.ALLOWED
+                    : ObjectInputFilter.Status.REJECTED;
+        }
+        // Not a class, not size limited
+        return ObjectInputFilter.Status.UNDECIDED;
+    }
+
+}
--- a/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -168,6 +168,13 @@
     }
 
     /**
+     * Discard any post-processing of refs the InputStream.
+     */
+    public void discardPendingRefs() {
+        in.discardRefs();
+    }
+
+    /**
      * Returns an output stream (may put out header information
      * relating to the success of the call).
      * @param success If true, indicates normal return, else indicates
--- a/src/java.rmi/share/classes/sun/rmi/transport/Target.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/transport/Target.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,6 +31,7 @@
 import java.rmi.server.Unreferenced;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.*;
 import sun.rmi.runtime.Log;
 import sun.rmi.runtime.NewThreadAction;
@@ -322,27 +323,15 @@
             Remote obj = getImpl();
             if (obj instanceof Unreferenced) {
                 final Unreferenced unrefObj = (Unreferenced) obj;
-                final Thread t =
-                    java.security.AccessController.doPrivileged(
-                        new NewThreadAction(new Runnable() {
-                            public void run() {
-                                unrefObj.unreferenced();
-                            }
-                        }, "Unreferenced-" + nextThreadNum++, false, true));
-                // REMIND: access to nextThreadNum not synchronized; you care?
-                /*
-                 * We must manually set the context class loader appropriately
-                 * for threads that may invoke user code (see bugid 4171278).
-                 */
-                java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedAction<Void>() {
-                        public Void run() {
-                        t.setContextClassLoader(ccl);
-                        return null;
-                    }
-                });
-
-                t.start();
+                AccessController.doPrivileged(
+                    new NewThreadAction(() -> {
+                        Thread.currentThread().setContextClassLoader(ccl);
+                        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                            unrefObj.unreferenced();
+                            return null;
+                        }, acc);
+                    }, "Unreferenced-" + nextThreadNum++, false, true)).start();
+                    // REMIND: access to nextThreadNum not synchronized; you care?
             }
 
             unpinImpl();
--- a/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java	Mon Jun 19 11:29:42 2017 -0700
@@ -270,7 +270,7 @@
     }
 
     public String toString() {
-        return "PC/SC card in " + terminal.getName()
+        return "PC/SC card in " + terminal.name
             + ", protocol " + getProtocol() + ", state " + state;
     }
 
@@ -278,6 +278,7 @@
     protected void finalize() throws Throwable {
         try {
             if (state == State.OK) {
+                state = State.DISCONNECTED;
                 SCardDisconnect(cardId, SCARD_LEAVE_CARD);
             }
         } finally {
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -370,9 +370,15 @@
         }
         random.nextBytes(seed);
 
+        // random bits needed for timing countermeasures
+        int timingArgument = random.nextInt();
+        // values must be non-zero to enable countermeasures
+        timingArgument |= 1;
+
         byte[] sig;
         try {
-            sig = signDigest(getDigestValue(), s, encodedParams, seed);
+            sig = signDigest(getDigestValue(), s, encodedParams, seed,
+                timingArgument);
         } catch (GeneralSecurityException e) {
             throw new SignatureException("Could not sign data", e);
         }
@@ -509,11 +515,19 @@
      * @param s the private key's S value.
      * @param encodedParams the curve's DER encoded object identifier.
      * @param seed the random seed.
+     * @param timing When non-zero, the implmentation will use timing
+     *     countermeasures to hide secrets from timing channels. The EC
+     *     implementation will disable the countermeasures when this value is
+     *     zero, because the underlying EC functions are shared by several
+     *     crypto operations, some of which do not use the countermeasures.
+     *     The high-order 31 bits must be uniformly random. The entropy from
+     *     these bits is used by the countermeasures.
      *
      * @return byte[] the signature.
      */
     private static native byte[] signDigest(byte[] digest, byte[] s,
-        byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
+        byte[] encodedParams, byte[] seed, int timing)
+            throws GeneralSecurityException;
 
     /**
      * Verifies the signed digest using the public key.
--- a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -196,7 +196,7 @@
  */
 JNIEXPORT jbyteArray
 JNICALL Java_sun_security_ec_ECDSASignature_signDigest
-  (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed)
+  (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing)
 {
     jbyte* pDigestBuffer = NULL;
     jint jDigestLength = env->GetArrayLength(digest);
@@ -256,7 +256,7 @@
 
     // Sign the digest (using the supplied seed)
     if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
-        (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) {
+        (unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) {
         ThrowException(env, KEY_EXCEPTION);
         goto cleanup;
     }
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@
  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
- * Last Modified Date from the Original Code: November 2016
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "mplogic.h"
@@ -87,7 +87,7 @@
  */
 SECStatus
 ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
-             const SECItem *pointP, SECItem *pointQ, int kmflag)
+             const SECItem *pointP, SECItem *pointQ, int kmflag, int timing)
 {
     mp_int Px, Py, Qx, Qy;
     mp_int Gx, Gy, order, irreducible, a, b;
@@ -199,9 +199,9 @@
                 goto cleanup;
 
         if ((k2 != NULL) && (pointP != NULL)) {
-                CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
+                CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy, timing) );
         } else {
-                CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
+                CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy, timing) );
     }
 
     /* Construct the SECItem representation of point Q */
@@ -333,7 +333,8 @@
     CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
         (mp_size) len) );
 
-    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
+    /* key generation does not support timing mitigation */
+    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag, /*timing*/ 0);
     if (rv != SECSuccess) goto cleanup;
     *privKey = key;
 
@@ -610,7 +611,8 @@
     }
 
     /* Multiply our private key and peer's public point */
-    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
+    /* ECDH doesn't support timing mitigation */
+    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag, /*timing*/ 0) != SECSuccess) ||
         ec_point_at_infinity(&pointQ))
         goto cleanup;
 
@@ -645,7 +647,8 @@
  */
 SECStatus
 ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
-    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
+    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag,
+    int timing)
 {
     SECStatus rv = SECFailure;
     mp_int x1;
@@ -715,16 +718,6 @@
     }
 
     /*
-     * Using an equivalent exponent of fixed length (same as n or 1 bit less
-     * than n) to keep the kG timing relatively constant.
-     *
-     * Note that this is an extra step on top of the approach defined in
-     * ANSI X9.62 so as to make a fixed length K.
-     */
-    CHECK_MPI_OK( mp_add(&k, &n, &k) );
-    CHECK_MPI_OK( mp_div_2(&k, &k) );
-
-    /*
     ** ANSI X9.62, Section 5.3.2, Step 2
     **
     ** Compute kG
@@ -732,7 +725,7 @@
     kGpoint.len = 2*flen + 1;
     kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
     if ((kGpoint.data == NULL) ||
-        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
+        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag, timing)
             != SECSuccess))
         goto cleanup;
 
@@ -854,7 +847,7 @@
 */
 SECStatus
 ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
-    const unsigned char* random, int randomLen, int kmflag)
+    const unsigned char* random, int randomLen, int kmflag, int timing)
 {
     SECStatus rv = SECFailure;
     int len;
@@ -872,7 +865,7 @@
     if (kBytes == NULL) goto cleanup;
 
     /* Generate ECDSA signature with the specified k value */
-    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
+    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag, timing);
 
 cleanup:
     if (kBytes) {
@@ -1018,7 +1011,8 @@
     ** Here, A = u1.G     B = u2.Q    and   C = A + B
     ** If the result, C, is the point at infinity, reject the signature
     */
-    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
+    /* verification does not support timing mitigation */
+    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag, /*timing*/ 0)
         != SECSuccess) {
         rv = SECFailure;
         goto cleanup;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _EC2_H
@@ -79,7 +80,7 @@
  * determines the field GF2m.  Uses Montgomery projective coordinates. */
 mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
                                                    const mp_int *py, mp_int *rx, mp_int *ry,
-                                                   const ECGroup *group);
+                                                   const ECGroup *group, int timing);
 
 #ifdef ECL_ENABLE_GF2M_PROJ
 /* Converts a point P(px, py) from affine coordinates to projective
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ec2.h"
@@ -329,7 +330,8 @@
     /* 4: Verify that the order of the curve times the publicValue
      *    is the point at infinity.
      */
-        MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
+        /* timing mitigation is not supported */
+        MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) );
         if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
                 res = MP_NO;
                 goto CLEANUP;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -35,6 +35,7 @@
  *   Stephen Fung <fungstep@hotmail.com>, and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
  *
+ *  Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ec2.h"
@@ -181,10 +182,12 @@
 /* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R.  "Fast
  * multiplication on elliptic curves over GF(2^m) without
  * precomputation". Elliptic curve points P and R can be identical. Uses
- * Montgomery projective coordinates. */
+ * Montgomery projective coordinates. The timing parameter is ignored
+ * because this algorithm resists timing attacks by default. */
 mp_err
 ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py,
-                                        mp_int *rx, mp_int *ry, const ECGroup *group)
+                                        mp_int *rx, mp_int *ry, const ECGroup *group,
+                                        int timing)
 {
         mp_err res = MP_OKAY;
         mp_int x1, x2, z1, z2;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecc_impl.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecc_impl.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@
  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
- * Last Modified Date from the Original Code: November 2013
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECC_IMPL_H
@@ -258,7 +258,7 @@
     const unsigned char* random, int randomlen, int);
 /* This function has been modified to accept an array of random bytes */
 extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
-    const unsigned char* random, int randomlen, int);
+    const unsigned char* random, int randomlen, int, int timing);
 extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
     const SECItem *, int);
 extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-priv.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-priv.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -34,6 +34,7 @@
  *   Stephen Fung <fungstep@hotmail.com> and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECL_PRIV_H
@@ -193,12 +194,13 @@
                                                  mp_int *ry, const ECGroup *group);
         mp_err (*point_mul) (const mp_int *n, const mp_int *px,
                                                  const mp_int *py, mp_int *rx, mp_int *ry,
-                                                 const ECGroup *group);
+                                                 const ECGroup *group, int timing);
         mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
                                                           const ECGroup *group);
         mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
                                                   const mp_int *px, const mp_int *py, mp_int *rx,
-                                                  mp_int *ry, const ECGroup *group);
+                                                  mp_int *ry, const ECGroup *group,
+                                                  int timing);
         mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
         /* Extra storage for implementation-specific data.  Any memory
          * allocated to these extra fields will be cleared by extra_free. */
@@ -262,10 +264,12 @@
 /* point multiplication */
 mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
                                                 const mp_int *px, const mp_int *py, mp_int *rx,
-                                                mp_int *ry, const ECGroup *group);
+                                                mp_int *ry, const ECGroup *group,
+                                                int timing);
 mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
                                                    const mp_int *px, const mp_int *py, mp_int *rx,
-                                                   mp_int *ry, const ECGroup *group);
+                                                   mp_int *ry, const ECGroup *group,
+                                                   int timing);
 
 /* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
  * be an array of signed char's to output to, bitsize should be the number
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECL_H
@@ -70,7 +71,8 @@
  * of the group of points on the elliptic curve. Input and output values
  * are assumed to be NOT field-encoded. */
 mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
-                                   const mp_int *py, mp_int *qx, mp_int *qy);
+                                   const mp_int *py, mp_int *qx, mp_int *qy,
+                                   int timing);
 
 /* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
  * k2 * P(x, y), where G is the generator (base point) of the group of
@@ -78,7 +80,7 @@
  * be NOT field-encoded. */
 mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
                                         const mp_int *k2, const mp_int *px, const mp_int *py,
-                                        mp_int *qx, mp_int *qy);
+                                        mp_int *qx, mp_int *qy, int timing);
 
 /* Validates an EC public key as described in Section 5.2.2 of X9.62.
  * Returns MP_YES if the public key is valid, MP_NO if the public key
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_mult.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_mult.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,7 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
- * Last Modified Date from the Original Code: Nov 2016
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "mpi.h"
@@ -50,7 +50,8 @@
  * are assumed to be NOT field-encoded. */
 mp_err
 ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
-                        const mp_int *py, mp_int *rx, mp_int *ry)
+                        const mp_int *py, mp_int *rx, mp_int *ry,
+                        int timing)
 {
         mp_err res = MP_OKAY;
         mp_int kt;
@@ -76,16 +77,16 @@
                         kt.flag = (mp_sign)0;
                         MP_CHECKOK(group->
                                            point_mul(&kt, &group->genx, &group->geny, rx, ry,
-                                                                 group));
+                                                                 group, timing));
                 }
         } else {
                 if (group->meth->field_enc) {
                         MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
                         MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
-                        MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group));
+                        MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group, timing));
                 } else {
                         kt.flag = (mp_sign)0;
-                        MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group));
+                        MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group, timing));
                 }
         }
         if (group->meth->field_dec) {
@@ -107,7 +108,7 @@
 mp_err
 ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
                                  const mp_int *py, mp_int *rx, mp_int *ry,
-                                 const ECGroup *group)
+                                 const ECGroup *group, int timing)
 {
         mp_err res = MP_OKAY;
         mp_int sx, sy;
@@ -119,9 +120,9 @@
 
         /* if some arguments are not defined used ECPoint_mul */
         if (k1 == NULL) {
-                return ECPoint_mul(group, k2, px, py, rx, ry);
+                return ECPoint_mul(group, k2, px, py, rx, ry, timing);
         } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
-                return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
+                return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
         }
 
         MP_DIGITS(&sx) = 0;
@@ -129,8 +130,8 @@
         MP_CHECKOK(mp_init(&sx, FLAG(k1)));
         MP_CHECKOK(mp_init(&sy, FLAG(k1)));
 
-        MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
-        MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));
+        MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy, timing));
+        MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry, timing));
 
         if (group->meth->field_enc) {
                 MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
@@ -162,7 +163,7 @@
 mp_err
 ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px,
                                         const mp_int *py, mp_int *rx, mp_int *ry,
-                                        const ECGroup *group)
+                                        const ECGroup *group, int timing)
 {
         mp_err res = MP_OKAY;
         mp_int precomp[4][4][2];
@@ -177,9 +178,9 @@
 
         /* if some arguments are not defined used ECPoint_mul */
         if (k1 == NULL) {
-                return ECPoint_mul(group, k2, px, py, rx, ry);
+                return ECPoint_mul(group, k2, px, py, rx, ry, timing);
         } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
-                return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
+                return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
         }
 
         /* initialize precomputation table */
@@ -311,7 +312,8 @@
  * Input and output values are assumed to be NOT field-encoded. */
 mp_err
 ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
-                         const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry)
+                         const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry,
+                         int timing)
 {
         mp_err res = MP_OKAY;
         mp_int k1t, k2t;
@@ -348,9 +350,9 @@
 
         /* if points_mul is defined, then use it */
         if (group->points_mul) {
-                res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
+                res = group->points_mul(k1p, k2p, px, py, rx, ry, group, timing);
         } else {
-                res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
+                res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group, timing);
         }
 
   CLEANUP:
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp.h	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp.h	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECP_H
@@ -122,7 +123,7 @@
 mp_err
  ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
                                         const mp_int *py, mp_int *rx, mp_int *ry,
-                                        const ECGroup *group);
+                                        const ECGroup *group, int timing);
 
 /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
  * curve points P and R can be identical. Uses mixed Modified-Jacobian
@@ -131,9 +132,13 @@
  * returns output that is still field-encoded. Uses 5-bit window NAF
  * method (algorithm 11) for scalar-point multiplication from Brown,
  * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
- * Curves Over Prime Fields. */
+ * Curves Over Prime Fields. The implementation includes a countermeasure
+ * that attempts to hide the size of n from timing channels. This counter-
+ * measure is enabled using the timing argument. The high-rder bits of timing
+ * must be uniformly random in order for this countermeasure to work. */
 mp_err
  ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
-                                           mp_int *rx, mp_int *ry, const ECGroup *group);
+                                           mp_int *rx, mp_int *ry, const ECGroup *group,
+                                           int timing);
 
 #endif /* _ECP_H */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_aff.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_aff.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -38,6 +38,7 @@
  *   Nils Larsch <nla@trustcenter.de>, and
  *   Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -340,7 +341,8 @@
     /* 4: Verify that the order of the curve times the publicValue
      *    is the point at infinity.
      */
-        MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
+        /* timing mitigation is not supported */
+        MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) );
         if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
                 res = MP_NO;
                 goto CLEANUP;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jac.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jac.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -38,6 +38,7 @@
  *   Nils Larsch <nla@trustcenter.de>, and
  *   Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -180,6 +181,15 @@
         MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
         MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
 
+        /*
+         * Additional checks for point equality and point at infinity
+         */
+        if (mp_cmp(px, &A) == 0 && mp_cmp(py, &B) == 0) {
+            /* POINT_DOUBLE(P) */
+            MP_CHECKOK(ec_GFp_pt_dbl_jac(px, py, pz, rx, ry, rz, group));
+            goto CLEANUP;
+        }
+
         /* C = A - px, D = B - py */
         MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
         MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
@@ -406,7 +416,7 @@
 mp_err
 ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
                                    const mp_int *py, mp_int *rx, mp_int *ry,
-                                   const ECGroup *group)
+                                   const ECGroup *group, int timing)
 {
         mp_err res = MP_OKAY;
         mp_int precomp[4][4][2];
@@ -430,9 +440,9 @@
 
         /* if some arguments are not defined used ECPoint_mul */
         if (k1 == NULL) {
-                return ECPoint_mul(group, k2, px, py, rx, ry);
+                return ECPoint_mul(group, k2, px, py, rx, ry, timing);
         } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
-                return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
+                return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
         }
 
         /* initialize precomputation table */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jm.c	Mon Jun 19 08:16:03 2017 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jm.c	Mon Jun 19 11:29:42 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@
  * Contributor(s):
  *   Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -165,6 +166,16 @@
         MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
         MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
 
+        /*
+         * Additional checks for point equality and point at infinity
+         */
+        if (mp_cmp(px, A) == 0 && mp_cmp(py, B) == 0) {
+            /* POINT_DOUBLE(P) */
+            MP_CHECKOK(ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
+                                        scratch, group));
+            goto CLEANUP;
+        }
+
         /* C = A - px, D = B - py */
         MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
         MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
@@ -213,19 +224,23 @@
  * Curves Over Prime Fields. */
 mp_err
 ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
-                                          mp_int *rx, mp_int *ry, const ECGroup *group)
+                                          mp_int *rx, mp_int *ry, const ECGroup *group,
+                                          int timing)
 {
         mp_err res = MP_OKAY;
-        mp_int precomp[16][2], rz, tpx, tpy;
-        mp_int raz4;
+        mp_int precomp[16][2], rz, tpx, tpy, tpz;
+        mp_int raz4, tpaz4;
         mp_int scratch[MAX_SCRATCH];
         signed char *naf = NULL;
         int i, orderBitSize;
+        int numDoubles, numAdds, extraDoubles, extraAdds;
 
         MP_DIGITS(&rz) = 0;
         MP_DIGITS(&raz4) = 0;
         MP_DIGITS(&tpx) = 0;
         MP_DIGITS(&tpy) = 0;
+        MP_DIGITS(&tpz) = 0;
+        MP_DIGITS(&tpaz4) = 0;
         for (i = 0; i < 16; i++) {
                 MP_DIGITS(&precomp[i][0]) = 0;
                 MP_DIGITS(&precomp[i][1]) = 0;
@@ -239,7 +254,9 @@
 
         /* initialize precomputation table */
         MP_CHECKOK(mp_init(&tpx, FLAG(n)));
-        MP_CHECKOK(mp_init(&tpy, FLAG(n)));;
+        MP_CHECKOK(mp_init(&tpy, FLAG(n)));
+        MP_CHECKOK(mp_init(&tpz, FLAG(n)));
+        MP_CHECKOK(mp_init(&tpaz4, FLAG(n)));
         MP_CHECKOK(mp_init(&rz, FLAG(n)));
         MP_CHECKOK(mp_init(&raz4, FLAG(n)));
 
@@ -295,19 +312,64 @@
         /* Compute 5NAF */
         ec_compute_wNAF(naf, orderBitSize, n, 5);
 
+        numAdds = 0;
+        numDoubles = orderBitSize;
         /* wNAF method */
         for (i = orderBitSize; i >= 0; i--) {
+
+                if (ec_GFp_pt_is_inf_jac(rx, ry, &rz) == MP_YES) {
+                  numDoubles--;
+                }
+
                 /* R = 2R */
                 ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,