Merge
authorduke
Wed, 05 Jul 2017 18:35:53 +0200
changeset 15024 680b33a36b29
parent 15023 8268581591da (current diff)
parent 15022 6bd47e828259 (diff)
child 15026 bccbb01d7958
Merge
--- a/.hgtags-top-repo	Thu Jan 10 09:55:26 2013 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 18:35:53 2017 +0200
@@ -193,3 +193,4 @@
 6ee8080a6efe0639fcd00627a5e0f839bf010481 jdk8-b69
 105a25ffa4a4f0af70188d4371b4a0385009b7ce jdk8-b70
 51ad2a34342055333eb5f36e2fb514b027895708 jdk8-b71
+c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72
--- a/common/bin/compare_exceptions.sh.incl	Thu Jan 10 09:55:26 2013 -0800
+++ b/common/bin/compare_exceptions.sh.incl	Wed Jul 05 18:35:53 2017 +0200
@@ -80,6 +80,7 @@
 ./bin/javadoc
 ./bin/javah
 ./bin/javap
+./bin/jdeps
 ./bin/jcmd
 ./bin/jconsole
 ./bin/jdb
@@ -167,6 +168,7 @@
 ./bin/javadoc
 ./bin/javah
 ./bin/javap
+./bin/jdeps
 ./bin/jcmd
 ./bin/jconsole
 ./bin/jdb
@@ -309,6 +311,7 @@
 ./bin/javadoc
 ./bin/javah
 ./bin/javap
+./bin/jdeps
 ./bin/javaws
 ./bin/jcmd
 ./bin/jconsole
@@ -449,6 +452,7 @@
 ./bin/amd64/javadoc
 ./bin/amd64/javah
 ./bin/amd64/javap
+./bin/amd64/jdeps
 ./bin/amd64/jcmd
 ./bin/amd64/jconsole
 ./bin/amd64/jdb
@@ -606,6 +610,7 @@
 ./bin/javadoc
 ./bin/javah
 ./bin/javap
+./bin/jdeps
 ./bin/javaws
 ./bin/jcmd
 ./bin/jconsole
@@ -751,6 +756,7 @@
 ./bin/sparcv9/javadoc
 ./bin/sparcv9/javah
 ./bin/sparcv9/javap
+./bin/sparcv9/jdeps
 ./bin/sparcv9/jcmd
 ./bin/sparcv9/jconsole
 ./bin/sparcv9/jdb
@@ -826,6 +832,7 @@
 ./bin/javadoc.exe
 ./bin/javah.exe
 ./bin/javap.exe
+./bin/jdeps.exe
 ./bin/javaw.exe
 ./bin/jcmd.exe
 ./bin/jconsole.exe
@@ -910,6 +917,7 @@
 ./bin/javadoc
 ./bin/javah
 ./bin/javap
+./bin/jdeps
 ./bin/jcmd
 ./bin/jconsole
 ./bin/jdb
--- a/hotspot/.hgtags	Thu Jan 10 09:55:26 2013 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 18:35:53 2017 +0200
@@ -305,3 +305,4 @@
 990bbd393c239d95310ccc38094e57923bbf1d4a hs25-b14
 e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70
 0847210f85480bf3848dc90bc2ab23c0a4791b55 jdk8-b71
+d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72
--- a/jdk/.hgtags	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/.hgtags	Wed Jul 05 18:35:53 2017 +0200
@@ -193,3 +193,4 @@
 a8012d8d7e9c5035de0bdd4887dc9f7c54008f21 jdk8-b69
 a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70
 2a5af0f766d0acd68a81fb08fe11fd66795f86af jdk8-b71
+32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72
--- a/jdk/make/common/Release.gmk	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/make/common/Release.gmk	Wed Jul 05 18:35:53 2017 +0200
@@ -375,6 +375,7 @@
 	com/sun/tools/javadoc   \
 	com/sun/tools/javah     \
 	com/sun/tools/javap     \
+	com/sun/tools/jdeps     \
 	com/sun/tools/corba     \
 	com/sun/tools/internal/xjc       \
 	com/sun/tools/internal/ws       \
@@ -457,6 +458,7 @@
 	javadoc$(EXE_SUFFIX) \
 	javah$(EXE_SUFFIX) \
 	javap$(EXE_SUFFIX) \
+	jdeps$(EXE_SUFFIX) \
 	jcmd$(EXE_SUFFIX) \
 	jdb$(EXE_SUFFIX) \
 	jps$(EXE_SUFFIX) \
@@ -564,6 +566,7 @@
 	$(ECHO) "sun/tools/javac/" >> $@
 	$(ECHO) "com/sun/tools/classfile/" >> $@
 	$(ECHO) "com/sun/tools/javap/" >> $@
+	$(ECHO) "com/sun/tools/jdeps/" >> $@
 	$(ECHO) "sun/tools/jcmd/" >> $@
 	$(ECHO) "sun/tools/jconsole/" >> $@
 	$(ECHO) "sun/tools/jps/" >> $@
--- a/jdk/make/docs/NON_CORE_PKGS.gmk	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/make/docs/NON_CORE_PKGS.gmk	Wed Jul 05 18:35:53 2017 +0200
@@ -76,7 +76,7 @@
 
 JCONSOLE_PKGS    = com.sun.tools.jconsole
 
-TREEAPI_PKGS 	 = com.sunsource.doctree \
+TREEAPI_PKGS 	 = com.sun.source.doctree \
 		   com.sun.source.tree \
 		   com.sun.source.util
 
--- a/jdk/make/launchers/Makefile	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/make/launchers/Makefile	Wed Jul 05 18:35:53 2017 +0200
@@ -63,6 +63,7 @@
 $(call make-launcher, javadoc, com.sun.tools.javadoc.Main, , )
 $(call make-launcher, javah, com.sun.tools.javah.Main, , )
 $(call make-launcher, javap, com.sun.tools.javap.Main, , )
+$(call make-launcher, jdeps, com.sun.tools.jdeps.Main, , )
 $(call make-launcher, jcmd, sun.tools.jcmd.JCmd, , )
 $(call make-launcher, jconsole, sun.tools.jconsole.JConsole, \
   -J-Djconsole.showOutputViewer, )
--- a/jdk/make/launchers/Makefile.launcher	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/make/launchers/Makefile.launcher	Wed Jul 05 18:35:53 2017 +0200
@@ -62,6 +62,10 @@
   WILDCARDS=true
   NEVER_ACT_AS_SERVER_CLASS_MACHINE=true
 endif
+ifeq ($(PROGRAM),jdeps)
+  WILDCARDS=true
+  NEVER_ACT_AS_SERVER_CLASS_MACHINE=true
+endif
 ifeq ($(PROGRAM),javah)
   WILDCARDS=true
   NEVER_ACT_AS_SERVER_CLASS_MACHINE=true
--- a/jdk/makefiles/CompileLaunchers.gmk	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/makefiles/CompileLaunchers.gmk	Wed Jul 05 18:35:53 2017 +0200
@@ -267,6 +267,11 @@
     -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
     -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javap.Main"$(COMMA) }'))
 
+$(eval $(call SetupLauncher,jdeps,\
+    -DEXPAND_CLASSPATH_WILDCARDS \
+    -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
+    -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.jdeps.Main"$(COMMA) }'))
+
 BUILD_LAUNCHER_jconsole_CFLAGS_windows:=-DJAVAW
 BUILD_LAUNCHER_jconsole_LDFLAGS_windows:=user32.lib
 
--- a/jdk/makefiles/CreateJars.gmk	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/makefiles/CreateJars.gmk	Wed Jul 05 18:35:53 2017 +0200
@@ -738,6 +738,7 @@
 	com/sun/tools/javadoc   \
 	com/sun/tools/javah     \
 	com/sun/tools/javap     \
+	com/sun/tools/jdeps	\
 	com/sun/tools/corba     \
 	com/sun/tools/internal/xjc       \
 	com/sun/tools/internal/ws       \
--- a/jdk/makefiles/Images.gmk	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/makefiles/Images.gmk	Wed Jul 05 18:35:53 2017 +0200
@@ -100,6 +100,7 @@
 	javadoc$(EXE_SUFFIX) \
 	javah$(EXE_SUFFIX) \
 	javap$(EXE_SUFFIX) \
+	jdeps$(EXE_SUFFIX) \
 	jcmd$(EXE_SUFFIX) \
 	jdb$(EXE_SUFFIX) \
 	jps$(EXE_SUFFIX) \
--- a/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -30,6 +30,7 @@
 import javax.crypto.*;
 import javax.crypto.spec.*;
 import javax.crypto.BadPaddingException;
+import java.nio.ByteBuffer;
 
 /**
  * This class implements the AES algorithm in its various modes
@@ -127,6 +128,21 @@
             super(32, "CFB", "NOPADDING");
         }
     }
+    public static final class AES128_GCM_NoPadding extends OidImpl {
+        public AES128_GCM_NoPadding() {
+            super(16, "GCM", "NOPADDING");
+        }
+    }
+    public static final class AES192_GCM_NoPadding extends OidImpl {
+        public AES192_GCM_NoPadding() {
+            super(24, "GCM", "NOPADDING");
+        }
+    }
+    public static final class AES256_GCM_NoPadding extends OidImpl {
+        public AES256_GCM_NoPadding() {
+            super(32, "GCM", "NOPADDING");
+        }
+    }
 
     // utility method used by AESCipher and AESWrapCipher
     static final void checkKeySize(Key key, int fixedKeySize)
@@ -531,4 +547,79 @@
         return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
                            wrappedKeyType);
     }
+
+    /**
+     * Continues a multi-part update of the Additional Authentication
+     * Data (AAD), using a subset of the provided buffer.
+     * <p>
+     * Calls to this method provide AAD to the cipher when operating in
+     * modes such as AEAD (GCM/CCM).  If this cipher is operating in
+     * either GCM or CCM mode, all AAD must be supplied before beginning
+     * operations on the ciphertext (via the {@code update} and {@code
+     * doFinal} methods).
+     *
+     * @param src the buffer containing the AAD
+     * @param offset the offset in {@code src} where the AAD input starts
+     * @param len the number of AAD bytes
+     *
+     * @throws IllegalStateException if this cipher is in a wrong state
+     * (e.g., has not been initialized), does not accept AAD, or if
+     * operating in either GCM or CCM mode and one of the {@code update}
+     * methods has already been called for the active
+     * encryption/decryption operation
+     * @throws UnsupportedOperationException if this method
+     * has not been overridden by an implementation
+     *
+     * @since 1.8
+     */
+    @Override
+    protected void engineUpdateAAD(byte[] src, int offset, int len) {
+        core.updateAAD(src, offset, len);
+    }
+
+    /**
+     * Continues a multi-part update of the Additional Authentication
+     * Data (AAD).
+     * <p>
+     * Calls to this method provide AAD to the cipher when operating in
+     * modes such as AEAD (GCM/CCM).  If this cipher is operating in
+     * either GCM or CCM mode, all AAD must be supplied before beginning
+     * operations on the ciphertext (via the {@code update} and {@code
+     * doFinal} methods).
+     * <p>
+     * All {@code src.remaining()} bytes starting at
+     * {@code src.position()} are processed.
+     * Upon return, the input buffer's position will be equal
+     * to its limit; its limit will not have changed.
+     *
+     * @param src the buffer containing the AAD
+     *
+     * @throws IllegalStateException if this cipher is in a wrong state
+     * (e.g., has not been initialized), does not accept AAD, or if
+     * operating in either GCM or CCM mode and one of the {@code update}
+     * methods has already been called for the active
+     * encryption/decryption operation
+     * @throws UnsupportedOperationException if this method
+     * has not been overridden by an implementation
+     *
+     * @since 1.8
+     */
+    @Override
+    protected void engineUpdateAAD(ByteBuffer src) {
+        if (src != null) {
+            int aadLen = src.limit() - src.position();
+            if (aadLen != 0) {
+                if (src.hasArray()) {
+                    int aadOfs = src.arrayOffset() + src.position();
+                    core.updateAAD(src.array(), aadOfs, aadLen);
+                    src.position(src.limit());
+                } else {
+                    byte[] aad = new byte[aadLen];
+                    src.get(aad);
+                    core.updateAAD(aad, 0, aadLen);
+                }
+            }
+        }
+    }
 }
+
--- a/jdk/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -106,7 +106,7 @@
         SecretKeySpec aesKey = null;
 
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         byte[] keyBytes = new byte[keySize];
--- a/jdk/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -104,7 +104,7 @@
      */
     protected SecretKey engineGenerateKey() {
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         byte[] keyBytes = new byte[this.keysize];
--- a/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.util.Arrays;
 import java.util.Locale;
 
 import java.security.*;
@@ -59,7 +60,7 @@
     private byte[] buffer = null;
 
     /*
-     * internal buffer
+     * block size of cipher in bytes
      */
     private int blockSize = 0;
 
@@ -76,10 +77,12 @@
     /*
      * minimum number of bytes in the buffer required for
      * FeedbackCipher.encryptFinal()/decryptFinal() call.
-     * update() must buffer this many bytes before before starting
+     * update() must buffer this many bytes before starting
      * to encrypt/decrypt data.
-     * currently, only CTS mode has a non-zero value due to its special
-     * handling on the last two blocks (the last one may be incomplete).
+     * currently, only the following cases have non-zero values:
+     * 1) CTS mode - due to its special handling on the last two blocks
+     * (the last one may be incomplete).
+     * 2) GCM mode + decryption - due to its trailing tag bytes
      */
     private int minBytes = 0;
 
@@ -121,6 +124,24 @@
     private static final int PCBC_MODE = 4;
     private static final int CTR_MODE = 5;
     private static final int CTS_MODE = 6;
+    private static final int GCM_MODE = 7;
+
+    /*
+     * variables used for performing the GCM (key+iv) uniqueness check.
+     * To use GCM mode safely, the cipher object must be re-initialized
+     * with a different combination of key + iv values for each
+     * encryption operation. However, checking all past key + iv values
+     * isn't feasible. Thus, we only do a per-instance check of the
+     * key + iv values used in previous encryption.
+     * For decryption operations, no checking is necessary.
+     * NOTE: this key+iv check have to be done inside CipherCore class
+     * since CipherCore class buffers potential tag bytes in GCM mode
+     * and may not call GaloisCounterMode when there isn't sufficient
+     * input to process.
+     */
+    private boolean requireReinit = false;
+    private byte[] lastEncKey = null;
+    private byte[] lastEncIv = null;
 
     /**
      * Creates an instance of CipherCore with default ECB mode and
@@ -149,7 +170,7 @@
      * @param mode the cipher mode
      *
      * @exception NoSuchAlgorithmException if the requested cipher mode does
-     * not exist
+     * not exist for this cipher
      */
     void setMode(String mode) throws NoSuchAlgorithmException {
         if (mode == null)
@@ -165,30 +186,34 @@
         if (modeUpperCase.equals("CBC")) {
             cipherMode = CBC_MODE;
             cipher = new CipherBlockChaining(rawImpl);
-        }
-        else if (modeUpperCase.equals("CTS")) {
+        } else if (modeUpperCase.equals("CTS")) {
             cipherMode = CTS_MODE;
             cipher = new CipherTextStealing(rawImpl);
             minBytes = blockSize+1;
             padding = null;
-        }
-        else if (modeUpperCase.equals("CTR")) {
+        } else if (modeUpperCase.equals("CTR")) {
             cipherMode = CTR_MODE;
             cipher = new CounterMode(rawImpl);
             unitBytes = 1;
             padding = null;
-        }
-        else if (modeUpperCase.startsWith("CFB")) {
+        }  else if (modeUpperCase.startsWith("GCM")) {
+            // can only be used for block ciphers w/ 128-bit block size
+            if (blockSize != 16) {
+                throw new NoSuchAlgorithmException
+                    ("GCM mode can only be used for AES cipher");
+            }
+            cipherMode = GCM_MODE;
+            cipher = new GaloisCounterMode(rawImpl);
+            padding = null;
+        } else if (modeUpperCase.startsWith("CFB")) {
             cipherMode = CFB_MODE;
             unitBytes = getNumOfUnit(mode, "CFB".length(), blockSize);
             cipher = new CipherFeedback(rawImpl, unitBytes);
-        }
-        else if (modeUpperCase.startsWith("OFB")) {
+        } else if (modeUpperCase.startsWith("OFB")) {
             cipherMode = OFB_MODE;
             unitBytes = getNumOfUnit(mode, "OFB".length(), blockSize);
             cipher = new OutputFeedback(rawImpl, unitBytes);
-        }
-        else if (modeUpperCase.equals("PCBC")) {
+        } else if (modeUpperCase.equals("PCBC")) {
             cipherMode = PCBC_MODE;
             cipher = new PCBC(rawImpl);
         }
@@ -219,6 +244,7 @@
         return result;
     }
 
+
     /**
      * Sets the padding mechanism of this cipher.
      *
@@ -242,11 +268,27 @@
                                              + " not implemented");
         }
         if ((padding != null) &&
-            ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE))) {
+            ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE)
+             || (cipherMode == GCM_MODE))) {
             padding = null;
-            throw new NoSuchPaddingException
-                ((cipherMode == CTR_MODE? "CTR":"CTS") +
-                 " mode must be used with NoPadding");
+            String modeStr = null;
+            switch (cipherMode) {
+            case CTR_MODE:
+                modeStr = "CTR";
+                break;
+            case GCM_MODE:
+                modeStr = "GCM";
+                break;
+            case CTS_MODE:
+                modeStr = "CTS";
+                break;
+            default:
+                // should never happen
+            }
+            if (modeStr != null) {
+                throw new NoSuchPaddingException
+                    (modeStr + " mode must be used with NoPadding");
+            }
         }
     }
 
@@ -257,7 +299,7 @@
      * <code>inputLen</code> (in bytes).
      *
      * <p>This call takes into account any unprocessed (buffered) data from a
-     * previous <code>update</code> call, and padding.
+     * previous <code>update</code> call, padding, and AEAD tagging.
      *
      * <p>The actual output length of the next <code>update</code> or
      * <code>doFinal</code> call may be smaller than the length returned by
@@ -270,23 +312,60 @@
     int getOutputSize(int inputLen) {
         int totalLen = buffered + inputLen;
 
-        if (padding == null)
-            return totalLen;
+        // GCM: this call may be for either update() or doFinal(), so have to
+        // return the larger value of both
+        // Encryption: based on doFinal value: inputLen + tag
+        // Decryption: based on update value: inputLen
+        if (!decrypting && (cipherMode == GCM_MODE)) {
+            return (totalLen + ((GaloisCounterMode) cipher).getTagLen());
+        }
 
-        if (decrypting)
+        if (padding == null) {
             return totalLen;
+        }
+
+        if (decrypting) {
+            return totalLen;
+        }
 
         if (unitBytes != blockSize) {
-            if (totalLen < diffBlocksize)
+            if (totalLen < diffBlocksize) {
                 return diffBlocksize;
-            else
+            } else {
                 return (totalLen + blockSize -
                         ((totalLen - diffBlocksize) % blockSize));
+            }
         } else {
             return totalLen + padding.padLength(totalLen);
         }
     }
 
+    private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
+        int totalLen = 0;
+        switch (cipherMode) {
+        case GCM_MODE:
+            totalLen = buffered + inputLen;
+            if (isDoFinal) {
+                int tagLen = ((GaloisCounterMode) cipher).getTagLen();
+                if (decrypting) {
+                    // need to get the actual value from cipher??
+                    // deduct tagLen
+                    totalLen -= tagLen;
+                } else {
+                    totalLen += tagLen;
+                }
+            }
+            if (totalLen < 0) {
+                totalLen = 0;
+            }
+            break;
+        default:
+             totalLen  = getOutputSize(inputLen);
+             break;
+        }
+        return totalLen;
+    }
+
     /**
      * Returns the initialization vector (IV) in a new buffer.
      *
@@ -318,34 +397,49 @@
      * does not use any parameters.
      */
     AlgorithmParameters getParameters(String algName) {
+        if (cipherMode == ECB_MODE) {
+            return null;
+        }
         AlgorithmParameters params = null;
-        if (cipherMode == ECB_MODE) return null;
+        AlgorithmParameterSpec spec;
         byte[] iv = getIV();
-        if (iv != null) {
-            AlgorithmParameterSpec ivSpec;
-            if (algName.equals("RC2")) {
-                RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
-                ivSpec = new RC2ParameterSpec(rawImpl.getEffectiveKeyBits(),
-                                              iv);
+        if (iv == null) {
+            // generate spec using default value
+            if (cipherMode == GCM_MODE) {
+                iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
             } else {
-                ivSpec = new IvParameterSpec(iv);
+                iv = new byte[blockSize];
             }
-            try {
-                params = AlgorithmParameters.getInstance(algName, "SunJCE");
-            } catch (NoSuchAlgorithmException nsae) {
-                // should never happen
-                throw new RuntimeException("Cannot find " + algName +
-                    " AlgorithmParameters implementation in SunJCE provider");
-            } catch (NoSuchProviderException nspe) {
-                // should never happen
-                throw new RuntimeException("Cannot find SunJCE provider");
-            }
-            try {
-                params.init(ivSpec);
-            } catch (InvalidParameterSpecException ipse) {
-                // should never happen
-                throw new RuntimeException("IvParameterSpec not supported");
-            }
+            SunJCE.getRandom().nextBytes(iv);
+        }
+        if (cipherMode == GCM_MODE) {
+            algName = "GCM";
+            spec = new GCMParameterSpec
+                (((GaloisCounterMode) cipher).getTagLen()*8, iv);
+        } else {
+           if (algName.equals("RC2")) {
+               RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
+               spec = new RC2ParameterSpec
+                   (rawImpl.getEffectiveKeyBits(), iv);
+           } else {
+               spec = new IvParameterSpec(iv);
+           }
+        }
+        try {
+            params = AlgorithmParameters.getInstance(algName, "SunJCE");
+        } catch (NoSuchAlgorithmException nsae) {
+            // should never happen
+            throw new RuntimeException("Cannot find " + algName +
+                " AlgorithmParameters implementation in SunJCE provider");
+        } catch (NoSuchProviderException nspe) {
+            // should never happen
+            throw new RuntimeException("Cannot find SunJCE provider");
+        }
+        try {
+            params.init(spec);
+        } catch (InvalidParameterSpecException ipse) {
+            // should never happen
+            throw new RuntimeException(spec.getClass() + " not supported");
         }
         return params;
     }
@@ -420,44 +514,63 @@
                   || (opmode == Cipher.UNWRAP_MODE);
 
         byte[] keyBytes = getKeyBytes(key);
-
-        byte[] ivBytes;
-        if (params == null) {
-            ivBytes = null;
-        } else if (params instanceof IvParameterSpec) {
-            ivBytes = ((IvParameterSpec)params).getIV();
-            if ((ivBytes == null) || (ivBytes.length != blockSize)) {
-                throw new InvalidAlgorithmParameterException
-                    ("Wrong IV length: must be " + blockSize +
-                    " bytes long");
+        int tagLen = -1;
+        byte[] ivBytes = null;
+        if (params != null) {
+            if (cipherMode == GCM_MODE) {
+                if (params instanceof GCMParameterSpec) {
+                    tagLen = ((GCMParameterSpec)params).getTLen();
+                    if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
+                        throw new InvalidAlgorithmParameterException
+                            ("Unsupported TLen value; must be one of " +
+                             "{128, 120, 112, 104, 96}");
+                    }
+                    tagLen = tagLen >> 3;
+                    ivBytes = ((GCMParameterSpec)params).getIV();
+                } else {
+                    throw new InvalidAlgorithmParameterException
+                        ("Unsupported parameter: " + params);
+               }
+            } else {
+                if (params instanceof IvParameterSpec) {
+                    ivBytes = ((IvParameterSpec)params).getIV();
+                    if ((ivBytes == null) || (ivBytes.length != blockSize)) {
+                        throw new InvalidAlgorithmParameterException
+                            ("Wrong IV length: must be " + blockSize +
+                             " bytes long");
+                    }
+                } else if (params instanceof RC2ParameterSpec) {
+                    ivBytes = ((RC2ParameterSpec)params).getIV();
+                    if ((ivBytes != null) && (ivBytes.length != blockSize)) {
+                        throw new InvalidAlgorithmParameterException
+                            ("Wrong IV length: must be " + blockSize +
+                             " bytes long");
+                    }
+                } else {
+                    throw new InvalidAlgorithmParameterException
+                        ("Unsupported parameter: " + params);
+                }
             }
-        } else if (params instanceof RC2ParameterSpec) {
-            ivBytes = ((RC2ParameterSpec)params).getIV();
-            if ((ivBytes != null) && (ivBytes.length != blockSize)) {
-                throw new InvalidAlgorithmParameterException
-                    ("Wrong IV length: must be " + blockSize +
-                    " bytes long");
-            }
-        } else {
-            throw new InvalidAlgorithmParameterException("Wrong parameter "
-                                                         + "type: IV "
-                                                         + "expected");
         }
-
         if (cipherMode == ECB_MODE) {
             if (ivBytes != null) {
                 throw new InvalidAlgorithmParameterException
                                                 ("ECB mode cannot use IV");
             }
-        } else if (ivBytes == null) {
+        } else if (ivBytes == null)  {
             if (decrypting) {
                 throw new InvalidAlgorithmParameterException("Parameters "
                                                              + "missing");
             }
+
             if (random == null) {
-                random = SunJCE.RANDOM;
+                random = SunJCE.getRandom();
             }
-            ivBytes = new byte[blockSize];
+            if (cipherMode == GCM_MODE) {
+                ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
+            } else {
+                ivBytes = new byte[blockSize];
+            }
             random.nextBytes(ivBytes);
         }
 
@@ -466,23 +579,57 @@
 
         String algorithm = key.getAlgorithm();
 
-        cipher.init(decrypting, algorithm, keyBytes, ivBytes);
+        // GCM mode needs additional handling
+        if (cipherMode == GCM_MODE) {
+            if(tagLen == -1) {
+                tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
+            }
+            if (decrypting) {
+                minBytes = tagLen;
+            } else {
+                // check key+iv for encryption in GCM mode
+                requireReinit =
+                    Arrays.equals(ivBytes, lastEncIv) &&
+                    Arrays.equals(keyBytes, lastEncKey);
+                if (requireReinit) {
+                    throw new InvalidAlgorithmParameterException
+                        ("Cannot reuse iv for GCM encryption");
+                }
+                lastEncIv = ivBytes;
+                lastEncKey = keyBytes;
+            }
+            ((GaloisCounterMode) cipher).init
+                (decrypting, algorithm, keyBytes, ivBytes, tagLen);
+        } else {
+            cipher.init(decrypting, algorithm, keyBytes, ivBytes);
+        }
+        // skip checking key+iv from now on until after doFinal()
+        requireReinit = false;
     }
 
     void init(int opmode, Key key, AlgorithmParameters params,
               SecureRandom random)
         throws InvalidKeyException, InvalidAlgorithmParameterException {
-        IvParameterSpec ivSpec = null;
+        AlgorithmParameterSpec spec = null;
+        String paramType = null;
         if (params != null) {
             try {
-                ivSpec = params.getParameterSpec(IvParameterSpec.class);
+                if (cipherMode == GCM_MODE) {
+                    paramType = "GCM";
+                    spec = params.getParameterSpec(GCMParameterSpec.class);
+                } else {
+                    // NOTE: RC2 parameters are always handled through
+                    // init(..., AlgorithmParameterSpec,...) method, so
+                    // we can assume IvParameterSpec type here.
+                    paramType = "IV";
+                    spec = params.getParameterSpec(IvParameterSpec.class);
+                }
             } catch (InvalidParameterSpecException ipse) {
-                throw new InvalidAlgorithmParameterException("Wrong parameter "
-                                                             + "type: IV "
-                                                             + "expected");
+                throw new InvalidAlgorithmParameterException
+                    ("Wrong parameter type: " + paramType + " expected");
             }
         }
-        init(opmode, key, ivSpec, random);
+        init(opmode, key, spec, random);
     }
 
     /**
@@ -504,6 +651,7 @@
         return keyBytes;
     }
 
+
     /**
      * Continues a multiple-part encryption or decryption operation
      * (depending on how this cipher was initialized), processing another data
@@ -524,22 +672,25 @@
      * (e.g., has not been initialized)
      */
     byte[] update(byte[] input, int inputOffset, int inputLen) {
+        if (requireReinit) {
+            throw new IllegalStateException
+                ("Must use either different key or iv for GCM encryption");
+        }
+
         byte[] output = null;
-        byte[] out = null;
         try {
-            output = new byte[getOutputSize(inputLen)];
+            output = new byte[getOutputSizeByOperation(inputLen, false)];
             int len = update(input, inputOffset, inputLen, output,
                              0);
             if (len == output.length) {
-                out = output;
+                return output;
             } else {
-                out = new byte[len];
-                System.arraycopy(output, 0, out, 0, len);
+                return Arrays.copyOf(output, len);
             }
         } catch (ShortBufferException e) {
-            // never thrown
+            // should never happen
+            throw new ProviderException("Unexpected exception", e);
         }
-        return out;
     }
 
     /**
@@ -567,6 +718,11 @@
      */
     int update(byte[] input, int inputOffset, int inputLen, byte[] output,
                int outputOffset) throws ShortBufferException {
+        if (requireReinit) {
+            throw new IllegalStateException
+                ("Must use either different key or iv for GCM encryption");
+        }
+
         // figure out how much can be sent to crypto function
         int len = buffered + inputLen - minBytes;
         if (padding != null && decrypting) {
@@ -582,6 +738,7 @@
                                            + "(at least) " + len
                                            + " bytes long");
         }
+
         if (len != 0) {
             // there is some work to do
             byte[] in = new byte[len];
@@ -600,7 +757,6 @@
                 System.arraycopy(input, inputOffset, in,
                                  bufferedConsumed, inputConsumed);
             }
-
             if (decrypting) {
                 cipher.decrypt(in, 0, len, output, outputOffset);
             } else {
@@ -611,11 +767,12 @@
             // the total input length a multiple of blocksize when
             // padding is applied
             if (unitBytes != blockSize) {
-                if (len < diffBlocksize)
+                if (len < diffBlocksize) {
                     diffBlocksize -= len;
-                else
+                } else {
                     diffBlocksize = blockSize -
                         ((len - diffBlocksize) % blockSize);
+                }
             }
 
             inputLen -= inputConsumed;
@@ -669,21 +826,18 @@
     byte[] doFinal(byte[] input, int inputOffset, int inputLen)
         throws IllegalBlockSizeException, BadPaddingException {
         byte[] output = null;
-        byte[] out = null;
         try {
-            output = new byte[getOutputSize(inputLen)];
+            output = new byte[getOutputSizeByOperation(inputLen, true)];
             int len = doFinal(input, inputOffset, inputLen, output, 0);
             if (len < output.length) {
-                out = new byte[len];
-                if (len != 0)
-                    System.arraycopy(output, 0, out, 0, len);
+                return Arrays.copyOf(output, len);
             } else {
-                out = output;
+                return output;
             }
         } catch (ShortBufferException e) {
             // never thrown
+            throw new ProviderException("Unexpected exception", e);
         }
-        return out;
     }
 
     /**
@@ -726,6 +880,10 @@
                 int outputOffset)
         throws IllegalBlockSizeException, ShortBufferException,
                BadPaddingException {
+        if (requireReinit) {
+            throw new IllegalStateException
+                ("Must use either different key or iv for GCM encryption");
+        }
 
         // calculate the total input length
         int totalLen = buffered + inputLen;
@@ -752,8 +910,9 @@
         }
 
         // if encrypting and padding not null, add padding
-        if (!decrypting && padding != null)
+        if (!decrypting && padding != null) {
             paddedLen += paddingLen;
+        }
 
         // check output buffer capacity.
         // if we are decrypting with padding applied, we can perform this
@@ -763,8 +922,8 @@
             throw new ShortBufferException("Output buffer is null");
         }
         int outputCapacity = output.length - outputOffset;
-        if (((!decrypting) || (padding == null)) &&
-            (outputCapacity < paddedLen) ||
+
+        if (((!decrypting) && (outputCapacity < paddedLen)) ||
             (decrypting && (outputCapacity < (paddedLen - blockSize)))) {
             throw new ShortBufferException("Output buffer too short: "
                                            + outputCapacity + " bytes given, "
@@ -812,6 +971,7 @@
                 }
                 totalLen = padStart;
             }
+
             if ((output.length - outputOffset) < totalLen) {
                 // restore so users can retry with a larger buffer
                 cipher.restore();
@@ -824,8 +984,13 @@
                 output[outputOffset + i] = outWithPadding[i];
             }
         } else { // encrypting
-            totalLen = finalNoPadding(finalBuf, finalOffset, output,
-                                      outputOffset, paddedLen);
+            try {
+                totalLen = finalNoPadding(finalBuf, finalOffset, output,
+                                          outputOffset, paddedLen);
+            } finally {
+                // reset after doFinal() for GCM encryption
+                requireReinit = (cipherMode == GCM_MODE);
+            }
         }
 
         buffered = 0;
@@ -836,33 +1001,33 @@
         return totalLen;
     }
 
-    private int finalNoPadding(byte[] in, int inOff, byte[] out, int outOff,
+    private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,
                                int len)
-        throws IllegalBlockSizeException
-    {
-        if (in == null || len == 0)
-            return 0;
+        throws IllegalBlockSizeException, AEADBadTagException {
 
-        if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE)
-            && ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
-            if (padding != null) {
-                throw new IllegalBlockSizeException
-                    ("Input length (with padding) not multiple of " +
-                     unitBytes + " bytes");
-            } else {
-                throw new IllegalBlockSizeException
-                    ("Input length not multiple of " + unitBytes
-                     + " bytes");
-            }
+        if ((cipherMode != GCM_MODE) && (in == null || len == 0)) {
+            return 0;
         }
-
+        if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) &&
+            (cipherMode != GCM_MODE) &&
+            ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
+                if (padding != null) {
+                    throw new IllegalBlockSizeException
+                        ("Input length (with padding) not multiple of " +
+                         unitBytes + " bytes");
+                } else {
+                    throw new IllegalBlockSizeException
+                        ("Input length not multiple of " + unitBytes
+                         + " bytes");
+                }
+        }
+        int outLen = 0;
         if (decrypting) {
-            cipher.decryptFinal(in, inOff, len, out, outOff);
+            outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs);
         } else {
-            cipher.encryptFinal(in, inOff, len, out, outOff);
+            outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs);
         }
-
-        return len;
+        return outLen;
     }
 
     // Note: Wrap() and Unwrap() are the same in
@@ -939,4 +1104,36 @@
         return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
                                           wrappedKeyType);
     }
+
+    /**
+     * Continues a multi-part update of the Additional Authentication
+     * Data (AAD), using a subset of the provided buffer.
+     * <p>
+     * Calls to this method provide AAD to the cipher when operating in
+     * modes such as AEAD (GCM/CCM).  If this cipher is operating in
+     * either GCM or CCM mode, all AAD must be supplied before beginning
+     * operations on the ciphertext (via the {@code update} and {@code
+     * doFinal} methods).
+     *
+     * @param src the buffer containing the AAD
+     * @param offset the offset in {@code src} where the AAD input starts
+     * @param len the number of AAD bytes
+     *
+     * @throws IllegalStateException if this cipher is in a wrong state
+     * (e.g., has not been initialized), does not accept AAD, or if
+     * operating in either GCM or CCM mode and one of the {@code update}
+     * methods has already been called for the active
+     * encryption/decryption operation
+     * @throws UnsupportedOperationException if this method
+     * has not been overridden by an implementation
+     *
+     * @since 1.8
+     */
+    void updateAAD(byte[] src, int offset, int len) {
+        if (requireReinit) {
+            throw new IllegalStateException
+                ("Must use either different key or iv for GCM encryption");
+        }
+        cipher.updateAAD(src, offset, len);
+    }
 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -83,9 +83,10 @@
      * @param plainLen the length of the input data
      * @param cipher the buffer for the result
      * @param cipherOffset the offset in <code>cipher</code>
+     * @return the number of bytes placed into <code>cipher</code>
      */
-    void encryptFinal(byte[] plain, int plainOffset, int plainLen,
-                      byte[] cipher, int cipherOffset)
+    int encryptFinal(byte[] plain, int plainOffset, int plainLen,
+                     byte[] cipher, int cipherOffset)
         throws IllegalBlockSizeException {
 
         if (plainLen < blockSize) {
@@ -134,6 +135,7 @@
                 embeddedCipher.encryptBlock(tmp2, 0, cipher, cipherOffset);
             }
         }
+        return plainLen;
     }
 
     /**
@@ -158,9 +160,10 @@
      * @param cipherLen the length of the input data
      * @param plain the buffer for the result
      * @param plainOffset the offset in <code>plain</code>
+     * @return the number of bytes placed into <code>plain</code>
      */
-    void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
-                      byte[] plain, int plainOffset)
+    int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
+                     byte[] plain, int plainOffset)
         throws IllegalBlockSizeException {
         if (cipherLen < blockSize) {
             throw new IllegalBlockSizeException("input is too short!");
@@ -211,5 +214,6 @@
                 }
             }
         }
+        return cipherLen;
     }
 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -102,7 +102,7 @@
         DESKey desKey = null;
 
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         try {
--- a/jdk/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -105,7 +105,7 @@
      */
     protected SecretKey engineGenerateKey() {
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         byte[] rawkey = new byte[DESedeKeySpec.DES_EDE_KEY_LEN];
--- a/jdk/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -217,7 +217,7 @@
             if (params == null) {
                 iv = new byte[8];
                 if (random == null) {
-                    random = SunJCE.RANDOM;
+                    random = SunJCE.getRandom();
                 }
                 random.nextBytes(iv);
             }
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -140,7 +140,7 @@
      */
     public KeyPair generateKeyPair() {
         if (random == null) {
-            random = SunJCE.RANDOM;
+            random = SunJCE.getRandom();
         }
 
         if (params == null) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -131,7 +131,7 @@
         }
 
         if (this.random == null)
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
 
         try {
             AlgorithmParameterGenerator paramGen;
--- a/jdk/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -26,7 +26,7 @@
 package com.sun.crypto.provider;
 
 import java.security.InvalidKeyException;
-import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.*;
 
 /**
  * This class represents a block cipher in one of its modes. It wraps
@@ -150,11 +150,13 @@
      * @param plainLen the length of the input data
      * @param cipher the buffer for the encryption result
      * @param cipherOffset the offset in <code>cipher</code>
+     * @return the number of bytes placed into <code>cipher</code>
      */
-     void encryptFinal(byte[] plain, int plainOffset, int plainLen,
-                       byte[] cipher, int cipherOffset)
+     int encryptFinal(byte[] plain, int plainOffset, int plainLen,
+                      byte[] cipher, int cipherOffset)
          throws IllegalBlockSizeException {
          encrypt(plain, plainOffset, plainLen, cipher, cipherOffset);
+         return plainLen;
      }
     /**
      * Performs decryption operation.
@@ -190,10 +192,40 @@
      * @param cipherLen the length of the input data
      * @param plain the buffer for the decryption result
      * @param plainOffset the offset in <code>plain</code>
+     * @return the number of bytes placed into <code>plain</code>
      */
-     void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
-                       byte[] plain, int plainOffset)
-         throws IllegalBlockSizeException {
+     int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
+                      byte[] plain, int plainOffset)
+         throws IllegalBlockSizeException, AEADBadTagException {
          decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset);
+         return cipherLen;
      }
+
+    /**
+     * Continues a multi-part update of the Additional Authentication
+     * Data (AAD), using a subset of the provided buffer. If this
+     * cipher is operating in either GCM or CCM mode, all AAD must be
+     * supplied before beginning operations on the ciphertext (via the
+     * {@code update} and {@code doFinal} methods).
+     * <p>
+     * NOTE: Given most modes do not accept AAD, default impl for this
+     * method throws IllegalStateException.
+     *
+     * @param src the buffer containing the AAD
+     * @param offset the offset in {@code src} where the AAD input starts
+     * @param len the number of AAD bytes
+     *
+     * @throws IllegalStateException if this cipher is in a wrong state
+     * (e.g., has not been initialized), does not accept AAD, or if
+     * operating in either GCM or CCM mode and one of the {@code update}
+     * methods has already been called for the active
+     * encryption/decryption operation
+     * @throws UnsupportedOperationException if this method
+     * has not been overridden by an implementation
+     *
+     * @since 1.8
+     */
+    void updateAAD(byte[] src, int offset, int len) {
+        throw new IllegalStateException("No AAD accepted");
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/GCMParameters.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 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.io.IOException;
+import java.security.AlgorithmParametersSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import javax.crypto.spec.GCMParameterSpec;
+import sun.misc.HexDumpEncoder;
+import sun.security.util.*;
+
+/**
+ * This class implements the parameter set used with
+ * GCM encryption, which is defined in RFC 5084 as follows:
+ *
+ * <pre>
+ *    GCMParameters ::= SEQUENCE {
+ *      aes-iv      OCTET STRING, -- recommended size is 12 octets
+ *      aes-tLen    AES-GCM-ICVlen DEFAULT 12 }
+ *
+ *    AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
+ *
+ * </pre>
+ *
+ * @author Valerie Peng
+ * @since 1.8
+ */
+public final class GCMParameters extends AlgorithmParametersSpi {
+
+    // the iv
+    private byte[] iv;
+    // the tag length in bytes
+    private int tLen;
+
+    public GCMParameters() {}
+
+    protected void engineInit(AlgorithmParameterSpec paramSpec)
+        throws InvalidParameterSpecException {
+
+        if (!(paramSpec instanceof GCMParameterSpec)) {
+            throw new InvalidParameterSpecException
+                ("Inappropriate parameter specification");
+        }
+        GCMParameterSpec gps = (GCMParameterSpec) paramSpec;
+        // need to convert from bits to bytes for ASN.1 encoding
+        this.tLen = gps.getTLen()/8;
+        this.iv = gps.getIV();
+    }
+
+    protected void engineInit(byte[] encoded) throws IOException {
+        DerValue val = new DerValue(encoded);
+        // check if IV or params
+        if (val.tag == DerValue.tag_Sequence) {
+            byte[] iv = val.data.getOctetString();
+            int tLen;
+            if (val.data.available() != 0) {
+                tLen = val.data.getInteger();
+                if (tLen < 12 || tLen > 16 ) {
+                    throw new IOException
+                        ("GCM parameter parsing error: unsupported tag len: " +
+                         tLen);
+                }
+                if (val.data.available() != 0) {
+                    throw new IOException
+                        ("GCM parameter parsing error: extra data");
+                }
+            } else {
+                tLen = 12;
+            }
+            this.iv = iv.clone();
+            this.tLen = tLen;
+        } else {
+            throw new IOException("GCM parameter parsing error: no SEQ tag");
+        }
+    }
+
+    protected void engineInit(byte[] encoded, String decodingMethod)
+        throws IOException {
+        engineInit(encoded);
+    }
+
+    protected <T extends AlgorithmParameterSpec>
+            T engineGetParameterSpec(Class<T> paramSpec)
+        throws InvalidParameterSpecException {
+
+        if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) {
+            return paramSpec.cast(new GCMParameterSpec(tLen * 8, iv));
+        } else {
+            throw new InvalidParameterSpecException
+                ("Inappropriate parameter specification");
+        }
+    }
+
+    protected byte[] engineGetEncoded() throws IOException {
+        DerOutputStream out = new DerOutputStream();
+        DerOutputStream bytes = new DerOutputStream();
+
+        bytes.putOctetString(iv);
+        bytes.putInteger(tLen);
+        out.write(DerValue.tag_Sequence, bytes);
+        return out.toByteArray();
+    }
+
+    protected byte[] engineGetEncoded(String encodingMethod)
+        throws IOException {
+        return engineGetEncoded();
+    }
+
+    /*
+     * Returns a formatted string describing the parameters.
+     */
+    protected String engineToString() {
+        String LINE_SEP = System.getProperty("line.separator");
+        HexDumpEncoder encoder = new HexDumpEncoder();
+        StringBuilder sb
+            = new StringBuilder(LINE_SEP + "    iv:" + LINE_SEP + "["
+                + encoder.encodeBuffer(iv) + "]");
+
+        sb.append(LINE_SEP + "tLen(bits):" + LINE_SEP + tLen*8 + LINE_SEP);
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * (C) Copyright IBM Corp. 2013
+ */
+
+package com.sun.crypto.provider;
+
+import java.security.*;
+import javax.crypto.*;
+import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
+
+/**
+ * This class represents the GCTR function defined in NIST 800-38D
+ * under section 6.5. It needs to be constructed w/ an initialized
+ * cipher object, and initial counter block(ICB). Given an input X
+ * of arbitrary length, it processes and returns an output which has
+ * the same length as X.
+ *
+ * <p>This function is used in the implementation of GCM mode.
+ *
+ * @since 1.8
+ */
+final class GCTR {
+
+    // these fields should not change after the object has been constructed
+    private final SymmetricCipher aes;
+    private final byte[] icb;
+
+    // the current counter value
+    private byte[] counter;
+
+    // needed for save/restore calls
+    private byte[] counterSave;
+
+    // NOTE: cipher should already be initialized
+    GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
+        this.aes = cipher;
+        this.icb = initialCounterBlk;
+        this.counter = icb.clone();
+    }
+
+    // input must be multiples of 128-bit blocks when calling update
+    int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
+        if (inLen - inOfs > in.length) {
+            throw new RuntimeException("input length out of bound");
+        }
+        if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) {
+            throw new RuntimeException("input length unsupported");
+        }
+        if (out.length - outOfs < inLen) {
+            throw new RuntimeException("output buffer too small");
+        }
+
+        byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
+
+        int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
+        for (int i = 0; i < numOfCompleteBlocks; i++) {
+            aes.encryptBlock(counter, 0, encryptedCntr, 0);
+            for (int n = 0; n < AES_BLOCK_SIZE; n++) {
+                int index = (i * AES_BLOCK_SIZE + n);
+                out[outOfs + index] =
+                    (byte) ((in[inOfs + index] ^ encryptedCntr[n]));
+            }
+            GaloisCounterMode.increment32(counter);
+        }
+        return inLen;
+    }
+
+    // input can be arbitrary size when calling doFinal
+    protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out,
+                          int outOfs) throws IllegalBlockSizeException {
+        try {
+            if (inLen < 0) {
+                throw new IllegalBlockSizeException("Negative input size!");
+            } else if (inLen > 0) {
+                int lastBlockSize = inLen % AES_BLOCK_SIZE;
+                // process the complete blocks first
+                update(in, inOfs, inLen - lastBlockSize, out, outOfs);
+                if (lastBlockSize != 0) {
+                    // do the last partial block
+                    byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
+                    aes.encryptBlock(counter, 0, encryptedCntr, 0);
+
+                    int processed = inLen - lastBlockSize;
+                    for (int n = 0; n < lastBlockSize; n++) {
+                        out[outOfs + processed + n] =
+                            (byte) ((in[inOfs + processed + n] ^
+                                     encryptedCntr[n]));
+                    }
+                }
+            }
+        } finally {
+            reset();
+        }
+        return inLen;
+    }
+
+    /**
+     * Resets the current counter to its initial value.
+     * This is used after the doFinal() is called so this object can be
+     * reused w/o explicit re-initialization.
+     */
+    void reset() {
+        System.arraycopy(icb, 0, counter, 0, icb.length);
+    }
+
+    /**
+     * Save the current content of this object.
+     */
+    void save() {
+        this.counterSave = this.counter.clone();
+    }
+
+    /**
+     * Restores the content of this object to the previous saved one.
+     */
+    void restore() {
+        this.counter = this.counterSave;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/GHASH.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 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.
+ */
+/*
+ * (C) Copyright IBM Corp. 2013
+ */
+
+package com.sun.crypto.provider;
+
+import java.util.Arrays;
+import java.security.*;
+import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
+
+/**
+ * This class represents the GHASH function defined in NIST 800-38D
+ * under section 6.4. It needs to be constructed w/ a hash subkey, i.e.
+ * block H. Given input of 128-bit blocks, it will process and output
+ * a 128-bit block.
+ *
+ * <p>This function is used in the implementation of GCM mode.
+ *
+ * @since 1.8
+ */
+final class GHASH {
+
+    private static final byte P128 = (byte) 0xe1; //reduction polynomial
+
+    private static boolean getBit(byte[] b, int pos) {
+        int p = pos / 8;
+        pos %= 8;
+        int i = (b[p] >>> (7 - pos)) & 1;
+        return i != 0;
+    }
+
+    private static void shift(byte[] b) {
+        byte temp, temp2;
+        temp2 = 0;
+        for (int i = 0; i < b.length; i++) {
+            temp = (byte) ((b[i] & 0x01) << 7);
+            b[i] = (byte) ((b[i] & 0xff) >>> 1);
+            b[i] = (byte) (b[i] | temp2);
+            temp2 = temp;
+        }
+    }
+
+    // Given block X and Y, returns the muliplication of X * Y
+    private static byte[] blockMult(byte[] x, byte[] y) {
+        if (x.length != AES_BLOCK_SIZE || y.length != AES_BLOCK_SIZE) {
+            throw new RuntimeException("illegal input sizes");
+        }
+        byte[] z = new byte[AES_BLOCK_SIZE];
+        byte[] v = y.clone();
+        // calculate Z1-Z127 and V1-V127
+        for (int i = 0; i < 127; i++) {
+            // Zi+1 = Zi if bit i of x is 0
+            if (getBit(x, i)) {
+                for (int n = 0; n < z.length; n++) {
+                    z[n] ^= v[n];
+                }
+            }
+            boolean lastBitOfV = getBit(v, 127);
+            shift(v);
+            if (lastBitOfV) v[0] ^= P128;
+        }
+        // calculate Z128
+        if (getBit(x, 127)) {
+            for (int n = 0; n < z.length; n++) {
+                z[n] ^= v[n];
+            }
+        }
+        return z;
+    }
+
+    // hash subkey H; should not change after the object has been constructed
+    private final byte[] subkeyH;
+
+    // buffer for storing hash
+    private byte[] state;
+
+    // variables for save/restore calls
+    private byte[] stateSave = null;
+
+    /**
+     * Initializes the cipher in the specified mode with the given key
+     * and iv.
+     *
+     * @param subkeyH the hash subkey
+     *
+     * @exception ProviderException if the given key is inappropriate for
+     * initializing this digest
+     */
+    GHASH(byte[] subkeyH) throws ProviderException {
+        if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) {
+            throw new ProviderException("Internal error");
+        }
+        this.subkeyH = subkeyH;
+        this.state = new byte[AES_BLOCK_SIZE];
+    }
+
+    /**
+     * Resets the GHASH object to its original state, i.e. blank w/
+     * the same subkey H. Used after digest() is called and to re-use
+     * this object for different data w/ the same H.
+     */
+    void reset() {
+        Arrays.fill(state, (byte) 0);
+    }
+
+    /**
+     * Save the current snapshot of this GHASH object.
+     */
+    void save() {
+        stateSave = state.clone();
+    }
+
+    /**
+     * Restores this object using the saved snapshot.
+     */
+    void restore() {
+        state = stateSave;
+    }
+
+    private void processBlock(byte[] data, int ofs) {
+        if (data.length - ofs < AES_BLOCK_SIZE) {
+            throw new RuntimeException("need complete block");
+        }
+        for (int n = 0; n < state.length; n++) {
+            state[n] ^= data[ofs + n];
+        }
+        state = blockMult(state, subkeyH);
+    }
+
+    void update(byte[] in) {
+        update(in, 0, in.length);
+    }
+
+    void update(byte[] in, int inOfs, int inLen) {
+        if (inLen - inOfs > in.length) {
+            throw new RuntimeException("input length out of bound");
+        }
+        if (inLen % AES_BLOCK_SIZE != 0) {
+            throw new RuntimeException("input length unsupported");
+        }
+
+        for (int i = inOfs; i < (inOfs + inLen); i += AES_BLOCK_SIZE) {
+            processBlock(in, i);
+        }
+    }
+
+    byte[] digest() {
+        try {
+            return state.clone();
+        } finally {
+            reset();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 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.S
+ *
+ * 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.util.Arrays;
+import java.io.*;
+import java.security.*;
+import javax.crypto.*;
+import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
+
+/**
+ * This class represents ciphers in GaloisCounter (GCM) mode.
+ *
+ * <p>This mode currently should only be used w/ AES cipher.
+ * Although no checking is done here, caller should only
+ * pass AES Cipher to the constructor.
+ *
+ * <p>NOTE: This class does not deal with buffering or padding.
+ *
+ * @since 1.8
+ */
+final class GaloisCounterMode extends FeedbackCipher {
+
+    static int DEFAULT_TAG_LEN = AES_BLOCK_SIZE;
+    static int DEFAULT_IV_LEN = 12; // in bytes
+
+    // buffer for AAD data; if null, meaning update has been called
+    private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
+    private int sizeOfAAD = 0;
+
+    // in bytes; need to convert to bits (default value 128) when needed
+    private int tagLenBytes = DEFAULT_TAG_LEN;
+
+    // these following 2 fields can only be initialized after init() is
+    // called, e.g. after cipher key k is set, and STAY UNCHANGED
+    private byte[] subkeyH = null;
+    private byte[] preCounterBlock = null;
+
+    private GCTR gctrPAndC = null;
+    private GHASH ghashAllToS = null;
+
+    // length of total data, i.e. len(C)
+    private int processed = 0;
+
+    // additional variables for save/restore calls
+    private byte[] aadBufferSave = null;
+    private int sizeOfAADSave = 0;
+    private int processedSave = 0;
+
+    // value must be 16-byte long; used by GCTR and GHASH as well
+    static void increment32(byte[] value) {
+        if (value.length != AES_BLOCK_SIZE) {
+            throw new RuntimeException("Unexpected counter block length");
+        }
+        // start from last byte and only go over 4 bytes, i.e. total 32 bits
+        int n = value.length - 1;
+        while ((n >= value.length - 4) && (++value[n] == 0)) {
+            n--;
+        }
+    }
+
+    // ivLen in bits
+    private static byte[] getLengthBlock(int ivLen) {
+        byte[] out = new byte[AES_BLOCK_SIZE];
+        out[12] = (byte)(ivLen >>> 24);
+        out[13] = (byte)(ivLen >>> 16);
+        out[14] = (byte)(ivLen >>> 8);
+        out[15] = (byte)ivLen;
+        return out;
+    }
+
+    // aLen and cLen both in bits
+    private static byte[] getLengthBlock(int aLen, int cLen) {
+        byte[] out = new byte[AES_BLOCK_SIZE];
+        out[4] = (byte)(aLen >>> 24);
+        out[5] = (byte)(aLen >>> 16);
+        out[6] = (byte)(aLen >>> 8);
+        out[7] = (byte)aLen;
+        out[12] = (byte)(cLen >>> 24);
+        out[13] = (byte)(cLen >>> 16);
+        out[14] = (byte)(cLen >>> 8);
+        out[15] = (byte)cLen;
+        return out;
+    }
+
+    private static byte[] expandToOneBlock(byte[] in, int inOfs, int len) {
+        if (len > AES_BLOCK_SIZE) {
+            throw new ProviderException("input " + len + " too long");
+        }
+        if (len == AES_BLOCK_SIZE && inOfs == 0) {
+            return in;
+        } else {
+            byte[] paddedIn = new byte[AES_BLOCK_SIZE];
+            System.arraycopy(in, inOfs, paddedIn, 0, len);
+            return paddedIn;
+        }
+    }
+
+    private static byte[] getJ0(byte[] iv, byte[] subkeyH) {
+        byte[] j0;
+        if (iv.length == 12) { // 96 bits
+            j0 = expandToOneBlock(iv, 0, iv.length);
+            j0[AES_BLOCK_SIZE - 1] = 1;
+        } else {
+            GHASH g = new GHASH(subkeyH);
+            int lastLen = iv.length % AES_BLOCK_SIZE;
+            if (lastLen != 0) {
+                g.update(iv, 0, iv.length - lastLen);
+                byte[] padded =
+                    expandToOneBlock(iv, iv.length - lastLen, lastLen);
+                g.update(padded);
+            } else {
+                g.update(iv);
+            }
+            byte[] lengthBlock = getLengthBlock(iv.length*8);
+            g.update(lengthBlock);
+            j0 = g.digest();
+        }
+        return j0;
+    }
+
+    GaloisCounterMode(SymmetricCipher embeddedCipher) {
+        super(embeddedCipher);
+        aadBuffer = new ByteArrayOutputStream();
+    }
+
+    /**
+     * Gets the name of the feedback mechanism
+     *
+     * @return the name of the feedback mechanism
+     */
+    String getFeedback() {
+        return "GCM";
+    }
+
+    /**
+     * Resets the cipher object to its original state.
+     * This is used when doFinal is called in the Cipher class, so that the
+     * cipher can be reused (with its original key and iv).
+     */
+    void reset() {
+        if (aadBuffer == null) {
+            aadBuffer = new ByteArrayOutputStream();
+        } else {
+            aadBuffer.reset();
+        }
+        if (gctrPAndC != null) gctrPAndC.reset();
+        if (ghashAllToS != null) ghashAllToS.reset();
+        processed = 0;
+        sizeOfAAD = 0;
+    }
+
+    /**
+     * Save the current content of this cipher.
+     */
+    void save() {
+        processedSave = processed;
+        sizeOfAADSave = sizeOfAAD;
+        aadBufferSave =
+            ((aadBuffer == null || aadBuffer.size() == 0)?
+             null : aadBuffer.toByteArray());
+        if (gctrPAndC != null) gctrPAndC.save();
+        if (ghashAllToS != null) ghashAllToS.save();
+    }
+
+    /**
+     * Restores the content of this cipher to the previous saved one.
+     */
+    void restore() {
+        processed = processedSave;
+        sizeOfAAD = sizeOfAADSave;
+        if (aadBuffer != null) {
+            aadBuffer.reset();
+            if (aadBufferSave != null) {
+                aadBuffer.write(aadBufferSave, 0, aadBufferSave.length);
+            }
+        }
+       if (gctrPAndC != null) gctrPAndC.restore();
+       if (ghashAllToS != null) ghashAllToS.restore();
+    }
+
+    /**
+     * Initializes the cipher in the specified mode with the given key
+     * and iv.
+     *
+     * @param decrypting flag indicating encryption or decryption
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param iv the iv
+     * @param tagLenBytes the length of tag in bytes
+     *
+     * @exception InvalidKeyException if the given key is inappropriate for
+     * initializing this cipher
+     */
+    void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)
+            throws InvalidKeyException {
+        init(decrypting, algorithm, key, iv, DEFAULT_TAG_LEN);
+    }
+
+    /**
+     * Initializes the cipher in the specified mode with the given key
+     * and iv.
+     *
+     * @param decrypting flag indicating encryption or decryption
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param iv the iv
+     * @param tagLenBytes the length of tag in bytes
+     *
+     * @exception InvalidKeyException if the given key is inappropriate for
+     * initializing this cipher
+     */
+    void init(boolean decrypting, String algorithm, byte[] keyValue,
+              byte[] ivValue, int tagLenBytes)
+              throws InvalidKeyException {
+        if (keyValue == null || ivValue == null) {
+            throw new InvalidKeyException("Internal error");
+        }
+
+        // always encrypt mode for embedded cipher
+        this.embeddedCipher.init(false, algorithm, keyValue);
+        this.subkeyH = new byte[AES_BLOCK_SIZE];
+        this.embeddedCipher.encryptBlock(new byte[AES_BLOCK_SIZE], 0,
+                this.subkeyH, 0);
+
+        this.iv = ivValue.clone();
+        preCounterBlock = getJ0(iv, subkeyH);
+        byte[] j0Plus1 = preCounterBlock.clone();
+        increment32(j0Plus1);
+        gctrPAndC = new GCTR(embeddedCipher, j0Plus1);
+        ghashAllToS = new GHASH(subkeyH);
+
+        this.tagLenBytes = tagLenBytes;
+        if (aadBuffer == null) {
+            aadBuffer = new ByteArrayOutputStream();
+        } else {
+            aadBuffer.reset();
+        }
+        processed = 0;
+        sizeOfAAD = 0;
+    }
+
+    /**
+     * Continues a multi-part update of the Additional Authentication
+     * Data (AAD), using a subset of the provided buffer. If this
+     * cipher is operating in either GCM or CCM mode, all AAD must be
+     * supplied before beginning operations on the ciphertext (via the
+     * {@code update} and {@code doFinal} methods).
+     * <p>
+     * NOTE: Given most modes do not accept AAD, default impl for this
+     * method throws IllegalStateException.
+     *
+     * @param src the buffer containing the AAD
+     * @param offset the offset in {@code src} where the AAD input starts
+     * @param len the number of AAD bytes
+     *
+     * @throws IllegalStateException if this cipher is in a wrong state
+     * (e.g., has not been initialized), does not accept AAD, or if
+     * operating in either GCM or CCM mode and one of the {@code update}
+     * methods has already been called for the active
+     * encryption/decryption operation
+     * @throws UnsupportedOperationException if this method
+     * has not been overridden by an implementation
+     *
+     * @since 1.8
+     */
+    void updateAAD(byte[] src, int offset, int len) {
+        if (aadBuffer != null) {
+            aadBuffer.write(src, offset, len);
+        } else {
+            // update has already been called
+            throw new IllegalStateException
+                ("Update has been called; no more AAD data");
+        }
+    }
+
+    // Feed the AAD data to GHASH, pad if necessary
+    void processAAD() {
+        if (aadBuffer != null) {
+            byte[] aad = aadBuffer.toByteArray();
+            sizeOfAAD = aad.length;
+            aadBuffer = null;
+
+            int lastLen = aad.length % AES_BLOCK_SIZE;
+            if (lastLen != 0) {
+                ghashAllToS.update(aad, 0, aad.length - lastLen);
+                byte[] padded = expandToOneBlock(aad, aad.length - lastLen,
+                                                 lastLen);
+                ghashAllToS.update(padded);
+            } else {
+                ghashAllToS.update(aad);
+            }
+        }
+    }
+
+    // Utility to process the last block; used by encryptFinal and decryptFinal
+    void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs,
+                     boolean isEncrypt) throws IllegalBlockSizeException {
+        // process data in 'in'
+        gctrPAndC.doFinal(in, inOfs, len, out, outOfs);
+        processed += len;
+
+        byte[] ct;
+        int ctOfs;
+        if (isEncrypt) {
+            ct = out;
+            ctOfs = outOfs;
+        } else {
+            ct = in;
+            ctOfs = inOfs;
+        }
+        int lastLen = len  % AES_BLOCK_SIZE;
+        if (lastLen != 0) {
+            ghashAllToS.update(ct, ctOfs, len - lastLen);
+            byte[] padded =
+                expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen);
+            ghashAllToS.update(padded);
+        } else {
+            ghashAllToS.update(ct, ctOfs, len);
+        }
+    }
+
+
+    /**
+     * Performs encryption operation.
+     *
+     * <p>The input plain text <code>in</code>, starting at <code>inOff</code>
+     * and ending at <code>(inOff + len - 1)</code>, is encrypted. The result
+     * is stored in <code>out</code>, starting at <code>outOfs</code>.
+     *
+     * <p>It is the application's responsibility to make sure that
+     * <code>len</code> is a multiple of the embedded cipher's block size,
+     * otherwise, a ProviderException will be thrown.
+     *
+     * <p>It is also the application's responsibility to make sure that
+     * <code>init</code> has been called before this method is called.
+     * (This check is omitted here, to avoid double checking.)
+     *
+     * @param in the buffer with the input data to be encrypted
+     * @param inOfs the offset in <code>in</code>
+     * @param len the length of the input data
+     * @param out the buffer for the result
+     * @param outOfs the offset in <code>out</code>
+     */
+    void encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
+        processAAD();
+        if (len > 0) {
+            gctrPAndC.update(in, inOfs, len, out, outOfs);
+            processed += len;
+            ghashAllToS.update(out, outOfs, len);
+        }
+    }
+
+    /**
+     * Performs encryption operation for the last time.
+     *
+     * <p>NOTE: <code>len</code> may not be multiple of the embedded
+     * cipher's block size for this call.
+     *
+     * @param in the input buffer with the data to be encrypted
+     * @param inOfs the offset in <code>in</code>
+     * @param len the length of the input data
+     * @param out the buffer for the encryption result
+     * @param outOfs the offset in <code>out</code>
+     * @return the number of bytes placed into the <code>out</code> buffer
+     */
+     int encryptFinal(byte[] in, int inOfs, int len, byte[] out, int outOfs)
+         throws IllegalBlockSizeException {
+         if (out.length - outOfs < (len + tagLenBytes)) {
+             throw new RuntimeException("Output buffer too small");
+         }
+
+         processAAD();
+         if (len > 0) {
+             //ByteUtil.dumpArray(Arrays.copyOfRange(in, inOfs, inOfs + len));
+             doLastBlock(in, inOfs, len, out, outOfs, true);
+         }
+
+         byte[] lengthBlock = getLengthBlock(sizeOfAAD*8, processed*8);
+         ghashAllToS.update(lengthBlock);
+         byte[] s = ghashAllToS.digest();
+         byte[] sOut = new byte[s.length];
+         GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
+         gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+
+         System.arraycopy(sOut, 0, out, (outOfs + len), tagLenBytes);
+         return (len + tagLenBytes);
+     }
+
+    /**
+     * Performs decryption operation.
+     *
+     * <p>The input cipher text <code>in</code>, starting at
+     * <code>inOfs</code> and ending at <code>(inOfs + len - 1)</code>,
+     * is decrypted. The result is stored in <code>out</code>, starting at
+     * <code>outOfs</code>.
+     *
+     * <p>It is the application's responsibility to make sure that
+     * <code>len</code> is a multiple of the embedded cipher's block
+     * size, as any excess bytes are ignored.
+     *
+     * <p>It is also the application's responsibility to make sure that
+     * <code>init</code> has been called before this method is called.
+     * (This check is omitted here, to avoid double checking.)
+     *
+     * @param in the buffer with the input data to be decrypted
+     * @param inOfs the offset in <code>in</code>
+     * @param len the length of the input data
+     * @param out the buffer for the result
+     * @param outOfs the offset in <code>out</code>
+     */
+    void decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
+        processAAD();
+
+        if (len > 0) { // must be at least AES_BLOCK_SIZE bytes long
+            gctrPAndC.update(in, inOfs, len, out, outOfs);
+            processed += len;
+            ghashAllToS.update(in, inOfs, len);
+        }
+    }
+
+    /**
+     * Performs decryption operation for the last time.
+     *
+     * <p>NOTE: For cipher feedback modes which does not perform
+     * special handling for the last few blocks, this is essentially
+     * the same as <code>encrypt(...)</code>. Given most modes do
+     * not do special handling, the default impl for this method is
+     * to simply call <code>decrypt(...)</code>.
+     *
+     * @param in the input buffer with the data to be decrypted
+     * @param inOfs the offset in <code>cipher</code>
+     * @param len the length of the input data
+     * @param out the buffer for the decryption result
+     * @param outOfs the offset in <code>plain</code>
+     * @return the number of bytes placed into the <code>out</code> buffer
+     */
+     int decryptFinal(byte[] in, int inOfs, int len,
+                      byte[] out, int outOfs)
+         throws IllegalBlockSizeException, AEADBadTagException {
+         if (len < tagLenBytes) {
+             throw new RuntimeException("Input buffer too short - need tag");
+         }
+         if (out.length - outOfs < (len - tagLenBytes)) {
+             throw new RuntimeException("Output buffer too small");
+         }
+         processAAD();
+
+         int processedOld = processed;
+         byte[] tag = new byte[tagLenBytes];
+         // get the trailing tag bytes from 'in'
+         System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
+         len -= tagLenBytes;
+
+         if (len > 0) {
+             doLastBlock(in, inOfs, len, out, outOfs, false);
+         }
+
+         byte[] lengthBlock = getLengthBlock(sizeOfAAD*8, processed*8);
+         ghashAllToS.update(lengthBlock);
+
+         byte[] s = ghashAllToS.digest();
+         byte[] sOut = new byte[s.length];
+         GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
+         gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+         for (int i = 0; i < tagLenBytes; i++) {
+             if (tag[i] != sOut[i]) {
+                 throw new AEADBadTagException("Tag mismatch!");
+             }
+         }
+         return len;
+     }
+
+    // return tag length in bytes
+    int getTagLen() {
+        return this.tagLenBytes;
+    }
+}
--- a/jdk/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -98,7 +98,7 @@
      */
     protected SecretKey engineGenerateKey() {
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         byte[] keyBytes = new byte[this.keysize];
--- a/jdk/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@
             // generate default for salt and iteration count if necessary
             if (salt == null) {
                 salt = new byte[20];
-                SunJCE.RANDOM.nextBytes(salt);
+                SunJCE.getRandom().nextBytes(salt);
             }
             if (iCount == 0) iCount = 100;
         } else if (!(params instanceof PBEParameterSpec)) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -98,7 +98,7 @@
      */
     protected SecretKey engineGenerateKey() {
         if (this.random == null) {
-            this.random = SunJCE.RANDOM;
+            this.random = SunJCE.getRandom();
         }
 
         byte[] keyBytes = new byte[this.keysize];
--- a/jdk/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
 
         byte paddingOctet = (byte) (len & 0xff);
         byte[] padding = new byte[len];
-        SunJCE.RANDOM.nextBytes(padding);
+        SunJCE.getRandom().nextBytes(padding);
         padding[len-1] = paddingOctet;
         System.arraycopy(padding, 0, in, off, len);
         return;
--- a/jdk/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@
     // generate the key
     SecretKey implGenerateKey() {
         if (random == null) {
-            random = SunJCE.RANDOM;
+            random = SunJCE.getRandom();
         }
         byte[] b = new byte[(keySize + 7) >> 3];
         random.nextBytes(b);
--- a/jdk/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -99,7 +99,7 @@
     {
         // create a random salt (8 bytes)
         byte[] salt = new byte[8];
-        SunJCE.RANDOM.nextBytes(salt);
+        SunJCE.getRandom().nextBytes(salt);
 
         // create PBE parameters from salt and iteration count
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
@@ -284,7 +284,7 @@
     {
         // create a random salt (8 bytes)
         byte[] salt = new byte[8];
-        SunJCE.RANDOM.nextBytes(salt);
+        SunJCE.getRandom().nextBytes(salt);
 
         // create PBE parameters from salt and iteration count
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -164,7 +164,7 @@
         AlgorithmParameters params = null;
         if (salt == null) {
             salt = new byte[8];
-            SunJCE.RANDOM.nextBytes(salt);
+            SunJCE.getRandom().nextBytes(salt);
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
         try {
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -164,7 +164,7 @@
         AlgorithmParameters params = null;
         if (salt == null) {
             salt = new byte[8];
-            SunJCE.RANDOM.nextBytes(salt);
+            SunJCE.getRandom().nextBytes(salt);
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
         try {
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -134,13 +134,13 @@
         if (salt == null) {
             // generate random salt and use default iteration count
             salt = new byte[DEFAULT_SALT_LENGTH];
-            SunJCE.RANDOM.nextBytes(salt);
+            SunJCE.getRandom().nextBytes(salt);
             iCount = DEFAULT_COUNT;
         }
         if (ivSpec == null) {
             // generate random IV
             byte[] ivBytes = new byte[blkSize];
-            SunJCE.RANDOM.nextBytes(ivBytes);
+            SunJCE.getRandom().nextBytes(ivBytes);
             ivSpec = new IvParameterSpec(ivBytes);
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,7 +123,7 @@
             // generate default for salt and iteration count if necessary
             if (salt == null) {
                 salt = new byte[DEFAULT_SALT_LENGTH];
-                SunJCE.RANDOM.nextBytes(salt);
+                SunJCE.getRandom().nextBytes(salt);
             }
             if (iCount == 0) iCount = DEFAULT_COUNT;
         } else if (!(params instanceof PBEParameterSpec)) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@
             // follow the recommendation in PKCS12 v1.0
             // section B.4 to generate salt and iCount.
             salt = new byte[DEFAULT_SALT_LENGTH];
-            SunJCE.RANDOM.nextBytes(salt);
+            SunJCE.getRandom().nextBytes(salt);
             iCount = DEFAULT_COUNT;
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
@@ -294,7 +294,7 @@
                 if (random != null) {
                     random.nextBytes(salt);
                 } else {
-                    SunJCE.RANDOM.nextBytes(salt);
+                    SunJCE.getRandom().nextBytes(salt);
                 }
             }
             if (iCount == 0) iCount = DEFAULT_COUNT;
--- a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -57,6 +57,7 @@
  * - ARCFOUR (RC4 compatible)
  *
  * - Cipher modes ECB, CBC, CFB, OFB, PCBC, CTR, and CTS for all block ciphers
+ *   and mode GCM for AES cipher
  *
  * - Cipher padding ISO10126Padding for non-PKCS#5 block ciphers and
  *   NoPadding and PKCS5Padding for all block ciphers
@@ -90,7 +91,12 @@
     /* Are we debugging? -- for developers */
     static final boolean debug = false;
 
-    static final SecureRandom RANDOM = new SecureRandom();
+    // lazy initialize SecureRandom to avoid potential recursion if Sun
+    // provider has not been installed yet
+    private static class SecureRandomHolder {
+        static final SecureRandom RANDOM = new SecureRandom();
+    }
+    static SecureRandom getRandom() { return SecureRandomHolder.RANDOM; }
 
     public SunJCE() {
         /* We are the "SunJCE" provider */
@@ -100,7 +106,7 @@
             "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
             "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64";
         final String BLOCK_MODES128 = BLOCK_MODES +
-            "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
+            "|GCM|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
             "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128";
         final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";
 
@@ -258,6 +264,9 @@
                     put("Cipher.AES_128/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding");
                     put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding");
                     put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding");
+                    put("Cipher.AES_128/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding");
+                    put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding");
+                    put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding");
 
                     put("Cipher.AES_192/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding");
                     put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding");
@@ -271,7 +280,9 @@
                     put("Cipher.AES_192/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding");
                     put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding");
                     put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding");
-
+                    put("Cipher.AES_192/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding");
+                    put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding");
+                    put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding");
 
                     put("Cipher.AES_256/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding");
                     put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding");
@@ -285,6 +296,9 @@
                     put("Cipher.AES_256/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding");
                     put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding");
                     put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding");
+                    put("Cipher.AES_256/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding");
+                    put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding");
+                    put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding");
 
                     put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher$General");
                     put("Cipher.AESWrap SupportedModes", "ECB");
@@ -509,6 +523,8 @@
                     put("AlgorithmParameters.AES",
                         "com.sun.crypto.provider.AESParameters");
                     put("Alg.Alias.AlgorithmParameters.Rijndael", "AES");
+                    put("AlgorithmParameters.GCM",
+                        "com.sun.crypto.provider.GCMParameters");
 
 
                     put("AlgorithmParameters.RC2",
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 18:35:53 2017 +0200
@@ -860,9 +860,9 @@
      * @return     the specified subsequence.
      *
      * @throws  IndexOutOfBoundsException
-     *          if <tt>start</tt> or <tt>end</tt> are negative,
-     *          if <tt>end</tt> is greater than <tt>length()</tt>,
-     *          or if <tt>start</tt> is greater than <tt>end</tt>
+     *          if {@code start} or {@code end} are negative,
+     *          if {@code end} is greater than {@code length()},
+     *          or if {@code start} is greater than {@code end}
      * @spec JSR-51
      */
     @Override
@@ -1292,7 +1292,7 @@
     /**
      * Returns the index within this string of the first occurrence of the
      * specified substring, starting at the specified index.  The integer
-     * returned is the smallest value <tt>k</tt> for which:
+     * returned is the smallest value {@code k} for which:
      * <blockquote><pre>
      *     k >= Math.min(fromIndex, str.length()) &&
      *                   this.toString().startsWith(str, k)
@@ -1418,7 +1418,7 @@
     public abstract String toString();
 
     /**
-     * Needed by <tt>String</tt> for the contentEquals method.
+     * Needed by {@code String} for the contentEquals method.
      */
     final char[] getValue() {
         return value;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/FunctionalInterface.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that an interface type declaration is intended to be a
+ * <i>functional interface</i> as defined by the Java Language
+ * Specification.
+ *
+ * Conceptually, a functional interface has exactly one abstract
+ * method.  Since {@linkplain java.lang.reflect.Method#isDefault()
+ * default methods} have an implementation, they are not abstract.  If
+ * an interface declares an abstract method overriding one of the
+ * public methods of {@code java.lang.Object}, that also does
+ * <em>not</em> count toward the interface's abstract method count
+ * since any implementation of the interface will have an
+ * implementation from {@code java.lang.Object} or elsewhere.
+ *
+ * <p>Note that instances of functional interfaces can be created with
+ * lambda expressions, method references, or constructor references.
+ *
+ * <p>If a type is annotated with this annotation type, compilers are
+ * required to generate an error message unless:
+ *
+ * <ul>
+ * <li> The type is an interface type and not an annotation type, enum, or class.
+ * <li> The annotated type satisfies the requirements of a functional interface.
+ * </ul>
+ *
+ * @jls 4.3.2. The Class Object
+ * @jls 9.8 Functional Interfaces
+ * @jls 9.4.3 Interface Method Body
+ * @since 1.8
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface FunctionalInterface {}
--- a/jdk/src/share/classes/java/lang/Integer.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/Integer.java	Wed Jul 05 18:35:53 2017 +0200
@@ -772,7 +772,7 @@
                 int i = parseInt(integerCacheHighPropValue);
                 i = Math.max(i, 127);
                 // Maximum array size is Integer.MAX_VALUE
-                h = Math.min(i, Integer.MAX_VALUE - (-low));
+                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
             }
             high = h;
 
--- a/jdk/src/share/classes/java/lang/String.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/String.java	Wed Jul 05 18:35:53 2017 +0200
@@ -615,10 +615,10 @@
     }
 
     /**
-     * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
+     * Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
      *
-     * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise
-     * <tt>false</tt>
+     * @return {@code true} if {@link #length()} is {@code 0}, otherwise
+     * {@code false}
      *
      * @since 1.6
      */
@@ -1229,23 +1229,23 @@
     /**
      * Tests if two string regions are equal.
      * <p>
-     * A substring of this <tt>String</tt> object is compared to a substring
+     * A substring of this {@code String} object is compared to a substring
      * of the argument other. The result is true if these substrings
      * represent identical character sequences. The substring of this
-     * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
-     * and has length <tt>len</tt>. The substring of other to be compared
-     * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
-     * result is <tt>false</tt> if and only if at least one of the following
+     * {@code String} object to be compared begins at index {@code toffset}
+     * and has length {@code len}. The substring of other to be compared
+     * begins at index {@code ooffset} and has length {@code len}. The
+     * result is {@code false} if and only if at least one of the following
      * is true:
-     * <ul><li><tt>toffset</tt> is negative.
-     * <li><tt>ooffset</tt> is negative.
-     * <li><tt>toffset+len</tt> is greater than the length of this
-     * <tt>String</tt> object.
-     * <li><tt>ooffset+len</tt> is greater than the length of the other
+     * <ul><li>{@code toffset} is negative.
+     * <li>{@code ooffset} is negative.
+     * <li>{@code toffset+len} is greater than the length of this
+     * {@code String} object.
+     * <li>{@code ooffset+len} is greater than the length of the other
      * argument.
-     * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
+     * <li>There is some nonnegative integer <i>k</i> less than {@code len}
      * such that:
-     * <tt>this.charAt(toffset+<i>k</i>)&nbsp;!=&nbsp;other.charAt(ooffset+<i>k</i>)</tt>
+     * <code>this.charAt(toffset+<i>k</i>)&nbsp;!=&nbsp;other.charAt(ooffset+<i>k</i>)</code>
      * </ul>
      *
      * @param   toffset   the starting offset of the subregion in this string.
@@ -1280,28 +1280,28 @@
     /**
      * Tests if two string regions are equal.
      * <p>
-     * A substring of this <tt>String</tt> object is compared to a substring
-     * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
+     * A substring of this {@code String} object is compared to a substring
+     * of the argument {@code other}. The result is {@code true} if these
      * substrings represent character sequences that are the same, ignoring
-     * case if and only if <tt>ignoreCase</tt> is true. The substring of
-     * this <tt>String</tt> object to be compared begins at index
-     * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
-     * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
-     * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
+     * case if and only if {@code ignoreCase} is true. The substring of
+     * this {@code String} object to be compared begins at index
+     * {@code toffset} and has length {@code len}. The substring of
+     * {@code other} to be compared begins at index {@code ooffset} and
+     * has length {@code len}. The result is {@code false} if and only if
      * at least one of the following is true:
-     * <ul><li><tt>toffset</tt> is negative.
-     * <li><tt>ooffset</tt> is negative.
-     * <li><tt>toffset+len</tt> is greater than the length of this
-     * <tt>String</tt> object.
-     * <li><tt>ooffset+len</tt> is greater than the length of the other
+     * <ul><li>{@code toffset} is negative.
+     * <li>{@code ooffset} is negative.
+     * <li>{@code toffset+len} is greater than the length of this
+     * {@code String} object.
+     * <li>{@code ooffset+len} is greater than the length of the other
      * argument.
-     * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative
-     * integer <i>k</i> less than <tt>len</tt> such that:
+     * <li>{@code ignoreCase} is {@code false} and there is some nonnegative
+     * integer <i>k</i> less than {@code len} such that:
      * <blockquote><pre>
      * this.charAt(toffset+k) != other.charAt(ooffset+k)
      * </pre></blockquote>
-     * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
-     * integer <i>k</i> less than <tt>len</tt> such that:
+     * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
+     * integer <i>k</i> less than {@code len} such that:
      * <blockquote><pre>
      * Character.toLowerCase(this.charAt(toffset+k)) !=
      Character.toLowerCase(other.charAt(ooffset+k))
@@ -1500,12 +1500,12 @@
      * of {@code ch} in the range from 0 to 0xFFFF (inclusive),
      * this is the smallest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+     * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
      * </pre></blockquote>
      * is true. For other values of {@code ch}, it is the
      * smallest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+     * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
      * </pre></blockquote>
      * is true. In either case, if no such character occurs in this
      * string at or after position {@code fromIndex}, then
@@ -1604,12 +1604,12 @@
      * from 0 to 0xFFFF (inclusive), the index returned is the largest
      * value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+     * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
      * </pre></blockquote>
      * is true. For other values of {@code ch}, it is the
      * largest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+     * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
      * </pre></blockquote>
      * is true. In either case, if no such character occurs in this
      * string at or before position {@code fromIndex}, then
@@ -1690,7 +1690,7 @@
      *
      * <p>The returned index is the smallest value <i>k</i> for which:
      * <blockquote><pre>
-     * <i>k</i> &gt;= fromIndex && this.startsWith(str, <i>k</i>)
+     * <i>k</i> &gt;= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
@@ -1799,7 +1799,7 @@
      *
      * <p>The returned index is the largest value <i>k</i> for which:
      * <blockquote><pre>
-     * <i>k</i> &lt;= fromIndex && this.startsWith(str, <i>k</i>)
+     * <i>k</i> {@code <=} fromIndex {@code &&} this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
@@ -2080,17 +2080,18 @@
      * href="../util/regex/Pattern.html#sum">regular expression</a>.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.matches(</tt><i>regex</i><tt>)</tt> yields exactly the
+     * <i>str</i>{@code .matches(}<i>regex</i>{@code )} yields exactly the
      * same result as the expression
      *
-     * <blockquote><tt> {@link java.util.regex.Pattern}.{@link
-     * java.util.regex.Pattern#matches(String,CharSequence)
-     * matches}(</tt><i>regex</i><tt>,</tt> <i>str</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#matches(String,CharSequence)
+     * matches(<i>regex</i>, <i>str</i>)}
+     * </blockquote>
      *
      * @param   regex
      *          the regular expression to which this string is to be matched
      *
-     * @return  <tt>true</tt> if, and only if, this string matches the
+     * @return  {@code true} if, and only if, this string matches the
      *          given regular expression
      *
      * @throws  PatternSyntaxException
@@ -2124,18 +2125,20 @@
      * given replacement.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.replaceFirst(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+     * <i>str</i>{@code .replaceFirst(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
      * yields exactly the same result as the expression
      *
-     * <blockquote><tt>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}(</tt><i>regex</i><tt>).{@link
-     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
-     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceFirst
-     * replaceFirst}(</tt><i>repl</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+     * java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
+     * </code>
+     * </blockquote>
      *
      *<p>
-     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+     * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
      * replacement string may cause the results to be different than if it were
      * being treated as a literal replacement string; see
      * {@link java.util.regex.Matcher#replaceFirst}.
@@ -2147,7 +2150,7 @@
      * @param   replacement
      *          the string to be substituted for the first match
      *
-     * @return  The resulting <tt>String</tt>
+     * @return  The resulting {@code String}
      *
      * @throws  PatternSyntaxException
      *          if the regular expression's syntax is invalid
@@ -2167,18 +2170,20 @@
      * given replacement.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.replaceAll(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+     * <i>str</i>{@code .replaceAll(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
      * yields exactly the same result as the expression
      *
-     * <blockquote><tt>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}(</tt><i>regex</i><tt>).{@link
-     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
-     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceAll
-     * replaceAll}(</tt><i>repl</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+     * java.util.regex.Matcher#replaceAll replaceAll}(<i>repl</i>)
+     * </code>
+     * </blockquote>
      *
      *<p>
-     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+     * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
      * replacement string may cause the results to be different than if it were
      * being treated as a literal replacement string; see
      * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}.
@@ -2190,7 +2195,7 @@
      * @param   replacement
      *          the string to be substituted for each match
      *
-     * @return  The resulting <tt>String</tt>
+     * @return  The resulting {@code String}
      *
      * @throws  PatternSyntaxException
      *          if the regular expression's syntax is invalid
@@ -2234,7 +2239,7 @@
      * expression does not match any part of the input then the resulting array
      * has just one element, namely this string.
      *
-     * <p> The <tt>limit</tt> parameter controls the number of times the
+     * <p> The {@code limit} parameter controls the number of times the
      * pattern is applied and therefore affects the length of the resulting
      * array.  If the limit <i>n</i> is greater than zero then the pattern
      * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
@@ -2245,7 +2250,7 @@
      * the pattern will be applied as many times as possible, the array can
      * have any length, and trailing empty strings will be discarded.
      *
-     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the
+     * <p> The string {@code "boo:and:foo"}, for example, yields the
      * following results with these parameters:
      *
      * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
@@ -2256,33 +2261,34 @@
      * </tr>
      * <tr><td align=center>:</td>
      *     <td align=center>2</td>
-     *     <td><tt>{ "boo", "and:foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and:foo" }}</td></tr>
      * <tr><td align=center>:</td>
      *     <td align=center>5</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>:</td>
      *     <td align=center>-2</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>5</td>
-     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>-2</td>
-     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>0</td>
-     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f" }}</td></tr>
      * </table></blockquote>
      *
      * <p> An invocation of this method of the form
-     * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+     * <i>str.</i>{@code split(}<i>regex</i>{@code ,}&nbsp;<i>n</i>{@code )}
      * yields the same result as the expression
      *
      * <blockquote>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link
-     * java.util.regex.Pattern#split(java.lang.CharSequence,int)
-     * split}<tt>(</tt><i>str</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(<i>str</i>,&nbsp;<i>n</i>)
+     * </code>
      * </blockquote>
      *
      *
@@ -2364,7 +2370,7 @@
      * argument of zero.  Trailing empty strings are therefore not included in
      * the resulting array.
      *
-     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the following
+     * <p> The string {@code "boo:and:foo"}, for example, yields the following
      * results with these expressions:
      *
      * <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result">
@@ -2373,9 +2379,9 @@
      *  <th>Result</th>
      * </tr>
      * <tr><td align=center>:</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>o</td>
-     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f" }}</td></tr>
      * </table></blockquote>
      *
      *
@@ -2815,7 +2821,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -2828,7 +2834,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  A formatted string
      *
@@ -2845,7 +2851,7 @@
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -2859,7 +2865,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -2872,7 +2878,7 @@
      *          formatter class specification
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  A formatted string
      *
@@ -3143,7 +3149,7 @@
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
-    * <p/>
+    * </p>
      * The hash value will never be zero.
     *
     * @return  a hash code value for this object.
--- a/jdk/src/share/classes/java/lang/StringBuffer.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java	Wed Jul 05 18:35:53 2017 +0200
@@ -57,7 +57,7 @@
  * <p>
  * In general, if sb refers to an instance of a {@code StringBuffer},
  * then {@code sb.append(x)} has the same effect as
- * {@code sb.insert(sb.length(),&nbsp;x)}.
+ * {@code sb.insert(sb.length(), x)}.
  * <p>
  * Whenever an operation occurs involving a source sequence (such as
  * appending or inserting from a source sequence), this class synchronizes
@@ -80,7 +80,7 @@
  *
  * As of  release JDK 5, this class has been supplemented with an equivalent
  * class designed for use by a single thread, {@link StringBuilder}.  The
- * <tt>StringBuilder</tt> class should generally be used in preference to
+ * {@code StringBuilder} class should generally be used in preference to
  * this one, as it supports all of the same operations but it is faster, as
  * it performs no synchronization.
  *
@@ -262,17 +262,17 @@
     }
 
     /**
-     * Appends the specified <tt>StringBuffer</tt> to this sequence.
+     * Appends the specified {@code StringBuffer} to this sequence.
      * <p>
-     * The characters of the <tt>StringBuffer</tt> argument are appended,
-     * in order, to the contents of this <tt>StringBuffer</tt>, increasing the
-     * length of this <tt>StringBuffer</tt> by the length of the argument.
-     * If <tt>sb</tt> is <tt>null</tt>, then the four characters
-     * <tt>"null"</tt> are appended to this <tt>StringBuffer</tt>.
+     * The characters of the {@code StringBuffer} argument are appended,
+     * in order, to the contents of this {@code StringBuffer}, increasing the
+     * length of this {@code StringBuffer} by the length of the argument.
+     * If {@code sb} is {@code null}, then the four characters
+     * {@code "null"} are appended to this {@code StringBuffer}.
      * <p>
      * Let <i>n</i> be the length of the old character sequence, the one
-     * contained in the <tt>StringBuffer</tt> just prior to execution of the
-     * <tt>append</tt> method. Then the character at index <i>k</i> in
+     * contained in the {@code StringBuffer} just prior to execution of the
+     * {@code append} method. Then the character at index <i>k</i> in
      * the new character sequence is equal to the character at index <i>k</i>
      * in the old character sequence, if <i>k</i> is less than <i>n</i>;
      * otherwise, it is equal to the character at index <i>k-n</i> in the
@@ -281,7 +281,7 @@
      * This method synchronizes on {@code this}, the destination
      * object, but does not synchronize on the source ({@code sb}).
      *
-     * @param   sb   the <tt>StringBuffer</tt> to append.
+     * @param   sb   the {@code StringBuffer} to append.
      * @return  a reference to this object.
      * @since 1.4
      */
--- a/jdk/src/share/classes/java/lang/StringBuilder.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/StringBuilder.java	Wed Jul 05 18:35:53 2017 +0200
@@ -28,39 +28,39 @@
 
 /**
  * A mutable sequence of characters.  This class provides an API compatible
- * with <code>StringBuffer</code>, but with no guarantee of synchronization.
+ * with {@code StringBuffer}, but with no guarantee of synchronization.
  * This class is designed for use as a drop-in replacement for
- * <code>StringBuffer</code> in places where the string buffer was being
+ * {@code StringBuffer} in places where the string buffer was being
  * used by a single thread (as is generally the case).   Where possible,
  * it is recommended that this class be used in preference to
- * <code>StringBuffer</code> as it will be faster under most implementations.
+ * {@code StringBuffer} as it will be faster under most implementations.
  *
- * <p>The principal operations on a <code>StringBuilder</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * <p>The principal operations on a {@code StringBuilder} are the
+ * {@code append} and {@code insert} methods, which are
  * overloaded so as to accept data of any type. Each effectively
  * converts a given datum to a string and then appends or inserts the
  * characters of that string to the string builder. The
- * <code>append</code> method always adds these characters at the end
- * of the builder; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the builder; the {@code insert} method adds the characters at
  * a specified point.
  * <p>
- * For example, if <code>z</code> refers to a string builder object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * builder to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string builder to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string builder object
+ * whose current contents are "{@code start}", then
+ * the method call {@code z.append("le")} would cause the string
+ * builder to contain "{@code startle}", whereas
+ * {@code z.insert(4, "le")} would alter the string builder to
+ * contain "{@code starlet}".
  * <p>
- * In general, if sb refers to an instance of a <code>StringBuilder</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(),&nbsp;x)</code>.
- *
+ * In general, if sb refers to an instance of a {@code StringBuilder},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(), x)}.
+ * <p>
  * Every string builder has a capacity. As long as the length of the
  * character sequence contained in the string builder does not exceed
  * the capacity, it is not necessary to allocate a new internal
  * buffer. If the internal buffer overflows, it is automatically made larger.
  *
- * <p>Instances of <code>StringBuilder</code> are not safe for
+ * <p>Instances of {@code StringBuilder} are not safe for
  * use by multiple threads. If such synchronization is required then it is
  * recommended that {@link java.lang.StringBuffer} be used.
  *
@@ -87,11 +87,11 @@
 
     /**
      * Constructs a string builder with no characters in it and an
-     * initial capacity specified by the <code>capacity</code> argument.
+     * initial capacity specified by the {@code capacity} argument.
      *
      * @param      capacity  the initial capacity.
-     * @throws     NegativeArraySizeException  if the <code>capacity</code>
-     *               argument is less than <code>0</code>.
+     * @throws     NegativeArraySizeException  if the {@code capacity}
+     *               argument is less than {@code 0}.
      */
     public StringBuilder(int capacity) {
         super(capacity);
@@ -100,10 +100,10 @@
     /**
      * Constructs a string builder initialized to the contents of the
      * specified string. The initial capacity of the string builder is
-     * <code>16</code> plus the length of the string argument.
+     * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @throws    NullPointerException if <code>str</code> is <code>null</code>
+     * @throws    NullPointerException if {@code str} is {@code null}
      */
     public StringBuilder(String str) {
         super(str.length() + 16);
@@ -112,12 +112,12 @@
 
     /**
      * Constructs a string builder that contains the same characters
-     * as the specified <code>CharSequence</code>. The initial capacity of
-     * the string builder is <code>16</code> plus the length of the
-     * <code>CharSequence</code> argument.
+     * as the specified {@code CharSequence}. The initial capacity of
+     * the string builder is {@code 16} plus the length of the
+     * {@code CharSequence} argument.
      *
      * @param      seq   the sequence to copy.
-     * @throws    NullPointerException if <code>seq</code> is <code>null</code>
+     * @throws    NullPointerException if {@code seq} is {@code null}
      */
     public StringBuilder(CharSequence seq) {
         this(seq.length() + 16);
@@ -136,22 +136,22 @@
     }
 
     /**
-     * Appends the specified <tt>StringBuffer</tt> to this sequence.
+     * Appends the specified {@code StringBuffer} to this sequence.
      * <p>
-     * The characters of the <tt>StringBuffer</tt> argument are appended,
+     * The characters of the {@code StringBuffer} argument are appended,
      * in order, to this sequence, increasing the
      * length of this sequence by the length of the argument.
-     * If <tt>sb</tt> is <tt>null</tt>, then the four characters
-     * <tt>"null"</tt> are appended to this sequence.
+     * If {@code sb} is {@code null}, then the four characters
+     * {@code "null"} are appended to this sequence.
      * <p>
      * Let <i>n</i> be the length of this character sequence just prior to
-     * execution of the <tt>append</tt> method. Then the character at index
+     * execution of the {@code append} method. Then the character at index
      * <i>k</i> in the new character sequence is equal to the character at
      * index <i>k</i> in the old character sequence, if <i>k</i> is less than
      * <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i>
-     * in the argument <code>sb</code>.
+     * in the argument {@code sb}.
      *
-     * @param   sb   the <tt>StringBuffer</tt> to append.
+     * @param   sb   the {@code StringBuffer} to append.
      * @return  a reference to this object.
      */
     public StringBuilder append(StringBuffer sb) {
@@ -418,13 +418,13 @@
     }
 
     /**
-     * Save the state of the <tt>StringBuilder</tt> instance to a stream
+     * Save the state of the {@code StringBuilder} instance to a stream
      * (that is, serialize it).
      *
      * @serialData the number of characters currently stored in the string
-     *             builder (<tt>int</tt>), followed by the characters in the
-     *             string builder (<tt>char[]</tt>).   The length of the
-     *             <tt>char</tt> array may be greater than the number of
+     *             builder ({@code int}), followed by the characters in the
+     *             string builder ({@code char[]}).   The length of the
+     *             {@code char} array may be greater than the number of
      *             characters currently stored in the string builder, in which
      *             case extra characters are ignored.
      */
--- a/jdk/src/share/classes/java/lang/StringIndexOutOfBoundsException.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/lang/StringIndexOutOfBoundsException.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2012, 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,7 +26,7 @@
 package java.lang;
 
 /**
- * Thrown by <code>String</code> methods to indicate that an index
+ * Thrown by {@code String} methods to indicate that an index
  * is either negative or greater than the size of the string.  For
  * some methods such as the charAt method, this exception also is
  * thrown when the index is equal to the size of the string.
@@ -40,7 +40,7 @@
     private static final long serialVersionUID = -6762910422159637258L;
 
     /**
-     * Constructs a <code>StringIndexOutOfBoundsException</code> with no
+     * Constructs a {@code StringIndexOutOfBoundsException} with no
      * detail message.
      *
      * @since   JDK1.0.
@@ -50,7 +50,7 @@
     }
 
     /**
-     * Constructs a <code>StringIndexOutOfBoundsException</code> with
+     * Constructs a {@code StringIndexOutOfBoundsException} with
      * the specified detail message.
      *
      * @param   s   the detail message.
@@ -60,7 +60,7 @@
     }
 
     /**
-     * Constructs a new <code>StringIndexOutOfBoundsException</code>
+     * Constructs a new {@code StringIndexOutOfBoundsException}
      * class with an argument indicating the illegal index.
      *
      * @param   index   the illegal index.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/annotation/Repeatable.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.annotation;
+
+/**
+ * The annotation type {@code java.lang.annotation.Repeatable} is
+ * used to indicate that the annotation type whose declaration it
+ * (meta-)annotates is <em>repeatable</em>. The value of
+ * {@code @Repeatable} indicates the <em>containing annotation
+ * type</em> for the repeatable annotation type.
+ *
+ * @since 1.8
+ * @jls 9.6 Annotation Types
+ * @jls 9.7 Annotations
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface Repeatable {
+    /**
+     * Indicates the <em>containing annotation type</em> for the
+     * repeatable annotation type.
+     */
+    Class<? extends Annotation> value();
+}
--- a/jdk/src/share/classes/java/security/Principal.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/security/Principal.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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,8 @@
 
 package java.security;
 
+import javax.security.auth.Subject;
+
 /**
  * This interface represents the abstract notion of a principal, which
  * can be used to represent any entity, such as an individual, a
@@ -45,7 +47,6 @@
      *
      * @return true if the principal passed in is the same as that
      * encapsulated by this principal, and false otherwise.
-
      */
     public boolean equals(Object another);
 
@@ -69,4 +70,24 @@
      * @return the name of this principal.
      */
     public String getName();
+
+    /**
+     * Returns true if the specified subject is implied by this principal.
+     *
+     * <p>The default implementation of this method returns true if
+     * {@code subject} is non-null and contains at least one principal that
+     * is equal to this principal.
+     *
+     * <p>Subclasses may override this with a different implementation, if
+     * necessary.
+     *
+     * @return true if {@code subject} is non-null and is
+     *              implied by this principal, or false otherwise.
+     * @since 1.8
+     */
+    public default boolean implies(Subject subject) {
+        if (subject == null)
+            return false;
+        return subject.getPrincipals().contains(this);
+    }
 }
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 18:35:53 2017 +0200
@@ -2611,6 +2611,7 @@
      * {@link #shutdown} or {@link #shutdownNow}.
      *
      * @return the common pool instance
+     * @since 1.8
      */
     public static ForkJoinPool commonPool() {
         // assert commonPool != null : "static init error";
@@ -2793,6 +2794,7 @@
      * Returns the targeted parallelism level of the common pool.
      *
      * @return the targeted parallelism level of the common pool
+     * @since 1.8
      */
     public static int getCommonPoolParallelism() {
         return commonPoolParallelism;
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Wed Jul 05 18:35:53 2017 +0200
@@ -111,7 +111,7 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public boolean weakCompareAndSet(boolean expect, boolean update) {
         int e = expect ? 1 : 0;
@@ -146,16 +146,16 @@
      * @return the previous value
      */
     public final boolean getAndSet(boolean newValue) {
-        for (;;) {
-            boolean current = get();
-            if (compareAndSet(current, newValue))
-                return current;
-        }
+        boolean prev;
+        do {
+            prev = get();
+        } while (!compareAndSet(prev, newValue));
+        return prev;
     }
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Boolean.toString(get());
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Wed Jul 05 18:35:53 2017 +0200
@@ -115,11 +115,7 @@
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        for (;;) {
-            int current = get();
-            if (compareAndSet(current, newValue))
-                return current;
-        }
+        return unsafe.getAndSetInt(this, valueOffset, newValue);
     }
 
     /**
@@ -145,7 +141,7 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int expect, int update) {
         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
@@ -157,12 +153,7 @@
      * @return the previous value
      */
     public final int getAndIncrement() {
-        for (;;) {
-            int current = get();
-            int next = current + 1;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return getAndAdd(1);
     }
 
     /**
@@ -171,12 +162,7 @@
      * @return the previous value
      */
     public final int getAndDecrement() {
-        for (;;) {
-            int current = get();
-            int next = current - 1;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return getAndAdd(-1);
     }
 
     /**
@@ -186,12 +172,7 @@
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        for (;;) {
-            int current = get();
-            int next = current + delta;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return unsafe.getAndAddInt(this, valueOffset, delta);
     }
 
     /**
@@ -200,12 +181,7 @@
      * @return the updated value
      */
     public final int incrementAndGet() {
-        for (;;) {
-            int current = get();
-            int next = current + 1;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(1) + 1;
     }
 
     /**
@@ -214,12 +190,7 @@
      * @return the updated value
      */
     public final int decrementAndGet() {
-        for (;;) {
-            int current = get();
-            int next = current - 1;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(-1) - 1;
     }
 
     /**
@@ -229,17 +200,12 @@
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        for (;;) {
-            int current = get();
-            int next = current + delta;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(delta) + delta;
     }
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Integer.toString(get());
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Wed Jul 05 18:35:53 2017 +0200
@@ -145,12 +145,7 @@
      * @return the previous value
      */
     public final int getAndSet(int i, int newValue) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            int current = getRaw(offset);
-            if (compareAndSetRaw(offset, current, newValue))
-                return current;
-        }
+        return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -182,7 +177,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, int expect, int update) {
         return compareAndSet(i, expect, update);
@@ -216,12 +211,7 @@
      * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            int current = getRaw(offset);
-            if (compareAndSetRaw(offset, current, current + delta))
-                return current;
-        }
+        return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
     }
 
     /**
@@ -231,7 +221,7 @@
      * @return the updated value
      */
     public final int incrementAndGet(int i) {
-        return addAndGet(i, 1);
+        return getAndAdd(i, 1) + 1;
     }
 
     /**
@@ -241,7 +231,7 @@
      * @return the updated value
      */
     public final int decrementAndGet(int i) {
-        return addAndGet(i, -1);
+        return getAndAdd(i, -1) - 1;
     }
 
     /**
@@ -252,13 +242,7 @@
      * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            int current = getRaw(offset);
-            int next = current + delta;
-            if (compareAndSetRaw(offset, current, next))
-                return next;
-        }
+        return getAndAdd(i, delta) + delta;
     }
 
     /**
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Wed Jul 05 18:35:53 2017 +0200
@@ -159,11 +159,11 @@
      * @return the previous value
      */
     public int getAndSet(T obj, int newValue) {
-        for (;;) {
-            int current = get(obj);
-            if (compareAndSet(obj, current, newValue))
-                return current;
-        }
+        int prev;
+        do {
+            prev = get(obj);
+        } while (!compareAndSet(obj, prev, newValue));
+        return prev;
     }
 
     /**
@@ -174,12 +174,12 @@
      * @return the previous value
      */
     public int getAndIncrement(T obj) {
-        for (;;) {
-            int current = get(obj);
-            int next = current + 1;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev + 1;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -190,12 +190,12 @@
      * @return the previous value
      */
     public int getAndDecrement(T obj) {
-        for (;;) {
-            int current = get(obj);
-            int next = current - 1;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev - 1;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -207,12 +207,12 @@
      * @return the previous value
      */
     public int getAndAdd(T obj, int delta) {
-        for (;;) {
-            int current = get(obj);
-            int next = current + delta;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev + delta;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -223,12 +223,12 @@
      * @return the updated value
      */
     public int incrementAndGet(T obj) {
-        for (;;) {
-            int current = get(obj);
-            int next = current + 1;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev + 1;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     /**
@@ -239,12 +239,12 @@
      * @return the updated value
      */
     public int decrementAndGet(T obj) {
-        for (;;) {
-            int current = get(obj);
-            int next = current - 1;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev - 1;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     /**
@@ -256,12 +256,12 @@
      * @return the updated value
      */
     public int addAndGet(T obj, int delta) {
-        for (;;) {
-            int current = get(obj);
-            int next = current + delta;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        int prev, next;
+        do {
+            prev = get(obj);
+            next = prev + delta;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     /**
@@ -361,6 +361,36 @@
             return unsafe.getIntVolatile(obj, offset);
         }
 
+        public int getAndSet(T obj, int newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getAndSetInt(obj, offset, newValue);
+        }
+
+        public int getAndIncrement(T obj) {
+            return getAndAdd(obj, 1);
+        }
+
+        public int getAndDecrement(T obj) {
+            return getAndAdd(obj, -1);
+        }
+
+        public int getAndAdd(T obj, int delta) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getAndAddInt(obj, offset, delta);
+        }
+
+        public int incrementAndGet(T obj) {
+            return getAndAdd(obj, 1) + 1;
+        }
+
+        public int decrementAndGet(T obj) {
+             return getAndAdd(obj, -1) - 1;
+        }
+
+        public int addAndGet(T obj, int delta) {
+            return getAndAdd(obj, delta) + delta;
+        }
+
         private void ensureProtectedAccess(T obj) {
             if (cclass.isInstance(obj)) {
                 return;
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java	Wed Jul 05 18:35:53 2017 +0200
@@ -129,11 +129,7 @@
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        while (true) {
-            long current = get();
-            if (compareAndSet(current, newValue))
-                return current;
-        }
+        return unsafe.getAndSetLong(this, valueOffset, newValue);
     }
 
     /**
@@ -159,7 +155,7 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(long expect, long update) {
         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
@@ -171,12 +167,7 @@
      * @return the previous value
      */
     public final long getAndIncrement() {
-        while (true) {
-            long current = get();
-            long next = current + 1;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return getAndAdd(1);
     }
 
     /**
@@ -185,12 +176,7 @@
      * @return the previous value
      */
     public final long getAndDecrement() {
-        while (true) {
-            long current = get();
-            long next = current - 1;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return getAndAdd(-1);
     }
 
     /**
@@ -200,12 +186,7 @@
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        while (true) {
-            long current = get();
-            long next = current + delta;
-            if (compareAndSet(current, next))
-                return current;
-        }
+        return unsafe.getAndAddLong(this, valueOffset, delta);
     }
 
     /**
@@ -214,12 +195,7 @@
      * @return the updated value
      */
     public final long incrementAndGet() {
-        for (;;) {
-            long current = get();
-            long next = current + 1;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(1) + 1;
     }
 
     /**
@@ -228,12 +204,7 @@
      * @return the updated value
      */
     public final long decrementAndGet() {
-        for (;;) {
-            long current = get();
-            long next = current - 1;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(-1) - 1;
     }
 
     /**
@@ -243,17 +214,12 @@
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        for (;;) {
-            long current = get();
-            long next = current + delta;
-            if (compareAndSet(current, next))
-                return next;
-        }
+        return getAndAdd(delta) + delta;
     }
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Long.toString(get());
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Wed Jul 05 18:35:53 2017 +0200
@@ -144,12 +144,7 @@
      * @return the previous value
      */
     public final long getAndSet(int i, long newValue) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            long current = getRaw(offset);
-            if (compareAndSetRaw(offset, current, newValue))
-                return current;
-        }
+        return unsafe.getAndSetLong(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -181,7 +176,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, long expect, long update) {
         return compareAndSet(i, expect, update);
@@ -215,12 +210,7 @@
      * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            long current = getRaw(offset);
-            if (compareAndSetRaw(offset, current, current + delta))
-                return current;
-        }
+        return unsafe.getAndAddLong(array, checkedByteOffset(i), delta);
     }
 
     /**
@@ -230,7 +220,7 @@
      * @return the updated value
      */
     public final long incrementAndGet(int i) {
-        return addAndGet(i, 1);
+        return getAndAdd(i, 1) + 1;
     }
 
     /**
@@ -240,7 +230,7 @@
      * @return the updated value
      */
     public final long decrementAndGet(int i) {
-        return addAndGet(i, -1);
+        return getAndAdd(i, -1) - 1;
     }
 
     /**
@@ -251,13 +241,7 @@
      * @return the updated value
      */
     public long addAndGet(int i, long delta) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            long current = getRaw(offset);
-            long next = current + delta;
-            if (compareAndSetRaw(offset, current, next))
-                return next;
-        }
+        return getAndAdd(i, delta) + delta;
     }
 
     /**
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Wed Jul 05 18:35:53 2017 +0200
@@ -98,7 +98,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor.
      */
@@ -118,7 +118,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor.
      */
@@ -162,11 +162,11 @@
      * @return the previous value
      */
     public long getAndSet(T obj, long newValue) {
-        for (;;) {
-            long current = get(obj);
-            if (compareAndSet(obj, current, newValue))
-                return current;
-        }
+        long prev;
+        do {
+            prev = get(obj);
+        } while (!compareAndSet(obj, prev, newValue));
+        return prev;
     }
 
     /**
@@ -177,12 +177,12 @@
      * @return the previous value
      */
     public long getAndIncrement(T obj) {
-        for (;;) {
-            long current = get(obj);
-            long next = current + 1;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev + 1;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -193,12 +193,12 @@
      * @return the previous value
      */
     public long getAndDecrement(T obj) {
-        for (;;) {
-            long current = get(obj);
-            long next = current - 1;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev - 1;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -210,12 +210,12 @@
      * @return the previous value
      */
     public long getAndAdd(T obj, long delta) {
-        for (;;) {
-            long current = get(obj);
-            long next = current + delta;
-            if (compareAndSet(obj, current, next))
-                return current;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev + delta;
+        } while (!compareAndSet(obj, prev, next));
+        return prev;
     }
 
     /**
@@ -226,12 +226,12 @@
      * @return the updated value
      */
     public long incrementAndGet(T obj) {
-        for (;;) {
-            long current = get(obj);
-            long next = current + 1;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev + 1;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     /**
@@ -242,12 +242,12 @@
      * @return the updated value
      */
     public long decrementAndGet(T obj) {
-        for (;;) {
-            long current = get(obj);
-            long next = current - 1;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev - 1;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     /**
@@ -259,12 +259,12 @@
      * @return the updated value
      */
     public long addAndGet(T obj, long delta) {
-        for (;;) {
-            long current = get(obj);
-            long next = current + delta;
-            if (compareAndSet(obj, current, next))
-                return next;
-        }
+        long prev, next;
+        do {
+            prev = get(obj);
+            next = prev + delta;
+        } while (!compareAndSet(obj, prev, next));
+        return next;
     }
 
     private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
@@ -345,6 +345,36 @@
             return unsafe.getLongVolatile(obj, offset);
         }
 
+        public long getAndSet(T obj, long newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getAndSetLong(obj, offset, newValue);
+        }
+
+        public long getAndIncrement(T obj) {
+            return getAndAdd(obj, 1);
+        }
+
+        public long getAndDecrement(T obj) {
+            return getAndAdd(obj, -1);
+        }
+
+        public long getAndAdd(T obj, long delta) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getAndAddLong(obj, offset, delta);
+        }
+
+        public long incrementAndGet(T obj) {
+            return getAndAdd(obj, 1) + 1;
+        }
+
+        public long decrementAndGet(T obj) {
+             return getAndAdd(obj, -1) - 1;
+        }
+
+        public long addAndGet(T obj, long delta) {
+            return getAndAdd(obj, delta) + delta;
+        }
+
         private void ensureProtectedAccess(T obj) {
             if (cclass.isInstance(obj)) {
                 return;
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java	Wed Jul 05 18:35:53 2017 +0200
@@ -124,7 +124,7 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(V expect, V update) {
         return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
@@ -136,17 +136,14 @@
      * @param newValue the new value
      * @return the previous value
      */
+    @SuppressWarnings("unchecked")
     public final V getAndSet(V newValue) {
-        while (true) {
-            V x = get();
-            if (compareAndSet(x, newValue))
-                return x;
-        }
+        return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
     }
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return String.valueOf(get());
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Jul 05 18:35:53 2017 +0200
@@ -159,13 +159,9 @@
      * @param newValue the new value
      * @return the previous value
      */
+    @SuppressWarnings("unchecked")
     public final E getAndSet(int i, E newValue) {
-        long offset = checkedByteOffset(i);
-        while (true) {
-            E current = getRaw(offset);
-            if (compareAndSetRaw(offset, current, newValue))
-                return current;
-        }
+        return (E)unsafe.getAndSetObject(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -197,7 +193,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, E expect, E update) {
         return compareAndSet(i, expect, update);
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Wed Jul 05 18:35:53 2017 +0200
@@ -116,7 +116,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public abstract boolean compareAndSet(T obj, V expect, V update);
 
@@ -134,7 +134,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
 
@@ -176,11 +176,11 @@
      * @return the previous value
      */
     public V getAndSet(T obj, V newValue) {
-        for (;;) {
-            V current = get(obj);
-            if (compareAndSet(obj, current, newValue))
-                return current;
-        }
+        V prev;
+        do {
+            prev = get(obj);
+        } while (!compareAndSet(obj, prev, newValue));
+        return prev;
     }
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
@@ -321,6 +321,15 @@
             return (V)unsafe.getObjectVolatile(obj, offset);
         }
 
+        @SuppressWarnings("unchecked")
+        public V getAndSet(T obj, V newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (newValue != null && vclass != null &&
+                 vclass != newValue.getClass()))
+                updateCheck(obj, newValue);
+            return (V)unsafe.getAndSetObject(obj, offset, newValue);
+        }
+
         private void ensureProtectedAccess(T obj) {
             if (cclass.isInstance(obj)) {
                 return;
--- a/jdk/src/share/classes/javax/crypto/Cipher.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/javax/crypto/Cipher.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -104,17 +104,30 @@
  * must be supplied to GCM/CCM implementations (via the {@code
  * updateAAD} methods) <b>before</b> the ciphertext is processed (via
  * the {@code update} and {@code doFinal} methods).
- *
+ * <p>
+ * Note that GCM mode has a uniqueness requirement on IVs used in
+ * encryption with a given key. When IVs are repeated for GCM
+ * encryption, such usages are subject to forgery attacks. Thus, after
+ * each encryption operation using GCM mode, callers should re-initialize
+ * the cipher objects with GCM parameters which has a different IV value.
  * <pre>
- *     GCMParameterSpec s = new GCMParameterSpec(...);
+ *     GCMParameterSpec s = ...;
  *     cipher.init(..., s);
  *
- *     // If the GCMParameterSpec is needed again
- *     cipher.getParameters().getParameterSpec(GCMParameterSpec.class));
+ *     // If the GCM parameters were generated by the provider, it can
+ *     // be retrieved by:
+ *     // cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
  *
  *     cipher.updateAAD(...);  // AAD
  *     cipher.update(...);     // Multi-part update
  *     cipher.doFinal(...);    // conclusion of operation
+ *
+ *     // Use a different IV value for every encryption
+ *     byte[] newIv = ...;
+ *     s = new GCMParameterSpec(s.getTLen(), newIv);
+ *     cipher.init(..., s);
+ *     ...
+ *
  * </pre>
  * Every implementation of the Java platform is required to support
  * the following standard <code>Cipher</code> transformations with the keysizes
--- a/jdk/src/share/classes/javax/crypto/spec/GCMParameterSpec.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/javax/crypto/spec/GCMParameterSpec.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -43,7 +43,7 @@
  * (Additional Authenticated Data (AAD), Keys, block ciphers,
  * plain/ciphertext and authentication tags) are handled in the {@code
  * Cipher} class.
-  <p>
+ * <p>
  * Please see <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116
  * </a> for more information on the Authenticated Encryption with
  * Associated Data (AEAD) algorithm, and <a href=
--- a/jdk/src/share/classes/javax/swing/JTable.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 18:35:53 2017 +0200
@@ -3953,7 +3953,7 @@
                     break;
                 case TableModelEvent.INSERT:
                     modelSelection.insertIndexInterval(change.startModelIndex,
-                                                       change.endModelIndex,
+                                                       change.length,
                                                        true);
                     break;
                 default:
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -409,6 +409,15 @@
             if (mainValue == null) {
                 abort(null, "java.launcher.jar.error3", jarname);
             }
+            /*
+             * Hand off to FXHelper if it detects a JavaFX application
+             * This must be done after ensuring a Main-Class entry
+             * exists to enforce compliance with the jar specification
+             */
+            if (mainAttrs.containsKey(
+                    new Attributes.Name(FXHelper.JAVAFX_APPLICATION_MARKER))) {
+                return FXHelper.class.getName();
+            }
             return mainValue.trim();
         } catch (IOException ioe) {
             abort(ioe, "java.launcher.jar.error1", jarname);
@@ -483,26 +492,23 @@
         } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
             abort(cnfe, "java.launcher.cls.error1", cn);
         }
-        // set to mainClass, FXHelper may return something else
+        // set to mainClass
         appClass = mainClass;
 
-        Method m = getMainMethod(mainClass);
-        if (m != null) {
-            // this will abort if main method has the wrong signature
-            validateMainMethod(m);
-            return mainClass;
+        /*
+         * Check if FXHelper can launch it using the FX launcher. In an FX app,
+         * the main class may or may not have a main method, so do this before
+         * validating the main class.
+         */
+        if (mainClass.equals(FXHelper.class) ||
+                FXHelper.doesExtendFXApplication(mainClass)) {
+            // Will abort() if there are problems with the FX runtime
+            FXHelper.setFXLaunchParameters(what, mode);
+            return FXHelper.class;
         }
 
-        // Check if FXHelper can launch it using the FX launcher
-        Class<?> fxClass = FXHelper.getFXMainClass(mainClass);
-        if (fxClass != null) {
-            return fxClass;
-        }
-
-        // not an FX application either, abort with an error
-        abort(null, "java.launcher.cls.error4", mainClass.getName(),
-              FXHelper.JAVAFX_APPLICATION_CLASS_NAME);
-        return null; // avoid compiler error...
+        validateMainClass(mainClass);
+        return mainClass;
     }
 
     /*
@@ -515,16 +521,18 @@
         return appClass;
     }
 
-    // Check for main method or return null if not found
-    static Method getMainMethod(Class<?> clazz) {
+    // Check the existence and signature of main and abort if incorrect
+    static void validateMainClass(Class<?> mainClass) {
+        Method mainMethod;
         try {
-            return clazz.getMethod("main", String[].class);
-        } catch (NoSuchMethodException nsme) {}
-        return null;
-    }
+            mainMethod = mainClass.getMethod("main", String[].class);
+        } catch (NoSuchMethodException nsme) {
+            // invalid main or not FX application, abort with an error
+            abort(null, "java.launcher.cls.error4", mainClass.getName(),
+                  FXHelper.JAVAFX_APPLICATION_CLASS_NAME);
+            return; // Avoid compiler issues
+        }
 
-    // Check the signature of main and abort if it's incorrect
-    static void validateMainMethod(Method mainMethod) {
         /*
          * getMethod (above) will choose the correct method, based
          * on its name and parameter type, however, we still have to
@@ -644,41 +652,78 @@
     }
 
     static final class FXHelper {
+        // Marker entry in jar manifest that designates a JavaFX application jar
+        private static final String JAVAFX_APPLICATION_MARKER =
+                "JavaFX-Application-Class";
         private static final String JAVAFX_APPLICATION_CLASS_NAME =
                 "javafx.application.Application";
         private static final String JAVAFX_LAUNCHER_CLASS_NAME =
                 "com.sun.javafx.application.LauncherImpl";
 
         /*
+         * The launch method used to invoke the JavaFX launcher. These must
+         * match the strings used in the launchApplication method.
+         *
+         * Command line                 JavaFX-App-Class  Launch mode  FX Launch mode
+         * java -cp fxapp.jar FXClass   N/A               LM_CLASS     "LM_CLASS"
+         * java -cp somedir FXClass     N/A               LM_CLASS     "LM_CLASS"
+         * java -jar fxapp.jar          Present           LM_JAR       "LM_JAR"
+         * java -jar fxapp.jar          Not Present       LM_JAR       "LM_JAR"
+         */
+        private static final String JAVAFX_LAUNCH_MODE_CLASS = "LM_CLASS";
+        private static final String JAVAFX_LAUNCH_MODE_JAR = "LM_JAR";
+
+        /*
          * FX application launcher and launch method, so we can launch
          * applications with no main method.
          */
+        private static String fxLaunchName = null;
+        private static String fxLaunchMode = null;
+
         private static Class<?> fxLauncherClass    = null;
         private static Method   fxLauncherMethod   = null;
 
         /*
-         * We can assume that the class does NOT have a main method or it would
-         * have been handled already. We do, however, need to check if the class
-         * extends Application and the launcher is available and abort with an
-         * error if it's not.
+         * Set the launch params according to what was passed to LauncherHelper
+         * so we can use the same launch mode for FX. Abort if there is any
+         * issue with loading the FX runtime or with the launcher method.
          */
-        private static Class<?> getFXMainClass(Class<?> mainClass) {
-            // Check if mainClass extends Application
-            if (!doesExtendFXApplication(mainClass)) {
-                return null;
-            }
-
+        private static void setFXLaunchParameters(String what, int mode) {
             // Check for the FX launcher classes
             try {
                 fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME);
+                /*
+                 * signature must be:
+                 * public static void launchApplication(String launchName,
+                 *     String launchMode, String[] args);
+                 */
                 fxLauncherMethod = fxLauncherClass.getMethod("launchApplication",
-                        Class.class, String[].class);
+                        String.class, String.class, String[].class);
+
+                // verify launcher signature as we do when validating the main method
+                int mod = fxLauncherMethod.getModifiers();
+                if (!Modifier.isStatic(mod)) {
+                    abort(null, "java.launcher.javafx.error1");
+                }
+                if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) {
+                    abort(null, "java.launcher.javafx.error1");
+                }
             } catch (ClassNotFoundException | NoSuchMethodException ex) {
                 abort(ex, "java.launcher.cls.error5", ex);
             }
 
-            // That's all, return this class so we can launch later
-            return FXHelper.class;
+            fxLaunchName = what;
+            switch (mode) {
+                case LM_CLASS:
+                    fxLaunchMode = JAVAFX_LAUNCH_MODE_CLASS;
+                    break;
+                case LM_JAR:
+                    fxLaunchMode = JAVAFX_LAUNCH_MODE_JAR;
+                    break;
+                default:
+                    // should not have gotten this far...
+                    throw new InternalError(mode + ": Unknown launch mode");
+            }
         }
 
         /*
@@ -696,11 +741,15 @@
             return false;
         }
 
-        // preloader ?
         public static void main(String... args) throws Exception {
+            if (fxLauncherMethod == null
+                    || fxLaunchMode == null
+                    || fxLaunchName == null) {
+                throw new RuntimeException("Invalid JavaFX launch parameters");
+            }
             // launch appClass via fxLauncherMethod
-            fxLauncherMethod.invoke(null, new Object[] {appClass, args});
+            fxLauncherMethod.invoke(null,
+                    new Object[] {fxLaunchName, fxLaunchMode, args});
         }
     }
 }
-
--- a/jdk/src/share/classes/sun/launcher/resources/launcher.properties	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/launcher/resources/launcher.properties	Wed Jul 05 18:35:53 2017 +0200
@@ -140,3 +140,6 @@
 java.launcher.jar.error2=manifest not found in {0}
 java.launcher.jar.error3=no main manifest attribute, in {0}
 java.launcher.init.error=initialization error
+java.launcher.javafx.error1=\
+    Error: The JavaFX launchApplication method has the wrong signature, it\n\
+    must be declared static and return a value of type void
--- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java	Wed Jul 05 18:35:53 2017 +0200
@@ -206,7 +206,8 @@
 
             if(v == null) {
                 if ((v=schemes.get ("digest")) == null) {
-                    if (((v=schemes.get("ntlm"))==null)) {
+                    if (!NTLMAuthenticationProxy.supported
+                        || ((v=schemes.get("ntlm"))==null)) {
                         v = schemes.get ("basic");
                     }
                 }
--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Wed Jul 05 18:35:53 2017 +0200
@@ -86,7 +86,7 @@
      * For the context acceptor to call. It reads the bytes out of an
      * InputStream and constructs an InitSecContextToken with them.
      */
-    InitSecContextToken(Krb5Context context, EncryptionKey[] keys,
+    InitSecContextToken(Krb5Context context, Krb5AcceptCredential cred,
                                InputStream is)
         throws IOException, GSSException, KrbException  {
 
@@ -105,7 +105,7 @@
         if (context.getChannelBinding() != null) {
             addr = context.getChannelBinding().getInitiatorAddress();
         }
-        apReq = new KrbApReq(apReqBytes, keys, addr);
+        apReq = new KrbApReq(apReqBytes, cred, addr);
         //debug("\nReceived AP-REQ and authenticated it.\n");
 
         EncryptionKey sessionKey = apReq.getCreds().getSessionKey();
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java	Wed Jul 05 18:35:53 2017 +0200
@@ -45,13 +45,10 @@
 public class Krb5AcceptCredential
     implements Krb5CredElement {
 
-    private static final long serialVersionUID = 7714332137352567952L;
-
-    private Krb5NameElement name;
+    private final Krb5NameElement name;
+    private final ServiceCreds screds;
 
-    private Krb5Util.ServiceCreds screds;
-
-    private Krb5AcceptCredential(Krb5NameElement name, Krb5Util.ServiceCreds creds) {
+    private Krb5AcceptCredential(Krb5NameElement name, ServiceCreds creds) {
         /*
          * Initialize this instance with the data from the acquired
          * KerberosKey. This class needs to be a KerberosKey too
@@ -69,11 +66,11 @@
             name.getKrb5PrincipalName().getName());
         final AccessControlContext acc = AccessController.getContext();
 
-        Krb5Util.ServiceCreds creds = null;
+        ServiceCreds creds = null;
         try {
             creds = AccessController.doPrivileged(
-                        new PrivilegedExceptionAction<Krb5Util.ServiceCreds>() {
-                public Krb5Util.ServiceCreds run() throws Exception {
+                        new PrivilegedExceptionAction<ServiceCreds>() {
+                public ServiceCreds run() throws Exception {
                     return Krb5Util.getServiceCreds(
                         caller == GSSCaller.CALLER_UNKNOWN ? GSSCaller.CALLER_ACCEPT: caller,
                         serverPrinc, acc);
@@ -92,8 +89,10 @@
 
         if (name == null) {
             String fullName = creds.getName();
-            name = Krb5NameElement.getInstance(fullName,
+            if (fullName != null) {
+                name = Krb5NameElement.getInstance(fullName,
                                        Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
+            }
         }
 
         return new Krb5AcceptCredential(name, creds);
@@ -153,8 +152,8 @@
         return Krb5MechFactory.PROVIDER;
     }
 
-    EncryptionKey[] getKrb5EncryptionKeys() {
-        return screds.getEKeys();
+    public EncryptionKey[] getKrb5EncryptionKeys(PrincipalName princ) {
+        return screds.getEKeys(princ);
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java	Wed Jul 05 18:35:53 2017 +0200
@@ -818,16 +818,23 @@
                 }
                 myName = (Krb5NameElement) myCred.getName();
 
-                checkPermission(myName.getKrb5PrincipalName().getName(),
-                                "accept");
-
-                EncryptionKey[] secretKeys =
-                 ((Krb5AcceptCredential) myCred).getKrb5EncryptionKeys();
+                // If there is already a bound name, check now
+                if (myName != null) {
+                    Krb5MechFactory.checkAcceptCredPermission(myName, myName);
+                }
 
                 InitSecContextToken token = new InitSecContextToken(this,
-                                                    secretKeys, is);
+                                                    (Krb5AcceptCredential) myCred, is);
                 PrincipalName clientName = token.getKrbApReq().getClient();
                 peerName = Krb5NameElement.getInstance(clientName);
+
+                // If unbound, check after the bound name is found
+                if (myName == null) {
+                    myName = Krb5NameElement.getInstance(
+                        token.getKrbApReq().getCreds().getServer());
+                    Krb5MechFactory.checkAcceptCredPermission(myName, myName);
+                }
+
                 if (getMutualAuthState()) {
                         retVal = new AcceptSecContextToken(this,
                                           token.getKrbApReq()).encode();
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java	Wed Jul 05 18:35:53 2017 +0200
@@ -158,7 +158,7 @@
     public static void checkAcceptCredPermission(Krb5NameElement name,
                                            GSSNameSpi originalName) {
         SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
+        if (sm != null && name != null) {
             ServicePermission perm = new ServicePermission
                 (name.getKrb5PrincipalName().getName(), "accept");
             try {
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java	Wed Jul 05 18:35:53 2017 +0200
@@ -187,114 +187,6 @@
     }
 
     /**
-     * Credentials of a service, the private secret to authenticate its
-     * identity, which can be:
-     *   1. Some KerberosKeys (generated from password)
-     *   2. A KeyTab (for a typical service)
-     *   3. A TGT (for S4U2proxy extension)
-     *
-     * Note that some creds can coexist. For example, a user2user service
-     * can use its keytab (or keys) if the client can successfully obtain a
-     * normal service ticket, otherwise, it can uses the TGT (actually, the
-     * session key of the TGT) if the client can only acquire a service ticket
-     * of ENC-TKT-IN-SKEY style.
-     */
-    public static class ServiceCreds {
-        private KerberosPrincipal kp;
-        private List<KeyTab> ktabs;
-        private List<KerberosKey> kk;
-        private Subject subj;
-        private KerberosTicket tgt;
-
-        private static ServiceCreds getInstance(
-                Subject subj, String serverPrincipal) {
-
-            ServiceCreds sc = new ServiceCreds();
-            sc.subj = subj;
-
-            for (KerberosPrincipal p: subj.getPrincipals(KerberosPrincipal.class)) {
-                if (serverPrincipal == null ||
-                        p.getName().equals(serverPrincipal)) {
-                    sc.kp = p;
-                    serverPrincipal = p.getName();
-                    break;
-                }
-            }
-            if (sc.kp == null) {
-                // Compatibility with old behavior: even when there is no
-                // KerberosPrincipal, we can find one from KerberosKeys
-                List<KerberosKey> keys = SubjectComber.findMany(
-                        subj, serverPrincipal, null, KerberosKey.class);
-                if (!keys.isEmpty()) {
-                    sc.kp = keys.get(0).getPrincipal();
-                    serverPrincipal = sc.kp.getName();
-                    if (DEBUG) {
-                        System.out.println(">>> ServiceCreds: no kp?"
-                                + " find one from kk: " + serverPrincipal);
-                    }
-                } else {
-                    return null;
-                }
-            }
-            sc.ktabs = SubjectComber.findMany(
-                        subj, null, null, KeyTab.class);
-            sc.kk = SubjectComber.findMany(
-                        subj, serverPrincipal, null, KerberosKey.class);
-            sc.tgt = SubjectComber.find(
-                    subj, null, serverPrincipal, KerberosTicket.class);
-            if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) {
-                return null;
-            }
-            return sc;
-        }
-
-        public String getName() {
-            return kp.getName();
-        }
-
-        public KerberosKey[] getKKeys() {
-            List<KerberosKey> keys = new ArrayList<>();
-            for (KerberosKey k: kk) {
-                keys.add(k);
-            }
-            for (KeyTab ktab: ktabs) {
-                for (KerberosKey k: ktab.getKeys(kp)) {
-                    keys.add(k);
-                }
-            }
-            return keys.toArray(new KerberosKey[keys.size()]);
-        }
-
-        public EncryptionKey[] getEKeys() {
-            KerberosKey[] kkeys = getKKeys();
-            EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];
-            for (int i=0; i<ekeys.length; i++) {
-                ekeys[i] =  new EncryptionKey(
-                            kkeys[i].getEncoded(), kkeys[i].getKeyType(),
-                            new Integer(kkeys[i].getVersionNumber()));
-            }
-            return ekeys;
-        }
-
-        public Credentials getInitCred() {
-            if (tgt == null) {
-                return null;
-            }
-            try {
-                return ticketToCreds(tgt);
-            } catch (KrbException | IOException e) {
-                return null;
-            }
-        }
-
-        public void destroy() {
-            kp = null;
-            ktabs = null;
-            kk = null;
-            tgt = null;
-        }
-    }
-    /**
      * Retrieves the ServiceCreds for the specified server principal from
      * the Subject in the specified AccessControlContext. If not found, and if
      * useSubjectCredsOnly is false, then obtain from a LoginContext.
@@ -361,5 +253,4 @@
         return KerberosSecrets.getJavaxSecurityAuthKerberosAccess().
                 keyTabGetEncryptionKeys(ktab, cname);
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2012, 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.jgss.krb5;
+
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+import javax.security.auth.Subject;
+
+import sun.security.krb5.Credentials;
+import sun.security.krb5.EncryptionKey;
+import sun.security.krb5.KrbException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import sun.security.krb5.*;
+import sun.security.krb5.internal.Krb5;
+
+/**
+ * Credentials of a kerberos acceptor. A KerberosPrincipal object (kp) is
+ * the principal. It can be specified as the serverPrincipal argument
+ * in the getInstance() method, or uses only KerberosPrincipal in the subject.
+ * Otherwise, the creds object is unbound and kp is null.
+ *
+ * The class also encapsulates various secrets, which can be:
+ *
+ *   1. Some KerberosKeys (generated from password)
+ *   2. Some KeyTabs (for a typical service based on keytabs)
+ *   3. A TGT (for S4U2proxy extension or user2user)
+ *
+ * Note that some secrets can coexist. For example, a user2user service
+ * can use its keytab (or keys) if the client can successfully obtain a
+ * normal service ticket, or it can use the TGT (actually, the session key
+ * of the TGT) if the client can only acquire a service ticket
+ * of ENC-TKT-IN-SKEY style.
+ *
+ * @since 1.8
+ */
+public final class ServiceCreds {
+    // The principal, or null if unbound
+    private KerberosPrincipal kp;
+
+    // All principals in the subject's princ set
+    private Set<KerberosPrincipal> allPrincs;
+
+    // All private credentials that can be used
+    private List<KeyTab> ktabs;
+    private List<KerberosKey> kk;
+    private KerberosTicket tgt;
+
+    private boolean destroyed;
+
+    private ServiceCreds() {
+        // Make sure this class cannot be instantiated externally.
+    }
+
+    /**
+     * Creates a ServiceCreds object based on info in a Subject for
+     * a given principal name (if specified).
+     * @return the object, or null if there is no private creds for it
+     */
+    public static ServiceCreds getInstance(
+            Subject subj, String serverPrincipal) {
+
+        ServiceCreds sc = new ServiceCreds();
+
+        sc.allPrincs =
+                subj.getPrincipals(KerberosPrincipal.class);
+
+        // Compatibility. A key implies its own principal
+        for (KerberosKey key: SubjectComber.findMany(
+                subj, serverPrincipal, null, KerberosKey.class)) {
+            sc.allPrincs.add(key.getPrincipal());
+        }
+
+        if (serverPrincipal != null) {      // A named principal
+            sc.kp = new KerberosPrincipal(serverPrincipal);
+        } else {
+            if (sc.allPrincs.size() == 1) { // choose the only one
+                sc.kp = sc.allPrincs.iterator().next();
+                serverPrincipal = sc.kp.getName();
+            }
+        }
+
+        sc.ktabs = SubjectComber.findMany(
+                    subj, serverPrincipal, null, KeyTab.class);
+        sc.kk = SubjectComber.findMany(
+                    subj, serverPrincipal, null, KerberosKey.class);
+        sc.tgt = SubjectComber.find(
+                subj, null, serverPrincipal, KerberosTicket.class);
+        if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) {
+            return null;
+        }
+
+        sc.destroyed = false;
+
+        return sc;
+    }
+
+    // can be null
+    public String getName() {
+        if (destroyed) {
+            throw new IllegalStateException("This object is destroyed");
+        }
+        return kp == null ? null : kp.getName();
+    }
+
+    /**
+     * Gets keys for someone unknown.
+     * Used by TLS or as a fallback in getEKeys(). Can still return an
+     * empty array.
+     */
+    public KerberosKey[] getKKeys() {
+        if (destroyed) {
+            throw new IllegalStateException("This object is destroyed");
+        }
+        if (kp != null) {
+            return getKKeys(kp);
+        } else if (!allPrincs.isEmpty()) {
+            return getKKeys(allPrincs.iterator().next());
+        }
+        return new KerberosKey[0];
+    }
+
+    /**
+     * Get kkeys for a principal,
+     * @param princ the target name initiator requests. Not null.
+     * @return keys for the princ, never null, might be empty
+     */
+    private KerberosKey[] getKKeys(KerberosPrincipal princ) {
+        ArrayList<KerberosKey> keys = new ArrayList<>();
+        if (kp != null && !princ.equals(kp)) {
+            return new KerberosKey[0];      // Not me
+        }
+        if (!allPrincs.contains(princ)) {
+            return new KerberosKey[0];      // Not someone I know, This check
+                                            // is necessary but a KeyTab has
+                                            // no principal name recorded.
+        }
+        for (KerberosKey k: kk) {
+            if (k.getPrincipal().equals(princ)) {
+                keys.add(k);
+            }
+        }
+        for (KeyTab ktab: ktabs) {
+            for (KerberosKey k: ktab.getKeys(princ)) {
+                keys.add(k);
+            }
+        }
+        return keys.toArray(new KerberosKey[keys.size()]);
+    }
+
+    /**
+     * Gets EKeys for a principal.
+     * @param princ the target name initiator requests. Not null.
+     * @return keys for the princ, never null, might be empty
+     */
+    public EncryptionKey[] getEKeys(PrincipalName princ) {
+        if (destroyed) {
+            throw new IllegalStateException("This object is destroyed");
+        }
+        KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName()));
+        if (kkeys.length == 0) {
+            // Note: old JDK does not perform real name checking. If the
+            // acceptor starts by name A but initiator requests for B,
+            // as long as their keys match (i.e. A's keys can decrypt B's
+            // service ticket), the authentication is OK. There are real
+            // customers depending on this to use different names for a
+            // single service.
+            kkeys = getKKeys();
+        }
+        EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];
+        for (int i=0; i<ekeys.length; i++) {
+            ekeys[i] =  new EncryptionKey(
+                        kkeys[i].getEncoded(), kkeys[i].getKeyType(),
+                        new Integer(kkeys[i].getVersionNumber()));
+        }
+        return ekeys;
+    }
+
+    public Credentials getInitCred() {
+        if (destroyed) {
+            throw new IllegalStateException("This object is destroyed");
+        }
+        if (tgt == null) {
+            return null;
+        }
+        try {
+            return Krb5Util.ticketToCreds(tgt);
+        } catch (KrbException | IOException e) {
+            return null;
+        }
+    }
+
+    public void destroy() {
+        // Do not wipe out real keys because they are references to the
+        // priv creds in subject. Just make it useless.
+        destroyed = true;
+        kp = null;
+        ktabs.clear();
+        kk.clear();
+        tgt = null;
+    }
+}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java	Wed Jul 05 18:35:53 2017 +0200
@@ -33,6 +33,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.kerberos.KeyTab;
 
 /**
@@ -84,19 +85,37 @@
         } else {
             List<T> answer = (oneOnly ? null : new ArrayList<T>());
 
-            if (credClass == KeyTab.class) {    // Principal un-related
-                // We are looking for credentials unrelated to serverPrincipal
-                Iterator<T> iterator =
-                    subject.getPrivateCredentials(credClass).iterator();
-                while (iterator.hasNext()) {
-                    T t = iterator.next();
-                    if (DEBUG) {
-                        System.out.println("Found " + credClass.getSimpleName());
+            if (credClass == KeyTab.class) {
+                // TODO: There is currently no good way to filter out keytabs
+                // not for serverPrincipal. We can only check the principal
+                // set. If the server is not there, we can be sure none of the
+                // keytabs should be used, otherwise, use all for safety.
+                boolean useAll = false;
+                if (serverPrincipal != null) {
+                    for (KerberosPrincipal princ:
+                            subject.getPrincipals(KerberosPrincipal.class)) {
+                        if (princ.getName().equals(serverPrincipal)) {
+                            useAll = true;
+                            break;
+                        }
                     }
-                    if (oneOnly) {
-                        return t;
-                    } else {
-                        answer.add(t);
+                } else {
+                    useAll = true;
+                }
+                if (useAll) {
+                    Iterator<KeyTab> iterator =
+                        subject.getPrivateCredentials(KeyTab.class).iterator();
+                    while (iterator.hasNext()) {
+                        KeyTab t = iterator.next();
+                        if (DEBUG) {
+                            System.out.println("Found " + credClass.getSimpleName()
+                                    + " " + t);
+                        }
+                        if (oneOnly) {
+                            return t;
+                        } else {
+                            answer.add(credClass.cast(t));
+                        }
                     }
                 }
             } else if (credClass == KerberosKey.class) {
@@ -114,11 +133,6 @@
                          if (oneOnly) {
                              return t;
                          } else {
-                             if (serverPrincipal == null) {
-                                 // Record name so that keys returned will all
-                                 // belong to the same principal
-                                 serverPrincipal = name;
-                             }
                              answer.add(credClass.cast(t));
                          }
                     }
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Wed Jul 05 18:35:53 2017 +0200
@@ -34,6 +34,7 @@
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
 import sun.security.krb5.internal.rcache.*;
+import sun.security.jgss.krb5.Krb5AcceptCredential;
 import java.net.InetAddress;
 import sun.security.util.*;
 import java.io.IOException;
@@ -135,13 +136,13 @@
      */
      // Used in InitSecContextToken (for AP_REQ and not TGS REQ)
     public KrbApReq(byte[] message,
-                    EncryptionKey[] keys,
+                    Krb5AcceptCredential cred,
                     InetAddress initiator)
         throws KrbException, IOException {
         obuf = message;
         if (apReqMessg == null)
             decode();
-        authenticate(keys, initiator);
+        authenticate(cred, initiator);
     }
 
     /**
@@ -260,10 +261,11 @@
         }
     }
 
-    private void authenticate(EncryptionKey[] keys, InetAddress initiator)
+    private void authenticate(Krb5AcceptCredential cred, InetAddress initiator)
         throws KrbException, IOException {
         int encPartKeyType = apReqMessg.ticket.encPart.getEType();
         Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
+        EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname);
         EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
 
         if (dkey == null) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 18:35:53 2017 +0200
@@ -382,9 +382,15 @@
      */
     public void addEntry(PrincipalName service, char[] psswd,
             int kvno, boolean append) throws KrbException {
+        addEntry(service, service.getSalt(), psswd, kvno, append);
+    }
+
+    // Called by KDC test
+    public void addEntry(PrincipalName service, String salt, char[] psswd,
+            int kvno, boolean append) throws KrbException {
 
         EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
-            psswd, service.getSalt());
+            psswd, salt);
 
         // There should be only one maximum KVNO value for all etypes, so that
         // all added keys can have the same KVNO.
--- a/jdk/src/share/classes/sun/security/provider/PolicyFile.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java	Wed Jul 05 18:35:53 2017 +0200
@@ -31,13 +31,7 @@
 import java.net.URL;
 import java.net.URI;
 import java.util.*;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.ArrayList;
-import java.util.ListIterator;
 import java.text.MessageFormat;
-import com.sun.security.auth.PrincipalComparator;
 import java.security.*;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
@@ -46,19 +40,7 @@
 import java.io.FilePermission;
 import java.net.SocketPermission;
 import java.net.NetPermission;
-import java.util.PropertyPermission;
 import java.util.concurrent.atomic.AtomicReference;
-/*
-import javax.security.auth.AuthPermission;
-import javax.security.auth.kerberos.ServicePermission;
-import javax.security.auth.kerberos.DelegationPermission;
-import java.io.SerializablePermission;
-import java.util.logging.LoggingPermission;
-import java.sql.SQLPermission;
-import java.lang.reflect.ReflectPermission;
-import javax.sound.sampled.AudioPermission;
-import javax.net.ssl.SSLPermission;
-*/
 import sun.misc.JavaSecurityProtectionDomainAccess;
 import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
 import sun.misc.SharedSecrets;
@@ -794,12 +776,9 @@
             debug.println("Adding policy entry: ");
             debug.println("  signedBy " + ge.signedBy);
             debug.println("  codeBase " + ge.codeBase);
-            if (ge.principals != null && ge.principals.size() > 0) {
-                ListIterator<PolicyParser.PrincipalEntry> li =
-                                                ge.principals.listIterator();
-                while (li.hasNext()) {
-                    PolicyParser.PrincipalEntry pppe = li.next();
-                debug.println("  " + pppe.toString());
+            if (ge.principals != null) {
+                for (PolicyParser.PrincipalEntry pppe : ge.principals) {
+                    debug.println("  " + pppe.toString());
                 }
             }
         }
@@ -955,11 +934,15 @@
                InvocationTargetException
     {
         //XXX we might want to keep a hash of created factories...
-        Class<?> pc = Class.forName(type);
+        Class<?> pc = Class.forName(type, false, null);
         Permission answer = getKnownInstance(pc, name, actions);
         if (answer != null) {
             return answer;
         }
+        if (!Permission.class.isAssignableFrom(pc)) {
+            // not the right subtype
+            throw new ClassCastException(type + " is not a Permission");
+        }
 
         if (name == null && actions == null) {
             try {
@@ -1001,7 +984,6 @@
      */
     private static final Permission getKnownInstance(Class<?> claz,
         String name, String actions) {
-        // XXX shorten list to most popular ones?
         if (claz.equals(FilePermission.class)) {
             return new FilePermission(name, actions);
         } else if (claz.equals(SocketPermission.class)) {
@@ -1014,30 +996,6 @@
             return new NetPermission(name, actions);
         } else if (claz.equals(AllPermission.class)) {
             return SecurityConstants.ALL_PERMISSION;
-/*
-        } else if (claz.equals(ReflectPermission.class)) {
-            return new ReflectPermission(name, actions);
-        } else if (claz.equals(SecurityPermission.class)) {
-            return new SecurityPermission(name, actions);
-        } else if (claz.equals(PrivateCredentialPermission.class)) {
-            return new PrivateCredentialPermission(name, actions);
-        } else if (claz.equals(AuthPermission.class)) {
-            return new AuthPermission(name, actions);
-        } else if (claz.equals(ServicePermission.class)) {
-            return new ServicePermission(name, actions);
-        } else if (claz.equals(DelegationPermission.class)) {
-            return new DelegationPermission(name, actions);
-        } else if (claz.equals(SerializablePermission.class)) {
-            return new SerializablePermission(name, actions);
-        } else if (claz.equals(AudioPermission.class)) {
-            return new AudioPermission(name, actions);
-        } else if (claz.equals(SSLPermission.class)) {
-            return new SSLPermission(name, actions);
-        } else if (claz.equals(LoggingPermission.class)) {
-            return new LoggingPermission(name, actions);
-        } else if (claz.equals(SQLPermission.class)) {
-            return new SQLPermission(name, actions);
-*/
         } else {
             return null;
         }
@@ -1079,7 +1037,7 @@
 
             if (cert != null) {
                 if (vcerts == null)
-                    vcerts = new ArrayList<Certificate>();
+                    vcerts = new ArrayList<>();
                 vcerts.add(cert);
             }
         }
@@ -1329,7 +1287,7 @@
 
         List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
         if (debug != null) {
-            ArrayList<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
+            List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
             if (principals != null) {
                 for (int i = 0; i < principals.length; i++) {
                     accPs.add(new PolicyParser.PrincipalEntry
@@ -1368,79 +1326,72 @@
         // has principals.  see if policy entry principals match
         // principals in current ACC
 
-        for (int i = 0; i < entryPs.size(); i++) {
-            PolicyParser.PrincipalEntry pppe = entryPs.get(i);
+        for (PolicyParser.PrincipalEntry pppe : entryPs) {
 
-            // see if principal entry is a PrincipalComparator
+            // Check for wildcards
+            if (pppe.isWildcardClass()) {
+                // a wildcard class matches all principals in current ACC
+                continue;
+            }
 
-            try {
-                Class<?> pClass = Class.forName
-                                (pppe.principalClass,
-                                true,
-                                Thread.currentThread().getContextClassLoader());
+            if (pppe.isWildcardName()) {
+                // a wildcard name matches any principal with the same class
+                for (Principal p : principals) {
+                    if (pppe.principalClass.equals(p.getClass().getName())) {
+                        continue;
+                    }
+                }
+                if (debug != null) {
+                    debug.println("evaluation (principal name wildcard) failed");
+                }
+                // policy entry principal not in current ACC -
+                // immediately return and go to next policy entry
+                return;
+            }
 
-                if (!PrincipalComparator.class.isAssignableFrom(pClass)) {
-
-                    // common case - dealing with regular Principal class.
-                    // see if policy entry principal is in current ACC
+            Set<Principal> pSet = new HashSet<>(Arrays.asList(principals));
+            Subject subject = new Subject(true, pSet,
+                                          Collections.EMPTY_SET,
+                                          Collections.EMPTY_SET);
+            try {
+                ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                Class<?> pClass = Class.forName(pppe.principalClass, false, cl);
+                if (!Principal.class.isAssignableFrom(pClass)) {
+                    // not the right subtype
+                    throw new ClassCastException(pppe.principalClass +
+                                                 " is not a Principal");
+                }
 
-                    if (!checkEntryPs(principals, pppe)) {
-                        if (debug != null) {
-                            debug.println("evaluation (principals) failed");
-                        }
+                Constructor<?> c = pClass.getConstructor(PARAMS1);
+                Principal p = (Principal)c.newInstance(new Object[] {
+                                                       pppe.principalName });
 
-                        // policy entry principal not in current ACC -
-                        // immediately return and go to next policy entry
-                        return;
+                if (debug != null) {
+                    debug.println("found Principal " + p.getClass().getName());
+                }
+
+                // check if the Principal implies the current
+                // thread's principals
+                if (!p.implies(subject)) {
+                    if (debug != null) {
+                        debug.println("evaluation (principal implies) failed");
                     }
 
-                } else {
-
-                    // dealing with a PrincipalComparator
-
-                    Constructor<?> c = pClass.getConstructor(PARAMS1);
-                    PrincipalComparator pc = (PrincipalComparator)c.newInstance
-                                        (new Object[] { pppe.principalName });
-
-                    if (debug != null) {
-                        debug.println("found PrincipalComparator " +
-                                        pc.getClass().getName());
-                    }
-
-                    // check if the PrincipalComparator
-                    // implies the current thread's principals
-
-                    Set<Principal> pSet = new HashSet<>(principals.length);
-                    for (int j = 0; j < principals.length; j++) {
-                        pSet.add(principals[j]);
-                    }
-                    Subject subject = new Subject(true,
-                                                pSet,
-                                                Collections.EMPTY_SET,
-                                                Collections.EMPTY_SET);
-
-                    if (!pc.implies(subject)) {
-                        if (debug != null) {
-                            debug.println
-                                ("evaluation (principal comparator) failed");
-                        }
-
-                        // policy principal does not imply the current Subject -
-                        // immediately return and go to next policy entry
-                        return;
-                    }
+                    // policy principal does not imply the current Subject -
+                    // immediately return and go to next policy entry
+                    return;
                 }
             } catch (Exception e) {
-                // fall back to regular principal comparison.
+                // fall back to default principal comparison.
                 // see if policy entry principal is in current ACC
 
                 if (debug != null) {
                     e.printStackTrace();
                 }
 
-                if (!checkEntryPs(principals, pppe)) {
+                if (!pppe.implies(subject)) {
                     if (debug != null) {
-                        debug.println("evaluation (principals) failed");
+                        debug.println("evaluation (default principal implies) failed");
                     }
 
                     // policy entry principal not in current ACC -
@@ -1450,7 +1401,7 @@
             }
 
             // either the principal information matched,
-            // or the PrincipalComparator.implies succeeded.
+            // or the Principal.implies succeeded.
             // continue loop and test the next policy principal
         }
 
@@ -1485,47 +1436,6 @@
     }
 
     /**
-     * This method returns, true, if the principal in the policy entry,
-     * pppe, is part of the current thread's principal array, pList.
-     * This method also returns, true, if the policy entry's principal
-     * is appropriately wildcarded.
-     *
-     * Note that the provided <i>pppe</i> argument may have
-     * wildcards (*) for both the <code>Principal</code> class and name.
-     *
-     * @param pList an array of principals from the current thread's
-     *          AccessControlContext.
-     *
-     * @param pppe a Principal specified in a policy grant entry.
-     *
-     * @return true if the current thread's pList "contains" the
-     *          principal in the policy entry, pppe.  This method
-     *          also returns true if the policy entry's principal
-     *          appropriately wildcarded.
-     */
-    private boolean checkEntryPs(Principal[] pList,
-                                PolicyParser.PrincipalEntry pppe) {
-
-        for (int i = 0; i < pList.length; i++) {
-
-            if (pppe.principalClass.equals
-                        (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
-                pppe.principalClass.equals
-                        (pList[i].getClass().getName())) {
-
-                if (pppe.principalName.equals
-                        (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
-                    pppe.principalName.equals
-                        (pList[i].getName())) {
-
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
      * <p>
      *
      * @param sp the SelfPermission that needs to be expanded <p>
@@ -1568,8 +1478,7 @@
             sb.append(sp.getSelfName().substring(startIndex, v));
 
             // expand SELF
-            ListIterator<PolicyParser.PrincipalEntry> pli =
-                                                entryPs.listIterator();
+            Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator();
             while (pli.hasNext()) {
                 PolicyParser.PrincipalEntry pppe = pli.next();
                 String[][] principalInfo = getPrincipalInfo(pppe,pdp);
@@ -1596,8 +1505,8 @@
         try {
             // first try to instantiate the permission
             perms.add(getInstance(sp.getSelfType(),
-                                sb.toString(),
-                                sp.getSelfActions()));
+                                  sb.toString(),
+                                  sp.getSelfActions()));
         } catch (ClassNotFoundException cnfe) {
             // ok, the permission is not in the bootclasspath.
             // before we add an UnresolvedPermission, check to see
@@ -1673,10 +1582,7 @@
         // 2) the entry's Principal name is wildcarded only
         // 3) the entry's Principal class and name are wildcarded
 
-        if (!pe.principalClass.equals
-            (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
-            !pe.principalName.equals
-            (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
+        if (!pe.isWildcardClass() && !pe.isWildcardName()) {
 
             // build an info array for the principal
             // from the Policy entry
@@ -1685,24 +1591,19 @@
             info[0][1] = pe.principalName;
             return info;
 
-        } else if (!pe.principalClass.equals
-                   (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
-                   pe.principalName.equals
-                   (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
+        } else if (!pe.isWildcardClass() && pe.isWildcardName()) {
 
             // build an info array for every principal
             // in the current domain which has a principal class
             // that is equal to policy entry principal class name
             List<Principal> plist = new ArrayList<>();
             for (int i = 0; i < pdp.length; i++) {
-                if(pe.principalClass.equals(pdp[i].getClass().getName()))
+                if (pe.principalClass.equals(pdp[i].getClass().getName()))
                     plist.add(pdp[i]);
             }
             String[][] info = new String[plist.size()][2];
             int i = 0;
-            java.util.Iterator<Principal> pIterator = plist.iterator();
-            while (pIterator.hasNext()) {
-                Principal p = pIterator.next();
+            for (Principal p : plist) {
                 info[i][0] = p.getClass().getName();
                 info[i][1] = p.getName();
                 i++;
@@ -1763,7 +1664,7 @@
             // Done
             return certs;
 
-        ArrayList<Certificate> userCertList = new ArrayList<>();
+        List<Certificate> userCertList = new ArrayList<>();
         i = 0;
         while (i < certs.length) {
             userCertList.add(certs[i]);
@@ -1889,10 +1790,8 @@
         if (principals == null || principals.isEmpty() || keystore == null)
             return true;
 
-        ListIterator<PolicyParser.PrincipalEntry> i = principals.listIterator();
-        while (i.hasNext()) {
-            PolicyParser.PrincipalEntry pppe = i.next();
-            if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {
+        for (PolicyParser.PrincipalEntry pppe : principals) {
+            if (pppe.isReplaceName()) {
 
                 // perform replacement
                 // (only X509 replacement is possible now)
@@ -2241,8 +2140,7 @@
 
                     if (this.certs == null) {
                         // extract the signer certs
-                        ArrayList<Certificate> signerCerts =
-                            new ArrayList<>();
+                        List<Certificate> signerCerts = new ArrayList<>();
                         i = 0;
                         while (i < certs.length) {
                             signerCerts.add(certs[i]);
@@ -2406,11 +2304,10 @@
         private java.util.Random random;
 
         PolicyInfo(int numCaches) {
-            policyEntries = new ArrayList<PolicyEntry>();
+            policyEntries = new ArrayList<>();
             identityPolicyEntries =
                 Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
-            aliasMapping = Collections.synchronizedMap(
-                    new HashMap<Object, Object>(11));
+            aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
 
             pdMapping = new ProtectionDomainCache[numCaches];
             JavaSecurityProtectionDomainAccess jspda
--- a/jdk/src/share/classes/sun/security/provider/PolicyParser.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/provider/PolicyParser.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,16 +29,17 @@
 import java.lang.RuntimePermission;
 import java.net.SocketPermission;
 import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.text.MessageFormat;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.ListIterator;
 import java.util.Vector;
 import java.util.StringTokenizer;
-import java.text.MessageFormat;
 import javax.security.auth.x500.X500Principal;
 
-import java.security.GeneralSecurityException;
 import sun.security.util.Debug;
 import sun.security.util.PropertyExpander;
 import sun.security.util.ResourcesMgr;
@@ -72,7 +73,7 @@
  *  Permissions perms = policy.getPermissions(protectiondomain)
  * </pre>
  *
- * <p>The protection domain contains CodeSource
+ * <p>The protection domain contains a CodeSource
  * object, which encapsulates its codebase (URL) and public key attributes.
  * It also contains the principals associated with the domain.
  * The Policy object evaluates the global policy in light of who the
@@ -87,9 +88,6 @@
 
 public class PolicyParser {
 
-    // needs to be public for PolicyTool
-    public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME";
-
     private static final String EXTDIRS_PROPERTY = "java.ext.dirs";
     private static final String OLD_EXTDIRS_EXPANSION =
         "${" + EXTDIRS_PROPERTY + "}";
@@ -452,7 +450,7 @@
                 peekAndMatch(",");
             } else if (peekAndMatch("Principal")) {
                 if (principals == null) {
-                    principals = new LinkedList<PrincipalEntry>();
+                    principals = new LinkedList<>();
                 }
 
                 String principalClass;
@@ -461,7 +459,7 @@
                 if (peek("\"")) {
                     // both the principalClass and principalName
                     // will be replaced later
-                    principalClass = REPLACE_NAME;
+                    principalClass = PrincipalEntry.REPLACE_NAME;
                     principalName = match("principal type");
                 } else {
                     // check for principalClass wildcard
@@ -916,7 +914,7 @@
                     out.print(",\n");
             }
             if (principals != null && principals.size() > 0) {
-                ListIterator<PrincipalEntry> pli = principals.listIterator();
+                Iterator<PrincipalEntry> pli = principals.iterator();
                 while (pli.hasNext()) {
                     out.print("      ");
                     PrincipalEntry pe = pli.next();
@@ -949,23 +947,22 @@
     /**
      * Principal info (class and name) in a grant entry
      */
-    public static class PrincipalEntry {
+    public static class PrincipalEntry implements Principal {
 
         public static final String WILDCARD_CLASS = "WILDCARD_PRINCIPAL_CLASS";
         public static final String WILDCARD_NAME = "WILDCARD_PRINCIPAL_NAME";
+        public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME";
 
         String principalClass;
         String principalName;
 
         /**
-         * A PrincipalEntry consists of the <code>Principal</code>
-         * class and <code>Principal</code> name.
+         * A PrincipalEntry consists of the Principal class and Principal name.
          *
-         * <p>
-         *
-         * @param principalClass the <code>Principal</code> class. <p>
-         *
-         * @param principalName the <code>Principal</code> name. <p>
+         * @param principalClass the Principal class
+         * @param principalName the Principal name
+         * @throws NullPointerException if principalClass or principalName
+         *                              are null
          */
         public PrincipalEntry(String principalClass, String principalName) {
             if (principalClass == null || principalName == null)
@@ -975,6 +972,18 @@
             this.principalName = principalName;
         }
 
+        boolean isWildcardName() {
+            return principalName.equals(WILDCARD_NAME);
+        }
+
+        boolean isWildcardClass() {
+            return principalClass.equals(WILDCARD_CLASS);
+        }
+
+        boolean isReplaceName() {
+            return principalClass.equals(REPLACE_NAME);
+        }
+
         public String getPrincipalClass() {
             return principalClass;
         }
@@ -984,9 +993,9 @@
         }
 
         public String getDisplayClass() {
-            if (principalClass.equals(WILDCARD_CLASS)) {
+            if (isWildcardClass()) {
                 return "*";
-            } else if (principalClass.equals(REPLACE_NAME)) {
+            } else if (isReplaceName()) {
                 return "";
             }
             else return principalClass;
@@ -997,7 +1006,7 @@
         }
 
         public String getDisplayName(boolean addQuote) {
-            if (principalName.equals(WILDCARD_NAME)) {
+            if (isWildcardName()) {
                 return "*";
             }
             else {
@@ -1006,8 +1015,14 @@
             }
         }
 
+        @Override
+        public String getName() {
+            return principalName;
+        }
+
+        @Override
         public String toString() {
-            if (!principalClass.equals(REPLACE_NAME)) {
+            if (!isReplaceName()) {
                 return getDisplayClass() + "/" + getDisplayName();
             } else {
                 return getDisplayName();
@@ -1016,15 +1031,13 @@
 
         /**
          * Test for equality between the specified object and this object.
-         * Two PrincipalEntries are equal if their PrincipalClass and
-         * PrincipalName values are equal.
-         *
-         * <p>
+         * Two PrincipalEntries are equal if their class and name values
+         * are equal.
          *
-         * @param obj the object to test for equality with this object.
-         *
-         * @return true if the objects are equal, false otherwise.
+         * @param obj the object to test for equality with this object
+         * @return true if the objects are equal, false otherwise
          */
+        @Override
         public boolean equals(Object obj) {
             if (this == obj)
                 return true;
@@ -1033,27 +1046,23 @@
                 return false;
 
             PrincipalEntry that = (PrincipalEntry)obj;
-            if (this.principalClass.equals(that.principalClass) &&
-                this.principalName.equals(that.principalName)) {
-                return true;
-            }
-
-            return false;
+            return (principalClass.equals(that.principalClass) &&
+                    principalName.equals(that.principalName));
         }
 
         /**
-         * Return a hashcode for this <code>PrincipalEntry</code>.
+         * Return a hashcode for this PrincipalEntry.
          *
-         * <p>
-         *
-         * @return a hashcode for this <code>PrincipalEntry</code>.
+         * @return a hashcode for this PrincipalEntry
          */
+        @Override
         public int hashCode() {
             return principalClass.hashCode();
         }
+
         public void write(PrintWriter out) {
             out.print("principal " + getDisplayClass() + " " +
-                getDisplayName(true));
+                      getDisplayName(true));
         }
     }
 
@@ -1101,6 +1110,7 @@
          * Calculates a hash code value for the object.  Objects
          * which are equal will also have the same hashcode.
          */
+        @Override
         public int hashCode() {
             int retval = permission.hashCode();
             if (name != null) retval ^= name.hashCode();
@@ -1108,6 +1118,7 @@
             return retval;
         }
 
+        @Override
         public boolean equals(Object obj) {
             if (obj == this)
                 return true;
@@ -1210,28 +1221,18 @@
             i18nMessage = form.format(source);
         }
 
+        @Override
         public String getLocalizedMessage() {
             return i18nMessage;
         }
     }
 
     public static void main(String arg[]) throws Exception {
-        FileReader fr = null;
-        FileWriter fw = null;
-        try {
+        try (FileReader fr = new FileReader(arg[0]);
+             FileWriter fw = new FileWriter(arg[1])) {
             PolicyParser pp = new PolicyParser(true);
-            fr = new FileReader(arg[0]);
             pp.read(fr);
-            fw = new FileWriter(arg[1]);
             pp.write(fw);
-        } finally {
-            if (fr != null) {
-                fr.close();
-            }
-
-            if (fw != null) {
-                fw.close();
-            }
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java	Wed Jul 05 18:35:53 2017 +0200
@@ -36,6 +36,7 @@
 
 import sun.security.jgss.GSSCaller;
 import sun.security.jgss.krb5.Krb5Util;
+import sun.security.jgss.krb5.ServiceCreds;
 import sun.security.krb5.PrincipalName;
 import sun.security.ssl.Krb5Proxy;
 
@@ -62,7 +63,7 @@
     @Override
     public SecretKey[] getServerKeys(AccessControlContext acc)
             throws LoginException {
-        Krb5Util.ServiceCreds serviceCreds =
+        ServiceCreds serviceCreds =
             Krb5Util.getServiceCreds(GSSCaller.CALLER_SSL_SERVER, null, acc);
         return serviceCreds != null ? serviceCreds.getKKeys() :
                                         new KerberosKey[0];
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Wed Jul 05 18:35:53 2017 +0200
@@ -604,7 +604,7 @@
                InstantiationException
     {
         if (type.equals(PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
-            type.equals(PolicyParser.REPLACE_NAME)) {
+            type.equals(PolicyParser.PrincipalEntry.REPLACE_NAME)) {
             return;
         }
         Class<?> PRIN = Class.forName("java.security.Principal");
@@ -2094,7 +2094,7 @@
         } else if (pclass.equals("")) {
             // make this consistent with what PolicyParser does
             // when it sees an empty principal class
-            pclass = PolicyParser.REPLACE_NAME;
+            pclass = PolicyParser.PrincipalEntry.REPLACE_NAME;
             tool.warnings.addElement(
                         "Warning: Principal name '" + pname +
                                 "' specified without a Principal class.\n" +
--- a/jdk/src/share/native/java/lang/System.c	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/share/native/java/lang/System.c	Wed Jul 05 18:35:53 2017 +0200
@@ -389,11 +389,19 @@
         sprops->display_variant, sprops->format_variant, putID, getPropID);
     GETPROP(props, "file.encoding", jVMVal);
     if (jVMVal == NULL) {
+#ifdef MACOSX
+        /*
+         * Since sun_jnu_encoding is now hard-coded to UTF-8 on Mac, we don't
+         * want to use it to overwrite file.encoding
+         */
+        PUTPROP(props, "file.encoding", sprops->encoding);
+#else
         if (fmtdefault) {
             PUTPROP(props, "file.encoding", sprops->encoding);
         } else {
             PUTPROP(props, "file.encoding", sprops->sun_jnu_encoding);
         }
+#endif
     } else {
         (*env)->DeleteLocalRef(env, jVMVal);
     }
--- a/jdk/src/solaris/native/java/lang/java_props_md.c	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/solaris/native/java/lang/java_props_md.c	Wed Jul 05 18:35:53 2017 +0200
@@ -538,7 +538,12 @@
     sprops.display_script = sprops.script;
     sprops.display_country = sprops.country;
     sprops.display_variant = sprops.variant;
+
+#ifdef MACOSX
+    sprops.sun_jnu_encoding = "UTF-8";
+#else
     sprops.sun_jnu_encoding = sprops.encoding;
+#endif
 
 #ifdef _ALLBSD_SOURCE
 #if BYTE_ORDER == _LITTLE_ENDIAN
--- a/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -72,67 +72,97 @@
 
         private final SelectorProvider sp;
 
+        private IOException ioe = null;
+
         private Initializer(SelectorProvider sp) {
             this.sp = sp;
         }
 
+        @Override
         public Void run() throws IOException {
-            ServerSocketChannel ssc = null;
-            SocketChannel sc1 = null;
-            SocketChannel sc2 = null;
-
-            try {
-                // loopback address
-                InetAddress lb = InetAddress.getByName("127.0.0.1");
-                assert(lb.isLoopbackAddress());
-
-                // bind ServerSocketChannel to a port on the loopback address
-                ssc = ServerSocketChannel.open();
-                ssc.socket().bind(new InetSocketAddress(lb, 0));
-
-                // Establish connection (assumes connections are eagerly
-                // accepted)
-                InetSocketAddress sa
-                    = new InetSocketAddress(lb, ssc.socket().getLocalPort());
-                sc1 = SocketChannel.open(sa);
-
-                ByteBuffer bb = ByteBuffer.allocate(8);
-                long secret = rnd.nextLong();
-                bb.putLong(secret).flip();
-                sc1.write(bb);
-
-                // Get a connection and verify it is legitimate
+            LoopbackConnector connector = new LoopbackConnector();
+            connector.run();
+            if (ioe instanceof ClosedByInterruptException) {
+                ioe = null;
+                Thread connThread = new Thread(connector) {
+                    @Override
+                    public void interrupt() {}
+                };
+                connThread.start();
                 for (;;) {
-                    sc2 = ssc.accept();
-                    bb.clear();
-                    sc2.read(bb);
-                    bb.rewind();
-                    if (bb.getLong() == secret)
+                    try {
+                        connThread.join();
                         break;
-                    sc2.close();
+                    } catch (InterruptedException ex) {}
                 }
+                Thread.currentThread().interrupt();
+            }
+
+            if (ioe != null)
+                throw new IOException("Unable to establish loopback connection", ioe);
 
-                // Create source and sink channels
-                source = new SourceChannelImpl(sp, sc1);
-                sink = new SinkChannelImpl(sp, sc2);
-            } catch (IOException e) {
+            return null;
+        }
+
+        private class LoopbackConnector implements Runnable {
+
+            @Override
+            public void run() {
+                ServerSocketChannel ssc = null;
+                SocketChannel sc1 = null;
+                SocketChannel sc2 = null;
+
                 try {
-                    if (sc1 != null)
-                        sc1.close();
-                    if (sc2 != null)
+                    // Loopback address
+                    InetAddress lb = InetAddress.getByName("127.0.0.1");
+                    assert(lb.isLoopbackAddress());
+                    InetSocketAddress sa = null;
+                    for(;;) {
+                        // Bind ServerSocketChannel to a port on the loopback
+                        // address
+                        if (ssc == null || !ssc.isOpen()) {
+                            ssc = ServerSocketChannel.open();
+                            ssc.socket().bind(new InetSocketAddress(lb, 0));
+                            sa = new InetSocketAddress(lb, ssc.socket().getLocalPort());
+                        }
+
+                        // Establish connection (assume connections are eagerly
+                        // accepted)
+                        sc1 = SocketChannel.open(sa);
+                        ByteBuffer bb = ByteBuffer.allocate(8);
+                        long secret = rnd.nextLong();
+                        bb.putLong(secret).flip();
+                        sc1.write(bb);
+
+                        // Get a connection and verify it is legitimate
+                        sc2 = ssc.accept();
+                        bb.clear();
+                        sc2.read(bb);
+                        bb.rewind();
+                        if (bb.getLong() == secret)
+                            break;
                         sc2.close();
-                } catch (IOException e2) { }
-                IOException x = new IOException("Unable to establish"
-                                                + " loopback connection");
-                x.initCause(e);
-                throw x;
-            } finally {
-                try {
-                    if (ssc != null)
-                        ssc.close();
-                } catch (IOException e2) { }
+                        sc1.close();
+                    }
+
+                    // Create source and sink channels
+                    source = new SourceChannelImpl(sp, sc1);
+                    sink = new SinkChannelImpl(sp, sc2);
+                } catch (IOException e) {
+                    try {
+                        if (sc1 != null)
+                            sc1.close();
+                        if (sc2 != null)
+                            sc2.close();
+                    } catch (IOException e2) {}
+                    ioe = e;
+                } finally {
+                    try {
+                        if (ssc != null)
+                            ssc.close();
+                    } catch (IOException e2) {}
+                }
             }
-            return null;
         }
     }
 
@@ -144,7 +174,6 @@
         }
     }
 
-
     public SourceChannel source() {
         return source;
     }
--- a/jdk/test/ProblemList.txt	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 18:35:53 2017 +0200
@@ -1,6 +1,6 @@
 ###########################################################################
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -122,9 +122,6 @@
 
 # jdk_lang
 
-# 7194607
-java/lang/instrument/VerifyLocalVariableTableOnRetransformTest.sh generic-all
-
 # 6944188
 java/lang/management/ThreadMXBean/ThreadStateTest.java          generic-all
 
@@ -148,6 +145,9 @@
 # 6959636
 javax/management/loading/LibraryLoader/LibraryLoaderTest.java	windows-all
 
+# 8005472
+com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh windows-all
+
 ############################################################################
 
 # jdk_math
@@ -238,9 +238,6 @@
 # 7146541
 java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java	linux-all
 
-# 7187882
-java/rmi/activation/checkusage/CheckUsage.java                  generic-all
-
 # 7190106
 java/rmi/reliability/benchmark/runRmiBench.sh                   generic-all
 
@@ -324,6 +321,9 @@
 # 7150569
 tools/launcher/UnicodeTest.java                                 macosx-all
 
+# 8005252
+tools/pack200/AttributeTests.java                               generic-all
+
 ############################################################################
 
 # jdk_jdi
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512524.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512524.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -40,13 +40,13 @@
 public class Test4512524 {
 
     private static final String ALGO = "AES";
-    private static final String MODE = "CBC";
     private static final String PADDING = "NoPadding";
     private static final int KEYSIZE = 16; // in bytes
 
-    public boolean execute() throws Exception {
+    public void execute(String mode) throws Exception {
 
-        Cipher ci = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING, "SunJCE");
+        String transformation = ALGO+"/"+mode+"/"+PADDING;
+        Cipher ci = Cipher.getInstance(transformation, "SunJCE");
 
         // TEST FIX 4512524
         KeyGenerator kg = KeyGenerator.getInstance(ALGO, "SunJCE");
@@ -61,17 +61,14 @@
         }
 
         // passed all tests...hooray!
-        return true;
+        System.out.println(transformation + ": Passed");
     }
 
     public static void main (String[] args) throws Exception {
         Security.addProvider(new com.sun.crypto.provider.SunJCE());
 
         Test4512524 test = new Test4512524();
-        String testName = test.getClass().getName() + "[" + ALGO +
-            "/" + MODE + "/" + PADDING + "]";
-        if (test.execute()) {
-            System.out.println(testName + ": Passed!");
-        }
+        test.execute("CBC");
+        test.execute("GCM");
     }
 }
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512704.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512704.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -39,14 +39,14 @@
 
 public class Test4512704 {
     private static final String ALGO = "AES";
-    private static final String MODE = "CBC";
-    private static final String PADDING = "PKCS5Padding";
+    private static final String PADDING = "NoPadding";
     private static final int KEYSIZE = 16; // in bytes
 
-    public boolean execute() throws Exception {
+    public void execute(String mode) throws Exception {
+
         AlgorithmParameterSpec aps = null;
-
-        Cipher ci = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING, "SunJCE");
+        String transformation = ALGO + "/" + mode + "/"+PADDING;
+        Cipher ci = Cipher.getInstance(transformation, "SunJCE");
 
         KeyGenerator kg = KeyGenerator.getInstance(ALGO, "SunJCE");
         kg.init(KEYSIZE*8);
@@ -57,19 +57,14 @@
         } catch(InvalidAlgorithmParameterException ex) {
             throw new Exception("parameter should be generated when null is specified!");
         }
-
-        // passed all tests...hooray!
-        return true;
+        System.out.println(transformation + ": Passed");
     }
 
     public static void main (String[] args) throws Exception {
         Security.addProvider(new com.sun.crypto.provider.SunJCE());
 
         Test4512704 test = new Test4512704();
-        String testName = test.getClass().getName() + "[" + ALGO +
-            "/" + MODE + "/" + PADDING + "]";
-        if (test.execute()) {
-            System.out.println(testName + ": Passed!");
-        }
+        test.execute("CBC");
+        test.execute("GCM");
     }
 }
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4517355.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4517355.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -41,16 +41,14 @@
 public class Test4517355 {
 
     private static final String ALGO = "AES";
-    private static final String MODE = "CBC";
-    private static final String PADDING = "PKCS5Padding";
     private static final int KEYSIZE = 16; // in bytes
 
-    public boolean execute() throws Exception {
-        Random rdm = new Random();
-        byte[] plainText=new byte[125];
-        rdm.nextBytes(plainText);
+    private static byte[] plainText = new byte[125];
 
-        Cipher ci = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING, "SunJCE");
+    public void execute(String mode, String padding) throws Exception {
+        String transformation = ALGO + "/" + mode + "/" + padding;
+
+        Cipher ci = Cipher.getInstance(transformation, "SunJCE");
         KeyGenerator kg = KeyGenerator.getInstance(ALGO, "SunJCE");
         kg.init(KEYSIZE*8);
         SecretKey key = kg.generateKey();
@@ -59,9 +57,14 @@
         ci.init(Cipher.ENCRYPT_MODE, key);
         byte[] cipherText = ci.doFinal(plainText);
 
-        byte[] iv = ci.getIV();
-        AlgorithmParameterSpec aps = new IvParameterSpec(iv);
-        ci.init(Cipher.DECRYPT_MODE, key, aps);
+        if (mode.equalsIgnoreCase("GCM")) {
+            AlgorithmParameters params = ci.getParameters();
+            ci.init(Cipher.DECRYPT_MODE, key, params);
+        } else {
+            byte[] iv = ci.getIV();
+            AlgorithmParameterSpec aps = new IvParameterSpec(iv);
+            ci.init(Cipher.DECRYPT_MODE, key, aps);
+        }
         byte[] recoveredText = new byte[plainText.length];
         try {
             int len = ci.doFinal(cipherText, 0, cipherText.length,
@@ -80,21 +83,22 @@
             throw new Exception("encryption does not work!");
         }
         // 3. make sure padding is working
-        if ((cipherText.length/16)*16 != cipherText.length) {
-            throw new Exception("padding does not work!");
+        if (padding.equalsIgnoreCase("PKCS5Padding")) {
+            if ((cipherText.length/16)*16 != cipherText.length) {
+                throw new Exception("padding does not work!");
+            }
         }
-        // passed all tests...hooray!
-        return true;
+        System.out.println(transformation + ": Passed");
     }
 
     public static void main (String[] args) throws Exception {
         Security.addProvider(new com.sun.crypto.provider.SunJCE());
 
         Test4517355 test = new Test4517355();
-        String testName = test.getClass().getName() + "[" + ALGO +
-            "/" + MODE + "/" + PADDING + "]";
-        if (test.execute()) {
-            System.out.println(testName + ": Passed!");
-        }
+        Random rdm = new Random();
+        rdm.nextBytes(test.plainText);
+
+        test.execute("CBC", "PKCS5Padding");
+        test.execute("GCM", "NoPadding");
     }
 }
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4626070.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4626070.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -34,13 +34,11 @@
 
 public class Test4626070 {
     private static final String ALGO = "AES";
-    private static final String MODE = "CBC";
-    private static final String PADDING = "PKCS5Padding";
     private static final int KEYSIZE = 16; // in bytes
 
-    public boolean execute() throws Exception {
-
-        Cipher ci = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING, "SunJCE");
+    public void execute(String mode, String padding) throws Exception {
+        String transformation = ALGO + "/" + mode + "/" + padding;
+        Cipher ci = Cipher.getInstance(transformation, "SunJCE");
         KeyGenerator kg = KeyGenerator.getInstance(ALGO, "SunJCE");
         kg.init(KEYSIZE*8);
         SecretKey key = kg.generateKey();
@@ -58,18 +56,14 @@
             throw new Exception(
                 "key after wrap/unwrap is different from the original!");
         }
-        // passed all tests...hooray!
-        return true;
+        System.out.println(transformation + ": Passed");
     }
 
     public static void main (String[] args) throws Exception {
         Security.addProvider(new com.sun.crypto.provider.SunJCE());
 
         Test4626070 test = new Test4626070();
-        String testName = test.getClass().getName() + "[" + ALGO +
-            "/" + MODE + "/" + PADDING + "]";
-        if (test.execute()) {
-            System.out.println(testName + ": Passed!");
-        }
+        test.execute("CBC", "PKCS5Padding");
+        test.execute("GCM", "NoPadding");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6996769
+ * @library ../UTIL
+ * @build TestUtil
+ * @run main TestGCMKeyAndIvCheck
+ * @summary Ensure that same key+iv can't be repeated used for encryption.
+ * @author Valerie Peng
+ */
+
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+import com.sun.crypto.provider.*;
+
+import java.util.*;
+
+public class TestGCMKeyAndIvCheck {
+
+    private static final byte[] AAD = new byte[5];
+    private static final byte[] PT = new byte[18];
+
+    private static void checkISE(Cipher c) throws Exception {
+        // Subsequent encryptions should fail
+        try {
+            c.updateAAD(AAD);
+            throw new Exception("Should throw ISE for updateAAD()");
+        } catch (IllegalStateException ise) {
+            // expected
+        }
+
+        try {
+            c.update(PT);
+            throw new Exception("Should throw ISE for update()");
+        } catch (IllegalStateException ise) {
+            // expected
+        }
+        try {
+            c.doFinal(PT);
+            throw new Exception("Should throw ISE for doFinal()");
+        } catch (IllegalStateException ise) {
+            // expected
+        }
+    }
+
+    public void test() throws Exception {
+        Cipher c = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
+
+        SecretKey key = new SecretKeySpec(new byte[16], "AES");
+        // First try parameter-less init.
+        c.init(Cipher.ENCRYPT_MODE, key);
+        c.updateAAD(AAD);
+        byte[] ctPlusTag = c.doFinal(PT);
+
+        // subsequent encryption should fail unless re-init w/ different key+iv
+        checkISE(c);
+
+        // Validate the retrieved parameters against the IV and tag length.
+        AlgorithmParameters params = c.getParameters();
+        if (params == null) {
+            throw new Exception("getParameters() should not return null");
+        }
+        GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
+        if (spec.getTLen() != (ctPlusTag.length - PT.length)*8) {
+            throw new Exception("Parameters contains incorrect TLen value");
+        }
+        if (!Arrays.equals(spec.getIV(), c.getIV())) {
+            throw new Exception("Parameters contains incorrect IV value");
+        }
+
+        // Should be ok to use the same key+iv for decryption
+        c.init(Cipher.DECRYPT_MODE, key, params);
+        c.updateAAD(AAD);
+        byte[] recovered = c.doFinal(ctPlusTag);
+        if (!Arrays.equals(recovered, PT)) {
+            throw new Exception("decryption result mismatch");
+        }
+
+        // Now try to encrypt again using the same key+iv; should fail also
+        try {
+            c.init(Cipher.ENCRYPT_MODE, key, params);
+            throw new Exception("Should throw exception when same key+iv is used");
+        } catch (InvalidAlgorithmParameterException iape) {
+            // expected
+        }
+
+        // Now try to encrypt again using parameter-less init; should work
+        c.init(Cipher.ENCRYPT_MODE, key);
+        c.doFinal(PT);
+
+        // make sure a different iv is used
+        byte[] iv = c.getIV();
+        if (Arrays.equals(spec.getIV(), iv)) {
+            throw new Exception("IV should be different now");
+        }
+
+        // Now try to encrypt again using a different parameter; should work
+        c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, new byte[30]));
+        c.updateAAD(AAD);
+        c.doFinal(PT);
+        // subsequent encryption should fail unless re-init w/ different key+iv
+        checkISE(c);
+
+        // Now try decryption twice in a row; no re-init required and
+        // same parameters is used.
+        c.init(Cipher.DECRYPT_MODE, key, params);
+        c.updateAAD(AAD);
+        recovered = c.doFinal(ctPlusTag);
+
+        c.updateAAD(AAD);
+        recovered = c.doFinal(ctPlusTag);
+        if (!Arrays.equals(recovered, PT)) {
+            throw new Exception("decryption result mismatch");
+        }
+
+        // Now try decryption again and re-init using the same parameters
+        c.init(Cipher.DECRYPT_MODE, key, params);
+        c.updateAAD(AAD);
+        recovered = c.doFinal(ctPlusTag);
+
+        // init to decrypt w/o parameters; should fail with IKE as
+        // javadoc specified
+        try {
+            c.init(Cipher.DECRYPT_MODE, key);
+            throw new Exception("Should throw IKE for dec w/o params");
+        } catch (InvalidKeyException ike) {
+            // expected
+        }
+
+        // Lastly, try encryption AND decryption w/ wrong type of parameters,
+        // e.g. IvParameterSpec
+        try {
+            c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
+            throw new Exception("Should throw IAPE");
+        } catch (InvalidAlgorithmParameterException iape) {
+            // expected
+        }
+        try {
+            c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+            throw new Exception("Should throw IAPE");
+        } catch (InvalidAlgorithmParameterException iape) {
+            // expected
+        }
+
+        System.out.println("Test Passed!");
+    }
+
+    public static void main (String[] args) throws Exception {
+        TestGCMKeyAndIvCheck t = new TestGCMKeyAndIvCheck();
+        t.test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestKATForGCM.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6996769
+ * @library ../UTIL
+ * @build TestUtil
+ * @run main TestKATForGCM
+ * @summary Known Answer Test for AES cipher with GCM mode support in
+ * SunJCE provider.
+ * @author Valerie Peng
+ */
+
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+import com.sun.crypto.provider.*;
+
+import java.util.*;
+
+public class TestKATForGCM {
+
+    // Utility methods
+    private static byte[] HexToBytes(String hexVal) {
+        if (hexVal == null) return new byte[0];
+        byte[] result = new byte[hexVal.length()/2];
+        for (int i = 0; i < result.length; i++) {
+            // 2 characters at a time
+            String byteVal = hexVal.substring(2*i, 2*i +2);
+            result[i] = Integer.valueOf(byteVal, 16).byteValue();
+        }
+        return result;
+    }
+
+    private static class TestVector {
+        SecretKey key;
+        byte[] plainText;
+        byte[] aad;
+        byte[] cipherText;
+        byte[] tag;
+        GCMParameterSpec spec;
+        String info;
+
+        TestVector(String key, String iv, String pt, String aad,
+                   String ct, String tag) {
+            this.key = new SecretKeySpec(HexToBytes(key), "AES");
+            this.plainText = HexToBytes(pt);
+            this.aad = HexToBytes(aad);
+            this.cipherText = HexToBytes(ct);
+            this.tag = HexToBytes(tag);
+            this.spec = new GCMParameterSpec(this.tag.length * 8, HexToBytes(iv));
+            this.info = "key=" + key + ", iv=" + iv + ", pt=" + pt +
+                ",aad=" + aad + ", ct=" + ct + ", tag=" + tag;
+        }
+
+        public String toString() {
+            return info;
+        }
+    }
+
+    // These test vectors are found off NIST's CAVP page
+    // http://csrc.nist.gov/groups/STM/cavp/index.html
+    // inside the link named "GCM Test Vectors", i.e.
+    // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+    // CAVS 14.0, set of test vectors w/ count = 0, keysize = 128
+    private static TestVector[] testValues = {
+        // 96-bit iv w/ 128/120/112/104/96-bit tags
+        // no plain text, no aad
+        new TestVector("11754cd72aec309bf52f7687212e8957",
+                       "3c819d9a9bed087615030b65",
+                       null, null, null,
+                       "250327c674aaf477aef2675748cf6971"),
+        new TestVector("272f16edb81a7abbea887357a58c1917",
+                       "794ec588176c703d3d2a7a07",
+                       null, null, null,
+                       "b6e6f197168f5049aeda32dafbdaeb"),
+        new TestVector("81b6844aab6a568c4556a2eb7eae752f",
+                       "ce600f59618315a6829bef4d",
+                       null, null, null,
+                       "89b43e9dbc1b4f597dbbc7655bb5"),
+        new TestVector("cde2f9a9b1a004165ef9dc981f18651b",
+                       "29512c29566c7322e1e33e8e",
+                       null, null, null,
+                       "2e58ce7dabd107c82759c66a75"),
+        new TestVector("b01e45cc3088aaba9fa43d81d481823f",
+                       "5a2c4a66468713456a4bd5e1",
+                       null, null, null,
+                       "014280f944f53c681164b2ff"),
+        // 96-bit iv w/ 128/120/112/104/96-bit tags
+        // no plain text, 16-byte aad
+        new TestVector("77be63708971c4e240d1cb79e8d77feb",
+                       "e0e00f19fed7ba0136a797f3",
+                       null,
+                       "7a43ec1d9c0a5a78a0b16533a6213cab",
+                       null,
+                       "209fcc8d3675ed938e9c7166709dd946"),
+        new TestVector("da0b615656135194ba6d3c851099bc48",
+                       "d39d4b4d3cc927885090e6c3",
+                       null,
+                       "e7e5e6f8dac913036cb2ff29e8625e0e",
+                       null,
+                       "ab967711a5770461724460b07237e2"),
+        new TestVector("7e0986937a88eef894235aba4a2f43b2",
+                       "92c4a631695907166b422d60",
+                       null,
+                       "85c185f8518f9f2cd597a8f9208fc76b",
+                       null,
+                       "3bb916b728df94fe9d1916736be1"),
+        new TestVector("c3db570d7f0c21e86b028f11465d1dc9",
+                       "f86970f58ceef89fc7cb679e",
+                       null,
+                       "c095240708c0f57c288d86090ae34ee1",
+                       null,
+                       "e043c52160d652e82c7262fcf4"),
+        new TestVector("bea48ae4980d27f357611014d4486625",
+                       "32bddb5c3aa998a08556454c",
+                       null,
+                       "8a50b0b8c7654bced884f7f3afda2ead",
+                       null,
+                       "8e0f6d8bf05ffebe6f500eb1"),
+        // 96-bit iv w/ 128/120/112/104/96-bit tags
+        // no plain text, 20-byte aad
+        new TestVector("2fb45e5b8f993a2bfebc4b15b533e0b4",
+                       "5b05755f984d2b90f94b8027",
+                       null,
+                       "e85491b2202caf1d7dce03b97e09331c32473941",
+                       null,
+                       "c75b7832b2a2d9bd827412b6ef5769db"),
+        new TestVector("9bf406339fcef9675bbcf156aa1a0661",
+                       "8be4a9543d40f542abacac95",
+                       null,
+                       "7167cbf56971793186333a6685bbd58d47d379b3",
+                       null,
+                       "5e7968d7bbd5ba58cfcc750e2ef8f1"),
+        new TestVector("a2e962fff70fd0f4d63be728b80556fc",
+                       "1fa7103483de43d09bc23db4",
+                       null,
+                       "2a58edf1d53f46e4e7ee5e77ee7aeb60fc360658",
+                       null,
+                       "fa37f2dbbefab1451eae1d0d74ca"),
+        new TestVector("6bf4fdce82926dcdfc52616ed5f23695",
+                       "cc0f5899a10615567e1193ed",
+                       null,
+                       "3340655592374c1da2f05aac3ee111014986107f",
+                       null,
+                       "8ad3385cce3b5e7c985908192c"),
+        new TestVector("4df7a13e43c3d7b66b1a72fac5ba398e",
+                       "97179a3a2d417908dcf0fb28",
+                       null,
+                       "cbb7fc0010c255661e23b07dbd804b1e06ae70ac",
+                       null,
+                       "37791edae6c137ea946cfb40"),
+        // 96-bit iv w/ 128-bit tags, 13/16/32/51-byte plain text, no aad
+        new TestVector("fe9bb47deb3a61e423c2231841cfd1fb",
+                       "4d328eb776f500a2f7fb47aa",
+                       "f1cc3818e421876bb6b8bbd6c9",
+                       null,
+                       "b88c5c1977b35b517b0aeae967",
+                       "43fd4727fe5cdb4b5b42818dea7ef8c9"),
+        new TestVector("7fddb57453c241d03efbed3ac44e371c",
+                       "ee283a3fc75575e33efd4887",
+                       "d5de42b461646c255c87bd2962d3b9a2",
+                       null,
+                       "2ccda4a5415cb91e135c2a0f78c9b2fd",
+                       "b36d1df9b9d5e596f83e8b7f52971cb3"),
+        new TestVector("9971071059abc009e4f2bd69869db338",
+                       "07a9a95ea3821e9c13c63251",
+                       "f54bc3501fed4f6f6dfb5ea80106df0bd836e6826225b75c0222f6e859b35983",
+                       null,
+                       "0556c159f84ef36cb1602b4526b12009c775611bffb64dc0d9ca9297cd2c6a01",
+                       "7870d9117f54811a346970f1de090c41"),
+        new TestVector("594157ec4693202b030f33798b07176d",
+                       "49b12054082660803a1df3df",
+
+"3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c",
+                      null,
+
+"c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69",
+                      "ba92d3661ce8b04687e8788d55417dc2"),
+        // 96-bit iv w/ 128-bit tags, 16-byte plain text, 16/20/48/90-byte aad
+        new TestVector("c939cc13397c1d37de6ae0e1cb7c423c",
+                       "b3d8cc017cbb89b39e0f67e2",
+                       "c3b3c41f113a31b73d9a5cd432103069",
+                       "24825602bd12a984e0092d3e448eda5f",
+                       "93fe7d9e9bfd10348a5606e5cafa7354",
+                       "0032a1dc85f1c9786925a2e71d8272dd"),
+        new TestVector("d4a22488f8dd1d5c6c19a7d6ca17964c",
+                       "f3d5837f22ac1a0425e0d1d5",
+                       "7b43016a16896497fb457be6d2a54122",
+                       "f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a",
+                       "c2bd67eef5e95cac27e3b06e3031d0a8",
+                       "f23eacf9d1cdf8737726c58648826e9c"),
+        new TestVector("89850dd398e1f1e28443a33d40162664",
+                       "e462c58482fe8264aeeb7231",
+                       "2805cdefb3ef6cc35cd1f169f98da81a",
+
+"d74e99d1bdaa712864eec422ac507bddbe2b0d4633cd3dff29ce5059b49fe868526c59a2a3a604457bc2afea866e7606",
+                       "ba80e244b7fc9025cd031d0f63677e06",
+                       "d84a8c3eac57d1bb0e890a8f461d1065"),
+        new TestVector("bd7c5c63b7542b56a00ebe71336a1588",
+                       "87721f23ba9c3c8ea5571abc",
+                       "de15ddbb1e202161e8a79af6a55ac6f3",
+
+"a6ec8075a0d3370eb7598918f3b93e48444751624997b899a87fa6a9939f844e008aa8b70e9f4c3b1a19d3286bf543e7127bfecba1ad17a5ec53fccc26faecacc4c75369498eaa7d706aef634d0009279b11e4ba6c993e5e9ed9",
+                       "41eb28c0fee4d762de972361c863bc80",
+                       "9cb567220d0b252eb97bff46e4b00ff8"),
+        // 8/1024-bit iv w/ 128-bit tag, no plain text, no aad
+        new TestVector("1672c3537afa82004c6b8a46f6f0d026",
+                       "05",
+                       null, null, null,
+                       "8e2ad721f9455f74d8b53d3141f27e8e"),
+        new TestVector("d0f1f4defa1e8c08b4b26d576392027c",
+
+"42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
+                       null, null, null,
+                       "7ab49b57ddf5f62c427950111c5c4f0d"),
+        // 8-bit iv w/ 128-bit tag, 13-byte plain text, 90-byte aad
+        new TestVector("9f79239f0904eace50784b863e723f6b",
+                       "d9",
+                       "bdb0bb10c87965acd34d146171",
+
+"44db436089327726c5f01139e1f339735c9e85514ccc2f167bad728010fb34a9072a9794c8a5e7361b1d0dbcdc9ac4091e354bb2896561f0486645252e9c78c86beece91bfa4f7cc4a8794ce1f305b1b735efdbf1ed1563c0be0",
+                       "7e5a7c8dadb3f0c7335b4d9d8d",
+                       "6b6ef1f53723a89f3bb7c6d043840717"),
+        // 1024-bit iv w/ 128-bit tag, 51-byte plain text, 48-byte aad
+        new TestVector("141f1ce91989b07e7eb6ae1dbd81ea5e",
+
+"49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e194aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e57df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470dee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea2e8f05dd3a1396f",
+
+"d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec2fe87719dadf1eb0aef212b51e74c9c5b934104a43",
+
+"630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba323951727666c947a21894a079ef061ee159c05beeb4",
+
+"f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83240446b28dc088abd42b0fc687f208190ff24c0548",
+                      "dbb93bbb56d0439cd09f620a57687f5d"),
+    };
+
+    public boolean execute(TestVector[] testValues) throws Exception {
+        boolean testFailed = false;
+        Cipher c = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
+        for (int i = 0; i < testValues.length; i++) {
+            try {
+                c.init(Cipher.ENCRYPT_MODE, testValues[i].key, testValues[i].spec);
+                c.updateAAD(testValues[i].aad);
+                byte[] ctPlusTag = c.doFinal(testValues[i].plainText);
+
+                c.init(Cipher.DECRYPT_MODE, testValues[i].key, testValues[i].spec);
+                c.updateAAD(testValues[i].aad);
+                byte[] pt = c.doFinal(ctPlusTag); // should fail if tag mismatched
+
+                // check encryption/decryption results just to be sure
+                if (!Arrays.equals(testValues[i].plainText, pt)) {
+                    System.out.println("PlainText diff failed for test# " + i);
+                    testFailed = true;
+                }
+                int ctLen = testValues[i].cipherText.length;
+                if (!Arrays.equals(testValues[i].cipherText,
+                                   Arrays.copyOf(ctPlusTag, ctLen))) {
+                    System.out.println("CipherText diff failed for test# " + i);
+                    testFailed = true;
+                }
+                int tagLen = testValues[i].tag.length;
+                if (!Arrays.equals
+                    (testValues[i].tag,
+                     Arrays.copyOfRange(ctPlusTag, ctLen, ctLen+tagLen))) {
+                    System.out.println("Tag diff failed for test# " + i);
+                    testFailed = true;
+                }
+            } catch (Exception ex) {
+                // continue testing other test vectors
+                System.out.println("Failed Test Vector: " + testValues[i]);
+                ex.printStackTrace();
+                testFailed = true;
+                continue;
+            }
+        }
+        if (testFailed) {
+            throw new Exception("Test Failed");
+        }
+        // passed all tests...hooray!
+        return true;
+    }
+
+    public static void main (String[] args) throws Exception {
+        TestKATForGCM test = new TestKATForGCM();
+        if (test.execute(testValues)) {
+            System.out.println("Test Passed!");
+        }
+    }
+}
+
--- a/jdk/test/java/lang/Runtime/exec/WinCommand.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/lang/Runtime/exec/WinCommand.java	Wed Jul 05 18:35:53 2017 +0200
@@ -135,24 +135,19 @@
 
         // Win9x systems don't have a cmd.exe
         if (new File(systemDirW, "cmd.exe").exists()) {
-            try {
-                out.println("Running cmd.exe tests...");
-                writeFile("cdcmd.cmd", "@echo off\r\nCD\r\n");
-                writeFile("cdbat.bat", "@echo off\r\nCD\r\n");
-                checkCD("cmd",
-                        "cmd.exe",
-                        systemDirW + "\\cmd.exe",
-                        // Only the ".exe" extension can be omitted
-                        systemDirW + "\\cmd",
-                        systemDirM + "/cmd.exe",
-                        systemDirM + "/cmd",
-                        "/" + systemDirM + "/cmd",
-                        "cdcmd.cmd", "./cdcmd.cmd", ".\\cdcmd.cmd",
-                        "cdbat.bat", "./cdbat.bat", ".\\cdbat.bat");
-            } finally {
-                new File("cdcmd.cmd").delete();
-                new File("cdbat.bat").delete();
-            }
+            out.println("Running cmd.exe tests...");
+            writeFile("cdcmd.cmd", "@echo off\r\nCD\r\n");
+            writeFile("cdbat.bat", "@echo off\r\nCD\r\n");
+            checkCD("cmd",
+                    "cmd.exe",
+                    systemDirW + "\\cmd.exe",
+                    // Only the ".exe" extension can be omitted
+                    systemDirW + "\\cmd",
+                    systemDirM + "/cmd.exe",
+                    systemDirM + "/cmd",
+                    "/" + systemDirM + "/cmd",
+                    "cdcmd.cmd", "./cdcmd.cmd", ".\\cdcmd.cmd",
+                    "cdbat.bat", "./cdbat.bat", ".\\cdbat.bat");
         }
 
         // 16-bit apps like command.com must have a console;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/MacJNUEncoding/ExpectedEncoding.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/**
+ * Check that the value of file.encoding and sun.jnu.encoding match the expected
+ * values passed in on the command-line.
+ */
+public class ExpectedEncoding {
+    public static void main(String[] args) {
+        boolean failed = false;
+        if (args.length != 2) {
+            System.out.println("Usage:");
+            System.out.println("$ java ExpectedEncoding <expected file.encoding> <expected sun.jnu.encoding>");
+            System.exit(1);
+        }
+        String expectFileEnc = args[0];
+        String expectSunJnuEnc = args[1];
+
+        String fileEnc = System.getProperty("file.encoding");
+        String jnuEnc = System.getProperty("sun.jnu.encoding");
+
+        if (fileEnc == null || !fileEnc.equals(expectFileEnc)) {
+            System.err.println("Expected file.encoding: " + expectFileEnc);
+            System.err.println("Actual file.encoding: " + fileEnc);
+            failed = true;
+        }
+        if (jnuEnc == null || !jnuEnc.equals(expectSunJnuEnc)) {
+            System.err.println("Expected sun.jnu.encoding: " + expectSunJnuEnc);
+            System.err.println("Actual sun.jnu.encoding: " + jnuEnc);
+            failed = true;
+        }
+        if (failed) {
+            throw new RuntimeException("Test Failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/MacJNUEncoding/MacJNUEncoding.sh	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2012 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.
+#
+# 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.
+
+# @test
+# @bug 8003228
+# @summary Test the value of sun.jnu.encoding on Mac
+# @author Brent Christian
+#
+# @run shell MacJNUEncoding.sh
+
+# Only run test on Mac
+OS=`uname -s`
+case "$OS" in
+  Darwin )  ;;
+  * )
+    exit 0
+    ;;
+esac
+
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+  echo "TESTSRC not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+JAVAC="${TESTJAVA}"/bin/javac
+JAVA="${TESTJAVA}"/bin/java
+
+echo "Building test classes..."
+"$JAVAC" -d "${TESTCLASSES}" "${TESTSRC}"/ExpectedEncoding.java 
+
+echo ""
+echo "Running test for C locale"
+export LANG=C
+export LC_ALL=C
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" ExpectedEncoding US-ASCII UTF-8
+result1=$?
+
+echo ""
+echo "Running test for en_US.UTF-8 locale"
+export LANG=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" ExpectedEncoding UTF-8 UTF-8
+result2=$?
+
+echo ""
+echo "Cleanup"
+rm ${TESTCLASSES}/ExpectedEncoding.class
+
+if [ ${result1} -ne 0 ] ; then
+    echo "Test failed for C locale"
+    echo "  LANG=\"${LANG}\""
+    echo "  LC_ALL=\"${LC_ALL}\""
+    exit ${result1}
+fi
+if [ ${result2} -ne 0 ] ; then
+    echo "Test failed for en_US.UTF-8 locale"
+    echo "  LANG=\"${LANG}\""
+    echo "  LC_ALL=\"${LC_ALL}\""
+    exit ${result2}
+fi
+exit 0
+
--- a/jdk/test/java/net/Socks/SocksV4Test.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/net/Socks/SocksV4Test.java	Wed Jul 05 18:35:53 2017 +0200
@@ -26,6 +26,7 @@
  * @bug 4727547
  * @summary SocksSocketImpl throws NullPointerException
  * @build SocksServer
+ * @run main SocksV4Test
  */
 
 import java.net.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/Pipe/PipeInterrupt.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 8002306
+ * @summary Ensure that a Pipe can open even if its thread has already
+ *          been interrupted.
+ * @author Dan Xu
+ */
+
+import java.io.IOException;
+import java.nio.channels.Pipe;
+
+
+public class PipeInterrupt {
+
+    private Exception exc = null;
+
+    public static void main(String[] args) throws Exception {
+        PipeInterrupt instance = new PipeInterrupt();
+        instance.test();
+    }
+
+    public void test() throws Exception {
+
+        Thread tester = new Thread("PipeTester") {
+            private Pipe testPipe = null;
+
+            @Override
+            public void run() {
+                for (;;) {
+                    boolean interrupted = this.isInterrupted();
+                    try {
+                        testPipe = Pipe.open();
+                        close();
+                        if (interrupted) {
+                            if (!this.isInterrupted())
+                               exc = new RuntimeException("interrupt status reset");
+                            break;
+                        }
+                    } catch (IOException ioe) {
+                        exc = ioe;
+                    }
+                }
+            }
+
+            private void close() throws IOException {
+                if (testPipe != null) {
+                    testPipe.sink().close();
+                    testPipe.source().close();
+                }
+            }
+        };
+
+        tester.start();
+        Thread.sleep(200);
+        tester.interrupt();
+        tester.join();
+
+        if (exc != null)
+            throw exc;
+    }
+}
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -168,7 +168,7 @@
             registering = null;
 
             // Need to make sure that rmid goes away by itself
-            Process rmidProcess = rmid.getVM();
+            JavaVM rmidProcess = rmid;
             if (rmidProcess != null) {
                 try {
                     Runnable waitThread =
@@ -205,9 +205,9 @@
      * class that waits for rmid to exit
      */
     private static class ShutdownDetectThread implements Runnable {
-        private Process rmidProcess = null;
+        private JavaVM rmidProcess = null;
 
-        ShutdownDetectThread(Process rmidProcess) {
+        ShutdownDetectThread(JavaVM rmidProcess) {
             this.rmidProcess = rmidProcess;
         }
         public void run() {
--- a/jdk/test/java/rmi/activation/checkusage/CheckUsage.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/activation/checkusage/CheckUsage.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -23,6 +23,7 @@
 
 /* @test
  * @bug 4259564
+ * @summary RMID's usage message is incomplete and inconsistent with other tools
  *
  * @library ../../testlibrary
  * @build TestLibrary JavaVM
@@ -37,23 +38,16 @@
  */
 public class CheckUsage {
     public static void main(String[] args) {
-
-        System.err.println("\nregression test for 4259564\n");
-
-        JavaVM rmidVM = null;
-
         try {
-            // make sure the registry exits with a proper usage statement
             ByteArrayOutputStream berr = new ByteArrayOutputStream();
 
-            // run a VM to start the registry
-            rmidVM = new JavaVM("sun.rmi.server.Activation", "", "foo",
-                                    System.out, berr);
+            // create rmid with incorrect command line args
+            JavaVM rmidVM = new JavaVM("sun.rmi.server.Activation", "", "foo",
+                                       System.out, berr);
             System.err.println("starting rmid");
-            rmidVM.start();
 
-            // wait for registry exit
-            int rmidVMExitStatus = rmidVM.getVM().waitFor();
+            // run the subprocess and wait for it to exit
+            int rmidVMExitStatus = rmidVM.execute();
             System.err.println("rmid exited with status: " +
                                rmidVMExitStatus);
 
@@ -66,12 +60,8 @@
             } else {
                 System.err.println("test passed");
             }
-
         } catch (Exception e) {
             TestLibrary.bomb(e);
-        } finally {
-            rmidVM.destroy();
-            rmidVM = null;
         }
     }
 }
--- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -76,8 +76,7 @@
             }
 
             System.err.println("starting " + utilityToStart);
-            vm.start();
-            vm.getVM().waitFor();
+            vm.execute();
 
         } catch (Exception e) {
             TestLibrary.bomb(e);
--- a/jdk/test/java/rmi/registry/checkusage/CheckUsage.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/registry/checkusage/CheckUsage.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -35,34 +35,21 @@
 
 /**
  * Make sure that the rmiregistry prints out a correct usage statement
- * when run with an incorrect command line; test written to conform to
- * new tighter bug fix/regression test guidelines.
+ * when run with an incorrect command line.
  */
 public class CheckUsage {
     public static void main(String[] args) {
 
-        System.err.println("\nregression test for 4151966\n");
-
-        JavaVM registryVM = null;
-
         try {
-            // make sure the registry exits with a proper usage statement
             ByteArrayOutputStream berr = new ByteArrayOutputStream();
 
             // run a VM to start the registry
-            registryVM = new JavaVM("sun.rmi.registry.RegistryImpl",
-                                    "", "foo",
-                                    System.out, berr);
+            JavaVM registryVM = new JavaVM("sun.rmi.registry.RegistryImpl",
+                                           "", "foo",
+                                           System.out, berr);
             System.err.println("starting registry");
-            registryVM.start();
-
-            // wait for registry exit
             System.err.println(" registry exited with status: " +
-                               registryVM.getVM().waitFor());
-            try {
-                Thread.sleep(7000);
-            } catch (InterruptedException ie) {
-            }
+                               registryVM.execute());
 
             String usage = new String(berr.toByteArray());
 
@@ -75,9 +62,6 @@
             }
         } catch (Exception e) {
             TestLibrary.bomb(e);
-        } finally {
-            registryVM.destroy();
-            registryVM = null;
         }
     }
 }
--- a/jdk/test/java/rmi/registry/reexport/Reexport.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/registry/reexport/Reexport.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -122,8 +122,7 @@
         try {
             JavaVM jvm = new JavaVM("RegistryRunner", "", Integer.toString(p));
             jvm.start();
-            Reexport.subreg = jvm.getVM();
-
+            Reexport.subreg = jvm;
         } catch (IOException e) {
             // one of these is summarily dropped, can't remember which one
             System.out.println ("Test setup failed - cannot run rmiregistry");
@@ -135,7 +134,8 @@
         } catch (Exception whatever) {
         }
     }
-    private static Process subreg = null;
+
+    private static JavaVM subreg = null;
 
     public static void killRegistry(int port) {
         if (Reexport.subreg != null) {
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -41,6 +41,8 @@
     private OutputStream outputStream = System.out;
     private OutputStream errorStream = System.err;
     private String policyFileName = null;
+    private StreamPipe outPipe;
+    private StreamPipe errPipe;
 
     private static void mesg(Object mesg) {
         System.err.println("JAVAVM: " + mesg.toString());
@@ -145,13 +147,12 @@
         }
 
         mesg("command = " + Arrays.asList(javaCommand).toString());
-        System.err.println("");
 
         vm = Runtime.getRuntime().exec(javaCommand);
 
         /* output from the execed process may optionally be captured. */
-        StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
-        StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
+        outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
+        errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
     }
 
     public void destroy() {
@@ -161,7 +162,25 @@
         vm = null;
     }
 
-    protected Process getVM() {
-        return vm;
+    /**
+     * Waits for the subprocess to exit, joins the pipe threads to ensure that
+     * all output is collected, and returns its exit status.
+     */
+    public int waitFor() throws InterruptedException {
+        if (vm == null)
+            throw new IllegalStateException("can't wait for JavaVM that hasn't started");
+
+        int status = vm.waitFor();
+        outPipe.join();
+        errPipe.join();
+        return status;
+    }
+
+    /**
+     * Starts the subprocess, waits for it to exit, and returns its exit status.
+     */
+    public int execute() throws IOException, InterruptedException {
+        start();
+        return waitFor();
     }
 }
--- a/jdk/test/java/rmi/testlibrary/RMID.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/testlibrary/RMID.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -202,8 +202,6 @@
 
     public void start(long waitTime) throws IOException {
 
-        if (getVM() != null) return;
-
         // if rmid is already running, then the test will fail with
         // a well recognized exception (port already in use...).
 
--- a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -114,6 +114,7 @@
                 equal = "=";
             }
 
+            // create a client to tell checkFQDN what its rmi name is.
             JavaVM jvm = new JavaVM("CheckFQDNClient",
                                     propOption + property +
                                     equal +
@@ -125,10 +126,7 @@
             propertyBeingTested=property;
             propertyBeingTestedValue=propertyValue;
 
-            // create a client to tell checkFQDN what its rmi name is. */
-            jvm.start();
-
-            if (jvm.getVM().waitFor() != 0 ) {
+            if (jvm.execute() != 0) {
                 TestLibrary.bomb("Test failed, error in client.");
             }
 
--- a/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -102,9 +102,8 @@
                                         " -Drmi.registry.port=" +
                                         registryPort,
                                         "");
-                jvm.start();
 
-                if (jvm.getVM().waitFor() == 1 ) {
+                if (jvm.execute() != 0) {
                     TestLibrary.bomb("Client process failed");
                 }
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Principal/Implies.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7019834
+ * @summary test default implementation of Principal.implies
+ */
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.x500.X500Principal;
+
+public class Implies {
+    public static void main(String[] args) throws Exception {
+        X500Principal duke = new X500Principal("CN=Duke");
+        // should not throw NullPointerException
+        testImplies(duke, (Subject)null, false);
+
+        Set<Principal> principals = new HashSet<>();
+        principals.add(duke);
+        testImplies(duke, principals, true);
+
+        X500Principal tux = new X500Principal("CN=Tux");
+        principals.add(tux);
+        testImplies(duke, principals, true);
+
+        principals.add(new KerberosPrincipal("duke@java.com"));
+        testImplies(duke, principals, true);
+
+        principals.clear();
+        principals.add(tux);
+        testImplies(duke, principals, false);
+
+        System.out.println("test passed");
+    }
+
+    private static void testImplies(Principal principal,
+                                    Set<? extends Principal> principals,
+                                    boolean result)
+        throws SecurityException
+    {
+        Subject subject = new Subject(true, principals, Collections.emptySet(),
+                                      Collections.emptySet());
+        testImplies(principal, subject, result);
+    }
+
+    private static void testImplies(Principal principal,
+                                    Subject subject, boolean result)
+        throws SecurityException
+    {
+        if (principal.implies(subject) != result) {
+            throw new SecurityException("test failed");
+        }
+    }
+}
--- a/jdk/test/javax/crypto/Cipher/GCMAPI.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/javax/crypto/Cipher/GCMAPI.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -78,6 +78,8 @@
             c.updateAAD(src);
         } catch (UnsupportedOperationException e) {
             // swallow
+        } catch (IllegalStateException ise) {
+            // swallow
         }catch (Exception e) {
             e.printStackTrace();
             failed++;
@@ -99,6 +101,8 @@
             c.updateAAD(src, offset, len);
         } catch (UnsupportedOperationException e) {
             // swallow
+        } catch (IllegalStateException ise) {
+            // swallow
         } catch (Exception e) {
             e.printStackTrace();
             failed++;
@@ -120,6 +124,8 @@
             c.updateAAD(src);
         } catch (UnsupportedOperationException e) {
             // swallow
+        } catch (IllegalStateException ise) {
+            // swallow
         }catch (Exception e) {
             e.printStackTrace();
             failed++;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/8005019/bug8005019.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 8005019
+ * @summary JTable passes row index instead of length when inserts selection interval
+ * @author Alexander Scherbatiy
+ * @run main bug8005019
+ */
+
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+
+public class bug8005019 {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                testSelectionWithFilterTable();
+            }
+        });
+    }
+
+    private static void testSelectionWithFilterTable() {
+        DefaultTableModel model = new DefaultTableModel(0, 1);
+        // a model with 3 elements is the minimum to demonstrate
+        // the bug
+        int last = 2;
+        for (int i = 0; i <= last; i++) {
+            model.addRow(new Object[]{i});
+        }
+        JTable table = new JTable(model);
+        table.setAutoCreateRowSorter(true);
+        // set selection at the end
+        table.setRowSelectionInterval(last, last);
+        // exclude rows based on identifier
+        RowFilter filter = new GeneralFilter(new int[]{0});
+        ((DefaultRowSorter) table.getRowSorter()).setRowFilter(filter);
+        // insertRow _before or at_ selected model index, such that
+        // endIndex (in event) > 1
+        model.insertRow(2, new Object[]{"x"});
+    }
+
+    private static class GeneralFilter extends RowFilter<Object, Object> {
+
+        private int[] columns;
+        List excludes = Arrays.asList(0);
+
+        GeneralFilter(int[] columns) {
+            this.columns = columns;
+        }
+
+        public boolean include(RowFilter.Entry<? extends Object, ? extends Object> value) {
+            int count = value.getValueCount();
+            if (columns.length > 0) {
+                for (int i = columns.length - 1; i >= 0; i--) {
+                    int index = columns[i];
+                    if (index < count) {
+                        if (include(value, index)) {
+                            return true;
+                        }
+                    }
+                }
+            } else {
+                while (--count >= 0) {
+                    if (include(value, count)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        protected boolean include(
+                Entry<? extends Object, ? extends Object> entry,
+                int index) {
+            return !excludes.contains(entry.getIdentifier());
+        }
+    }
+}
--- a/jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -48,8 +48,7 @@
         ByteArrayOutputStream err = new ByteArrayOutputStream();
         JavaVM vm = new JavaVM(StartRegistry.class.getName(),
                                "-Dsun.rmi.transport.logLevel=v", "", out, err);
-        vm.start();
-        vm.getVM().waitFor();
+        vm.execute();
 
         String errString = err.toString();
 
--- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -65,8 +65,7 @@
         JavaVM vm = new JavaVM(DoRMIStuff.class.getName(),
             "-Djava.util.logging.config.file=" + loggingPropertiesFile,
                                "", out, err);
-        vm.start();
-        vm.getVM().waitFor();
+        vm.execute();
 
         /*
          * Verify that the subprocess had no System.out or System.err
--- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -104,7 +104,7 @@
             JavaVM jvm =
                 new JavaVM("sun.rmi.registry.RegistryImpl", "", Integer.toString(p));
             jvm.start();
-            DeadCachedConnection.subreg = jvm.getVM();
+            DeadCachedConnection.subreg = jvm;
 
         } catch (IOException e) {
             // one of these is summarily dropped, can't remember which one
@@ -117,7 +117,7 @@
         } catch (Exception whatever) {
         }
     }
-    private static Process subreg = null;
+    private static JavaVM subreg = null;
 
     public static void killRegistry() {
         if (DeadCachedConnection.subreg != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/ServiceCredsCombination.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+/*
+ * @test
+ * @bug 8005447
+ * @compile -XDignore.symbol.file ServiceCredsCombination.java
+ * @run main ServiceCredsCombination
+ * @summary default principal can act as anyone
+ */
+
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import sun.security.jgss.GSSUtil;
+
+public class ServiceCredsCombination {
+
+    public static void main(String[] args) throws Exception {
+        // pass
+        check("a", "a", princ("a"), key("a"));
+        check(null, "a", princ("a"), key("a"));
+        check("x", "NOCRED", princ("a"), key("a"));
+        // two pass
+        check("a", "a", princ("a"), key("a"), princ("b"), key("b"));
+        check("b", "b", princ("a"), key("a"), princ("b"), key("b"));
+        check(null, null, princ("a"), key("a"), princ("b"), key("b"));
+        check("x", "NOCRED", princ("a"), key("a"), princ("b"), key("b"));
+        // old ktab
+        check("b", "b", princ("b"), oldktab());
+        check("x", "NOCRED", princ("b"), oldktab());
+        check(null, "b", princ("b"), oldktab());
+        // Two old ktab
+        check("a", "a", princ("a"), princ("b"), oldktab(), oldktab());
+        check("b", "b", princ("a"), princ("b"), oldktab(), oldktab());
+        check(null, null, princ("a"), princ("b"), oldktab(), oldktab());
+        check("x", "NOCRED", princ("a"), princ("b"), oldktab(), oldktab());
+        // pass + old ktab
+        check("a", "a", princ("a"), princ("b"), key("a"), oldktab());
+        check("b", "b", princ("a"), princ("b"), key("a"), oldktab());
+        check(null, null, princ("a"), princ("b"), key("a"), oldktab());
+        check("x", "NOCRED", princ("a"), princ("b"), key("a"), oldktab());
+        // Compatibility, automatically add princ for keys
+        check(null, "a", key("a"));
+        check("x", "NOCRED", key("a"));
+        check(null, "a", key("a"), oldktab());
+        check("x", "NOCRED", key("a"), oldktab());
+        // Limitation, "a" has no key, but we don't know oldktab() is for "b"
+        check("a", "a", princ("a"), princ("b"), oldktab());
+    }
+
+    /**
+     * Checks the correct bound
+     * @param a get a creds for this principal, null for default one
+     * @param b expected name, null for still unbound, "NOCRED" for no creds
+     * @param objs princs, keys and keytabs in the subject
+     */
+    private static void check(final String a, String b, Object... objs)
+            throws Exception {
+        Subject subj = new Subject();
+        for (Object obj: objs) {
+            if (obj instanceof KerberosPrincipal) {
+                subj.getPrincipals().add((KerberosPrincipal)obj);
+            } else if (obj instanceof KerberosKey || obj instanceof KeyTab) {
+                subj.getPrivateCredentials().add(obj);
+            }
+        }
+        final GSSManager man = GSSManager.getInstance();
+        try {
+            String result = Subject.doAs(
+                    subj, new PrivilegedExceptionAction<String>() {
+                @Override
+                public String run() throws GSSException {
+                    GSSCredential cred = man.createCredential(
+                            a == null ? null : man.createName(r(a), null),
+                            GSSCredential.INDEFINITE_LIFETIME,
+                            GSSUtil.GSS_KRB5_MECH_OID,
+                            GSSCredential.ACCEPT_ONLY);
+                    GSSName name = cred.getName();
+                    return name == null ? null : name.toString();
+                }
+            });
+            if (!Objects.equals(result, r(b))) {
+                throw new Exception("Check failed: getInstance(" + a
+                        + ") has name " + result + ", not " + b);
+            }
+        } catch (PrivilegedActionException e) {
+            if (!"NOCRED".equals(b)) {
+                throw new Exception("Check failed: getInstance(" + a
+                        + ") is null " + ", but not one with name " + b);
+            }
+        }
+    }
+    private static String r(String s) {
+        return s == null ? null : (s+"@REALM");
+    }
+    private static KerberosPrincipal princ(String s) {
+        return new KerberosPrincipal(r(s));
+    }
+    private static KerberosKey key(String s) {
+        return new KerberosKey(princ(s), new byte[0], 0, 0);
+    }
+    private static KeyTab oldktab() {
+        return KeyTab.getInstance();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/AcceptPermissions.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file AcceptPermissions.java
+ * @run main/othervm AcceptPermissions
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.Permission;
+import javax.security.auth.kerberos.ServicePermission;
+import sun.security.jgss.GSSUtil;
+import java.util.*;
+
+public class AcceptPermissions extends SecurityManager {
+
+    private static Map<Permission,String> perms = new HashMap<>();
+    @Override
+    public void checkPermission(Permission perm) {
+        if (!(perm instanceof ServicePermission)) {
+            return;
+        }
+        ServicePermission sp = (ServicePermission)perm;
+        if (!sp.getActions().equals("accept")) {
+            return;
+        }
+        // We only care about accept ServicePermission in this test
+        try {
+            super.checkPermission(sp);
+        } catch (SecurityException se) {
+            if (perms.containsKey(sp)) {
+                perms.put(sp, "checked");
+            } else {
+                throw se;   // We didn't expect this is needed
+            }
+        }
+    }
+
+    // Fills in permissions we are expecting
+    private static void initPerms(String... names) {
+        perms.clear();
+        for (String name: names) {
+            perms.put(new ServicePermission(
+                    name + "@" + OneKDC.REALM, "accept"), "expected");
+        }
+    }
+
+    // Checks if they are all checked
+    private static void checkPerms() {
+        for (Map.Entry<Permission,String> entry: perms.entrySet()) {
+            if (entry.getValue().equals("expected")) {
+                throw new RuntimeException(
+                        "Expected but not used: " + entry.getKey());
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.setSecurityManager(new AcceptPermissions());
+        new OneKDC(null).writeJAASConf();
+        String two = "two {\n"
+                + " com.sun.security.auth.module.Krb5LoginModule required"
+                + "     principal=\"" + OneKDC.SERVER + "\" useKeyTab=true"
+                + "     isInitiator=false storeKey=true;\n"
+                + " com.sun.security.auth.module.Krb5LoginModule required"
+                + "     principal=\"" + OneKDC.BACKEND + "\" useKeyTab=true"
+                + "     isInitiator=false storeKey=true;\n"
+                + "};\n";
+        Files.write(Paths.get(OneKDC.JAAS_CONF), two.getBytes(),
+                StandardOpenOption.APPEND);
+
+        Context c, s;
+
+        // In all cases, a ServicePermission on the acceptor name is needed
+        // for a handshake. For default principal with no predictable name,
+        // permission not needed (yet) for credentials creation.
+
+        // Named principal
+        initPerms(OneKDC.SERVER);
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        checkPerms();
+        initPerms(OneKDC.SERVER);
+        Context.handshake(c, s);
+        checkPerms();
+
+        // Named principal (even if there are 2 JAAS modules)
+        initPerms(OneKDC.SERVER);
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("two");
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        checkPerms();
+        initPerms(OneKDC.SERVER);
+        Context.handshake(c, s);
+        checkPerms();
+
+        // Default principal with a predictable name
+        initPerms(OneKDC.SERVER);
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        checkPerms();
+        initPerms(OneKDC.SERVER);
+        Context.handshake(c, s);
+        checkPerms();
+
+        // Default principal with no predictable name
+        initPerms();    // permission not needed for cred !!!
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("two");
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        checkPerms();
+        initPerms(OneKDC.SERVER);   // still needed for handshake !!!
+        Context.handshake(c, s);
+        checkPerms();
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/CleanState.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/CleanState.java	Wed Jul 05 18:35:53 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6716534
+ * @compile -XDignore.symbol.file CleanState.java
  * @run main/othervm CleanState
  * @summary Krb5LoginModule has not cleaned temp info between authentication attempts
  */
--- a/jdk/test/sun/security/krb5/auto/Context.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/Context.java	Wed Jul 05 18:35:53 2017 +0200
@@ -131,21 +131,24 @@
         return out;
     }
 
+    /**
+     * Logins with username/password as a new Subject
+     */
     public static Context fromUserPass(
             String user, char[] pass, boolean storeKey) throws Exception {
-        return fromUserPass(null, user, pass, storeKey);
+        return fromUserPass(new Subject(), user, pass, storeKey);
     }
 
     /**
-     * Logins with a username and a password, using Krb5LoginModule directly
-     * @param s existing subject, test multiple princ & creds for single subj
-     * @param storeKey true if key should be saved, used on acceptor side
+     * Logins with username/password as an existing Subject. The
+     * same subject can be used multiple times to simulate multiple logins.
+     * @param s existing subject
      */
     public static Context fromUserPass(Subject s,
             String user, char[] pass, boolean storeKey) throws Exception {
         Context out = new Context();
         out.name = user;
-        out.s = s == null ? new Subject() : s;
+        out.s = s;
         Krb5LoginModule krb5 = new Krb5LoginModule();
         Map<String, String> map = new HashMap<>();
         Map<String, Object> shared = new HashMap<>();
@@ -172,14 +175,23 @@
     }
 
     /**
-     * Logins with a username and a keytab, using Krb5LoginModule directly
-     * @param storeKey true if key should be saved, used on acceptor side
+     * Logins with username/keytab as an existing Subject. The
+     * same subject can be used multiple times to simulate multiple logins.
+     * @param s existing subject
      */
-    public static Context fromUserKtab(String user, String ktab, boolean storeKey)
-            throws Exception {
+    public static Context fromUserKtab(
+            String user, String ktab, boolean storeKey) throws Exception {
+        return fromUserKtab(new Subject(), user, ktab, storeKey);
+    }
+
+    /**
+     * Logins with username/keytab as a new subject,
+     */
+    public static Context fromUserKtab(Subject s,
+            String user, String ktab, boolean storeKey) throws Exception {
         Context out = new Context();
         out.name = user;
-        out.s = new Subject();
+        out.s = s;
         Krb5LoginModule krb5 = new Krb5LoginModule();
         Map<String, String> map = new HashMap<>();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/DiffNameSameKey.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8005447
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file DiffNameSameKey.java
+ * @run main/othervm/fail DiffNameSameKey a
+ * @run main/othervm DiffNameSameKey b
+ */
+
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+
+/**
+ * This test confirms the compatibility codes described in
+ * ServiceCreds.getEKeys(). If the acceptor starts as x.us.oracle.com
+ * but client requests for x.us, as long as the KDC supports both names
+ * and the keys are the same, the auth should succeed.
+ */
+public class DiffNameSameKey {
+
+    static final String SERVER2 = "x" + OneKDC.SERVER;
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new KDC2();
+        kdc.addPrincipal(SERVER2, "samepass".toCharArray());
+        kdc.addPrincipal(OneKDC.SERVER, "samepass".toCharArray());
+        kdc.writeJAASConf();
+        kdc.writeKtab(OneKDC.KTAB);
+
+        Context c, s;
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+
+        switch (args[0]) {
+            case "a":   // If server starts as another service, should fail
+                c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_SPNEGO_MECH_OID);
+                s.startAsServer(SERVER2.replace('/', '@'),
+                        GSSUtil.GSS_SPNEGO_MECH_OID);
+                break;
+            case "b":   // If client requests another server with the same keys,
+                        // succeed to be compatible
+                c.startAsClient(SERVER2, GSSUtil.GSS_SPNEGO_MECH_OID);
+                s.startAsServer(OneKDC.SERVER.replace('/', '@'),
+                        GSSUtil.GSS_SPNEGO_MECH_OID);
+                break;
+        }
+
+        Context.handshake(c, s);
+
+        s.dispose();
+        c.dispose();
+    }
+
+    /**
+     * This KDC returns the same salt for all principals. This means same
+     * passwords generate same keys.
+     */
+    static class KDC2 extends OneKDC {
+        KDC2() throws Exception {
+            super(null);
+        }
+        @Override
+        public String getSalt(PrincipalName pn) {
+            return "SAME";
+        }
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/DynamicKeytab.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/DynamicKeytab.java	Wed Jul 05 18:35:53 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6894072
+ * @compile -XDignore.symbol.file DynamicKeytab.java
  * @run main/othervm DynamicKeytab
  * @summary always refresh keytab
  */
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 18:35:53 2017 +0200
@@ -285,10 +285,12 @@
             if (Character.isDigit(pass[pass.length-1])) {
                 kvno = pass[pass.length-1] - '0';
             }
-            ktab.addEntry(new PrincipalName(name,
-                    name.indexOf('/') < 0 ?
-                        PrincipalName.KRB_NT_UNKNOWN :
-                        PrincipalName.KRB_NT_SRV_HST),
+            PrincipalName pn = new PrincipalName(name,
+                        name.indexOf('/') < 0 ?
+                            PrincipalName.KRB_NT_UNKNOWN :
+                            PrincipalName.KRB_NT_SRV_HST);
+            ktab.addEntry(pn,
+                        getSalt(pn),
                         pass,
                         kvno,
                         true);
@@ -534,7 +536,7 @@
         if (pass == null) {
             throw new KrbException(server?
                 Krb5.KDC_ERR_S_PRINCIPAL_UNKNOWN:
-                Krb5.KDC_ERR_C_PRINCIPAL_UNKNOWN);
+                Krb5.KDC_ERR_C_PRINCIPAL_UNKNOWN, pn.toString());
         }
         return pass;
     }
@@ -544,7 +546,7 @@
      * @param p principal
      * @return the salt
      */
-    private String getSalt(PrincipalName p) {
+    protected String getSalt(PrincipalName p) {
         String pn = p.toString();
         if (p.getRealmString() == null) {
             pn = pn + "@" + getRealm();
--- a/jdk/test/sun/security/krb5/auto/KeyTabCompat.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/KeyTabCompat.java	Wed Jul 05 18:35:53 2017 +0200
@@ -38,7 +38,7 @@
  *
  * 1. If there is only KerberosKeys in private credential set and no
  *    KerberosPrincipal. JAAS login should go on.
- * 2. Even if KeyTab is used, user can still get KerberosKeys from
+ * 2. If KeyTab is used, user won't get KerberosKeys from
  *    private credentials set.
  */
 public class KeyTabCompat {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/TwoOrThree.java	Wed Jul 05 18:35:53 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8005447
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file TwoOrThree.java
+ * @run main/othervm TwoOrThree first first
+ * @run main/othervm/fail TwoOrThree first second
+ * @run main/othervm TwoOrThree - first
+ * @run main/othervm TwoOrThree - second
+ * @run main/othervm/fail TwoOrThree - third
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import javax.security.auth.Subject;
+import sun.security.jgss.GSSUtil;
+
+/*
+ * The JAAS login has two krb5 modules
+ *   1. principal is A
+ *   2. principal is B
+ * A named principal can only accept itself. The default principal can accept
+ * either, but not any other service even if the keytab also include its keys.
+ */
+public class TwoOrThree {
+
+    public static void main(String[] args) throws Exception {
+
+        String server = args[0].equals("-") ? null : args[0];
+        String target = args[1];
+        OneKDC kdc = new OneKDC(null);
+        kdc.addPrincipal("first", "first".toCharArray());
+        kdc.addPrincipal("second", "second".toCharArray());
+        kdc.addPrincipal("third", "third".toCharArray());
+        kdc.writeKtab(OneKDC.KTAB);
+
+        Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+
+        // Using keytabs
+        Subject sub4s = new Subject();
+        Context.fromUserKtab(sub4s, "first", OneKDC.KTAB, true);
+        Context s = Context.fromUserKtab(sub4s, "second", OneKDC.KTAB, true);
+        c.startAsClient(target, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(server, GSSUtil.GSS_KRB5_MECH_OID);
+        Context.handshake(c, s);
+
+        // Using keys
+        sub4s = new Subject();
+        Context.fromUserPass(sub4s, "first", "first".toCharArray(), true);
+        s = Context.fromUserPass(sub4s, "second", "second".toCharArray(), true);
+        c.startAsClient(target, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(server, GSSUtil.GSS_KRB5_MECH_OID);
+        Context.handshake(c, s);
+
+        s.dispose();
+        c.dispose();
+    }
+}
--- a/jdk/test/sun/security/provider/PolicyFile/Comparator.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/sun/security/provider/PolicyFile/Comparator.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2012, 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
@@ -39,7 +39,6 @@
 import javax.security.auth.x500.X500Principal;
 
 import sun.security.provider.PolicyFile;
-import com.sun.security.auth.PrincipalComparator;
 import com.sun.security.auth.UnixPrincipal;
 import com.sun.security.auth.NTUserPrincipal;
 import com.sun.security.auth.SolarisPrincipal;
@@ -90,7 +89,7 @@
     private static final Principal[] badP = new Principal[] {
                                 new SolarisPrincipal("bad") };
 
-    public static class PCompare1 implements PrincipalComparator {
+    public static class PCompare1 implements Principal {
 
         private String name;
 
@@ -98,6 +97,12 @@
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             if (subject.getPrincipals().contains(p1[0])) {
                 return true;
@@ -106,13 +111,19 @@
         }
     }
 
-    public static class PCompare2 implements PrincipalComparator {
+    public static class PCompare2 implements Principal {
         private String name;
 
         public PCompare2(String name) {
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             if (subject.getPrincipals().contains(p2[0]) &&
                 subject.getPrincipals().contains(p2[1])) {
@@ -122,13 +133,19 @@
         }
     }
 
-    public static class PCompare3 implements PrincipalComparator {
+    public static class PCompare3 implements Principal {
         private String name;
 
         public PCompare3(String name) {
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             return false;
         }
--- a/jdk/test/tools/launcher/FXLauncherTest.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/tools/launcher/FXLauncherTest.java	Wed Jul 05 18:35:53 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8001533
+ * @bug 8001533 8004547
  * @summary Test launching FX application with java -jar
  * Test uses main method and blank main method, a jfx app class and an incorrest
  * jfx app class, a main-class for the manifest, a bogus one and none.
@@ -47,6 +47,8 @@
 
     /* standard main class can be used as java main for fx app class */
     static final String StdMainClass = "helloworld.HelloWorld";
+    static final String ExtMainClass = "helloworld.ExtHello";
+    static final String NonFXMainClass = "helloworld.HelloJava";
     static int testcount = 0;
 
     /* a main method and a blank. */
@@ -107,9 +109,7 @@
     }
 
     /*
-     * Create class to extend fx java file for test application
-     * TODO: make test to create java file and this extension of the java file
-     *      and jar them together an run app via this java class.
+     * Create class that extends HelloWorld instead of Application
      */
     static void createExtJavaFile(String mainmethod) {
         try {
@@ -125,16 +125,48 @@
             compile("-cp", ".", "-d", ".", mainClass + JAVA_FILE_EXT);
         } catch (java.io.IOException ioe) {
             ioe.printStackTrace();
-            throw new RuntimeException("Failed creating HelloWorld.");
+            throw new RuntimeException("Failed creating ExtHello.");
+        }
+    }
+
+    /*
+     * Create non-JavaFX class for testing if jfxrt.jar is being loaded
+     * when it shouldn't be
+     */
+    static void createNonFXJavaFile() {
+        try {
+            String mainClass = "HelloJava";
+            List<String> contents = new ArrayList<>();
+            contents.add("package helloworld;");
+            contents.add("public class HelloJava {");
+            contents.add("    public static void main(String[] args) {");
+            contents.add("        for(String aa : args)");
+            contents.add("            System.out.println(\"arg: \" + aa);" );
+            contents.add("    }");
+            contents.add("}");
+            // Create and compile java source.
+            MainJavaFile = new File(mainClass + JAVA_FILE_EXT);
+            createFile(MainJavaFile, contents);
+            compile("-cp", ".", "-d", ".", mainClass + JAVA_FILE_EXT);
+        } catch (java.io.IOException ioe) {
+            ioe.printStackTrace();
+            throw new RuntimeException("Failed creating HelloJava.");
         }
     }
 
     // Create manifest for test fx application
-    static List<String> createManifestContents(String mainclassentry) {
+    static List<String> createManifestContents(String mainClassEntry, String fxMainEntry) {
         List<String> mcontents = new ArrayList<>();
         mcontents.add("Manifest-Version: 1.0");
         mcontents.add("Created-By: FXLauncherTest");
-        mcontents.add("Main-Class: " + mainclassentry);
+        if (mainClassEntry != null) {
+            mcontents.add("Main-Class: " + mainClassEntry);
+            System.out.println("Main-Class: " + mainClassEntry);
+        }
+        if (fxMainEntry != null) {
+            mcontents.add("JavaFX-Application-Class: " + fxMainEntry);
+            System.out.println("JavaFX-Application-Class: " + fxMainEntry);
+        }
         return mcontents;
     }
 
@@ -175,31 +207,41 @@
 
     /*
      * Set Main-Class and iterate main_methods.
-     * Try launching with both -jar and -cp methods.
+     * Try launching with both -jar and -cp methods, with and without FX main
+     * class manifest entry.
      * All cases should run.
+     *
+     * See sun.launcher.LauncherHelper$FXHelper for more details on how JavaFX
+     * applications are launched.
      */
     @Test
     static void testBasicFXApp() throws Exception {
-        testBasicFXApp(true);
-        testBasicFXApp(false);
+        testBasicFXApp(true, false);    // -cp, no JAC
+        testBasicFXApp(false, true);    // -jar, with JAC
+        testBasicFXApp(false, false);   // -jar, no JAC
     }
 
-    static void testBasicFXApp(boolean useCP) throws Exception {
+    static void testBasicFXApp(boolean useCP, boolean setFXMainClass) throws Exception {
         String testname = "testBasicFXApp";
+        if (useCP) {
+            testname = testname.concat("_useCP");
+        }
+        String fxMC = StdMainClass;
+        if (!setFXMainClass) {
+            testname = testname.concat("_noJAC");
+            fxMC = null;
+        }
         for (String mm : MAIN_METHODS) {
             testcount++;
             line();
-            System.out.println("test# " + testcount +
-                "-  Main method: " + mm +
-                 ";  MF main class: " + StdMainClass);
+            System.out.println("test# " + testcount + "-  Main method: " + mm);
             createJavaFile(mm);
-            createFile(ManifestFile, createManifestContents(StdMainClass));
+            createFile(ManifestFile, createManifestContents(StdMainClass, fxMC));
             createJar(FXtestJar, ManifestFile);
             String sTestJar = FXtestJar.getAbsolutePath();
             TestResult tr;
             if (useCP) {
                 tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]);
-                testname = testname.concat("_useCP");
             } else {
                 tr = doExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);
             }
@@ -224,26 +266,33 @@
      */
     @Test
     static void testExtendFXApp() throws Exception {
-        testExtendFXApp(true);
-        testExtendFXApp(false);
+        testExtendFXApp(true, false);   // -cp, no JAC
+        testExtendFXApp(false, true);   // -jar, with JAC
+        testExtendFXApp(false, false);  // -jar, no JAC
     }
 
-    static void testExtendFXApp(boolean useCP) throws Exception {
+    static void testExtendFXApp(boolean useCP, boolean setFXMainClass) throws Exception {
         String testname = "testExtendFXApp";
+        if (useCP) {
+            testname = testname.concat("_useCP");
+        }
+        String fxMC = ExtMainClass;
+        if (!setFXMainClass) {
+            testname = testname.concat("_noJAC");
+            fxMC = null;
+        }
         for (String mm : MAIN_METHODS) {
             testcount++;
             line();
-            System.out.println("test# " + testcount +
-                "-  Main method: " + mm + ";  MF main class: " + StdMainClass);
+            System.out.println("test# " + testcount + "-  Main method: " + mm);
             createJavaFile(mm);
             createExtJavaFile(mm);
-            createFile(ManifestFile, createManifestContents(StdMainClass));
+            createFile(ManifestFile, createManifestContents(ExtMainClass, fxMC));
             createJar(FXtestJar, ManifestFile);
             String sTestJar = FXtestJar.getAbsolutePath();
             TestResult tr;
             if (useCP) {
-                tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]);
-                testname = testname.concat("_useCP");
+                tr = doExec(javaCmd, "-cp", sTestJar, ExtMainClass, APP_PARMS[0], APP_PARMS[1]);
             } else {
                 tr = doExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);
             }
@@ -256,27 +305,82 @@
                     }
                 }
             }
-            checkStatus(tr, testname, testcount, StdMainClass);
+            checkStatus(tr, testname, testcount, ExtMainClass);
         }
     }
 
     /*
+     * Ensure we can NOT launch a FX app jar with no Main-Class manifest entry
+     */
+    @Test
+    static void testMissingMC() throws Exception {
+        String testname = "testMissingMC";
+        testcount++;
+        line();
+        System.out.println("test# " + testcount + ": abort on missing Main-Class");
+        createJavaFile(" "); // no main() needed
+        createFile(ManifestFile, createManifestContents(null, StdMainClass)); // No MC, but supply JAC
+        createJar(FXtestJar, ManifestFile);
+        String sTestJar = FXtestJar.getAbsolutePath();
+        TestResult tr = doExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);
+        tr.checkNegative(); // should abort if no Main-Class
+        if (tr.testStatus) {
+            if (!tr.contains("no main manifest attribute")) {
+                System.err.println("ERROR: launcher did not abort properly");
+            }
+        } else {
+            System.err.println("ERROR: jar executed with no Main-Class!");
+        }
+        checkStatus(tr, testname, testcount, StdMainClass);
+    }
+
+    /*
      * test to ensure that we don't load any extraneous fx jars when
      * launching a standard java application
+     * Test both -cp and -jar methods since they use different code paths.
+     * Neither case should cause jfxrt.jar to be loaded.
      */
     @Test
-    static void testExtraneousJars()throws Exception {
+    static void testExtraneousJars() throws Exception {
+        testExtraneousJars(true);
+        testExtraneousJars(false);
+    }
+
+    static void testExtraneousJars(boolean useCP) throws Exception {
         String testname = "testExtraneousJars";
+        if (useCP) {
+            testname = testname.concat("_useCP");
+        }
         testcount++;
         line();
-        System.out.println("test# " + testcount);
-        TestResult tr = doExec(javacCmd, "-J-verbose:class", "-version");
-        if (!tr.notContains("jfxrt.jar")) {
-            System.out.println("testing for extraneous jfxrt jar");
-            System.out.println(tr);
-            throw new Exception("jfxrt.jar is being loaded by javac!!!");
+        System.out.println("test# " + testcount
+                + ": test for erroneous jfxrt.jar loading");
+        createNonFXJavaFile();
+        createFile(ManifestFile, createManifestContents(NonFXMainClass, null));
+        createJar(FXtestJar, ManifestFile);
+        String sTestJar = FXtestJar.getAbsolutePath();
+        TestResult tr;
+
+        if (useCP) {
+            tr = doExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]);
+        } else {
+            tr = doExec(javaCmd, "-verbose:class", "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);
         }
-        checkStatus(tr, testname, testcount, StdMainClass);
+        tr.checkPositive();
+        if (tr.testStatus) {
+            if (!tr.notContains("jfxrt.jar")) {
+                System.out.println("testing for extraneous jfxrt jar");
+                System.out.println(tr);
+                throw new Exception("jfxrt.jar is being loaded, it should not be!");
+            }
+            for (String p : APP_PARMS) {
+                if (!tr.contains(p)) {
+                    System.err.println("ERROR: Did not find "
+                            + p + " in output!");
+                }
+            }
+        }
+        checkStatus(tr, testname, testcount, NonFXMainClass);
     }
 
     public static void main(String... args) throws Exception {
--- a/jdk/test/tools/launcher/VersionCheck.java	Thu Jan 10 09:55:26 2013 -0800
+++ b/jdk/test/tools/launcher/VersionCheck.java	Wed Jul 05 18:35:53 2017 +0200
@@ -68,6 +68,7 @@
         "jcmd",
         "jconsole",
         "jcontrol",
+        "jdeps",
         "jinfo",
         "jmap",
         "jps",