Merge jdk8-b73
authorduke
Wed, 05 Jul 2017 18:36:11 +0200
changeset 15047 fe94b40ffd93
parent 15046 c2fc8078c9a1 (diff)
parent 14984 5b9c408485ed (current diff)
child 15048 d2676af0a2a5
child 15049 9d683ae7c5ec
child 15120 8bac833614e0
child 15122 d01407f23a5c
child 15125 a406c61365c3
child 15151 5a4f1fb4c6ef
child 15153 573ba3de94a3
child 15156 79594b91a320
child 15159 2a928ef3978d
child 15162 d5c6242eb271
child 15165 2d74b1d7456b
child 15171 15b8cd02927b
child 15175 ff3529df71a3
child 15270 e2777acce5f3
child 15319 b3d5f7360aec
child 15347 4123ca5ab8fb
child 15364 deefeacccc41
Merge
--- a/.hgtags-top-repo	Wed Jul 05 18:35:27 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/common/bin/compare_exceptions.sh.incl	Wed Jul 05 18:36:11 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/corba/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -193,3 +193,4 @@
 22ddcac208a8dea894a16887d04f3ca4d3c5d267 jdk8-b69
 603cceb495c8133d47b26a7502d51c7d8a67d76b jdk8-b70
 8171d23e914d758836527b80b06debcfdb718f2d jdk8-b71
+cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72
--- a/hotspot/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -305,3 +305,4 @@
 990bbd393c239d95310ccc38094e57923bbf1d4a hs25-b14
 e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70
 0847210f85480bf3848dc90bc2ab23c0a4791b55 jdk8-b71
+d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72
--- a/jaxp/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -193,3 +193,4 @@
 789a855de959f7e9600e57759c6c3dbb0b24d78b jdk8-b69
 6ec9edffc286c9c9ac96c9cd2050b01cb5d514a8 jdk8-b70
 499be952a291cec1dc774a84a238941d6faf772d jdk8-b71
+bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72
--- a/jaxws/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -193,3 +193,4 @@
 756323c990115a9c0341d67b10f2d52c6370e35d jdk8-b69
 3b1c2733d47ee9f8c530925df4041c59f9ee5a31 jdk8-b70
 f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71
+d9707230294d54e695e745a90de6112909100f12 jdk8-b72
--- a/jdk/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -193,3 +193,4 @@
 a8012d8d7e9c5035de0bdd4887dc9f7c54008f21 jdk8-b69
 a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70
 2a5af0f766d0acd68a81fb08fe11fd66795f86af jdk8-b71
+32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72
--- a/jdk/make/common/Release.gmk	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/make/common/Release.gmk	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/make/docs/NON_CORE_PKGS.gmk	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/make/launchers/Makefile	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/make/launchers/Makefile.launcher	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/makefiles/CompileLaunchers.gmk	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/makefiles/CreateJars.gmk	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/makefiles/Images.gmk	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java	Wed Jul 05 18:36:11 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:36:11 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:36:11 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:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/Integer.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/String.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/StringBuilder.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/lang/StringIndexOutOfBoundsException.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/security/Principal.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/javax/crypto/Cipher.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/javax/crypto/spec/GCMParameterSpec.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/launcher/resources/launcher.properties	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/PolicyParser.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/share/native/java/lang/System.c	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/solaris/native/java/lang/java_props_md.c	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512524.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4512704.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4517355.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/Test4626070.java	Wed Jul 05 18:36:11 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:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/lang/Runtime/exec/WinCommand.java	Wed Jul 05 18:36:11 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:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/net/Socks/SocksV4Test.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/activation/checkusage/CheckUsage.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/registry/checkusage/CheckUsage.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/registry/reexport/Reexport.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/testlibrary/RMID.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/javax/crypto/Cipher/GCMAPI.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java	Wed Jul 05 18:36:11 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:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/CleanState.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/Context.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/DynamicKeytab.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/KeyTabCompat.java	Wed Jul 05 18:36:11 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:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/sun/security/provider/PolicyFile/Comparator.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/tools/launcher/FXLauncherTest.java	Wed Jul 05 18:36:11 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	Wed Jul 05 18:35:27 2017 +0200
+++ b/jdk/test/tools/launcher/VersionCheck.java	Wed Jul 05 18:36:11 2017 +0200
@@ -68,6 +68,7 @@
         "jcmd",
         "jconsole",
         "jcontrol",
+        "jdeps",
         "jinfo",
         "jmap",
         "jps",
--- a/langtools/.hgtags	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 18:36:11 2017 +0200
@@ -193,3 +193,4 @@
 d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69
 47f71d7c124f24c2fe2dfc49865b332345b458ed jdk8-b70
 467e4d9281bcf119eaec42af1423c96bd401871c jdk8-b71
+6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72
--- a/langtools/make/build.properties	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/make/build.properties	Wed Jul 05 18:36:11 2017 +0200
@@ -153,6 +153,7 @@
 javap.includes = \
         com/sun/tools/classfile/ \
         com/sun/tools/javap/ \
+        com/sun/tools/jdeps/ \
         sun/tools/javap/
 
 javap.tests = \
--- a/langtools/makefiles/BuildLangtools.gmk	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/makefiles/BuildLangtools.gmk	Wed Jul 05 18:36:11 2017 +0200
@@ -75,6 +75,7 @@
 	printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties
 	printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javap/resources/version.properties
 	printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties
+	printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.properties
 	echo Compiling $(words $(PROPSOURCES) v1 v2 v3) properties into resource bundles
 	$(TOOL_COMPILEPROPS_CMD) $(PROPCMDLINE) \
 		-compile 	$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties \
@@ -85,6 +86,9 @@
 				java.util.ListResourceBundle \
 		-compile	$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties \
 				$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.java \
+				java.util.ListResourceBundle \
+		-compile	$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.properties \
+				$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.java \
 				java.util.ListResourceBundle
 	echo PROPS_ARE_CREATED=yes > $@
 
--- a/langtools/src/share/classes/com/sun/javadoc/AnnotationDesc.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/javadoc/AnnotationDesc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -52,6 +52,12 @@
      */
     ElementValuePair[] elementValues();
 
+    /**
+     * Check for the synthesized bit on the annotation.
+     *
+     * @return true if the annotation is synthesized.
+     */
+    boolean isSynthesized();
 
     /**
      * Represents an association between an annotation type element
--- a/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -51,6 +51,7 @@
     public static final String LineNumberTable          = "LineNumberTable";
     public static final String LocalVariableTable       = "LocalVariableTable";
     public static final String LocalVariableTypeTable   = "LocalVariableTypeTable";
+    public static final String MethodParameters         = "MethodParameters";
     public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
     public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
     public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@@ -113,6 +114,7 @@
             standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
 
             if (!compat) { // old javap does not recognize recent attributes
+                standardAttributes.put(MethodParameters, MethodParameters_attribute.class);
                 standardAttributes.put(CompilationID, CompilationID_attribute.class);
                 standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
                 standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
@@ -171,6 +173,7 @@
         R visitLineNumberTable(LineNumberTable_attribute attr, P p);
         R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
         R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
+        R visitMethodParameters(MethodParameters_attribute attr, P p);
         R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
         R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
         R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
--- a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -479,6 +479,15 @@
             out.writeShort(entry.index);
         }
 
+        public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
+            out.writeByte(attr.method_parameter_table.length);
+            for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
+                out.writeShort(e.name_index);
+                out.writeInt(e.flags);
+            }
+            return null;
+        }
+
         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
--- a/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java	Wed Jul 05 18:36:11 2017 +0200
@@ -142,6 +142,15 @@
     }
 
     /**
+     * Get a finder to do class dependency analysis.
+     *
+     * @return a Class dependency finder
+     */
+    public static Finder getClassDependencyFinder() {
+        return new ClassDependencyFinder();
+    }
+
+    /**
      * Get the finder used to locate the dependencies for a class.
      * @return the finder
      */
@@ -246,8 +255,6 @@
         return results;
     }
 
-
-
     /**
      * Find the dependencies of a class, using the current
      * {@link Dependencies#getFinder finder} and
@@ -306,38 +313,44 @@
      * A location identifying a class.
      */
     static class SimpleLocation implements Location {
-        public SimpleLocation(String className) {
-            this.className = className;
+        public SimpleLocation(String name) {
+            this.name = name;
+            this.className = name.replace('/', '.').replace('$', '.');
         }
 
-        /**
-         * Get the name of the class being depended on. This name will be used to
-         * locate the class file for transitive dependency analysis.
-         * @return the name of the class being depended on
-         */
+        public String getName() {
+            return name;
+        }
+
         public String getClassName() {
             return className;
         }
 
+        public String getPackageName() {
+            int i = name.lastIndexOf('/');
+            return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
+        }
+
         @Override
         public boolean equals(Object other) {
             if (this == other)
                 return true;
             if (!(other instanceof SimpleLocation))
                 return false;
-            return (className.equals(((SimpleLocation) other).className));
+            return (name.equals(((SimpleLocation) other).name));
         }
 
         @Override
         public int hashCode() {
-            return className.hashCode();
+            return name.hashCode();
         }
 
         @Override
         public String toString() {
-            return className;
+            return name;
         }
 
+        private String name;
         private String className;
     }
 
@@ -431,9 +444,7 @@
         }
 
         public boolean accepts(Dependency dependency) {
-            String cn = dependency.getTarget().getClassName();
-            int lastSep = cn.lastIndexOf("/");
-            String pn = (lastSep == -1 ? "" : cn.substring(0, lastSep));
+            String pn = dependency.getTarget().getPackageName();
             if (packageNames.contains(pn))
                 return true;
 
@@ -451,8 +462,6 @@
         private final boolean matchSubpackages;
     }
 
-
-
     /**
      * This class identifies class names directly or indirectly in the constant pool.
      */
@@ -462,6 +471,26 @@
             for (CPInfo cpInfo: classfile.constant_pool.entries()) {
                 v.scan(cpInfo);
             }
+            try {
+                v.addClass(classfile.super_class);
+                v.addClasses(classfile.interfaces);
+                v.scan(classfile.attributes);
+
+                for (Field f : classfile.fields) {
+                    v.scan(f.descriptor, f.attributes);
+                }
+                for (Method m : classfile.methods) {
+                    v.scan(m.descriptor, m.attributes);
+                    Exceptions_attribute e =
+                        (Exceptions_attribute)m.attributes.get(Attribute.Exceptions);
+                    if (e != null) {
+                        v.addClasses(e.exception_index_table);
+                    }
+                }
+            } catch (ConstantPoolException e) {
+                throw new ClassFileError(e);
+            }
+
             return v.deps;
         }
     }
@@ -558,9 +587,7 @@
             void scan(Descriptor d, Attributes attrs) {
                 try {
                     scan(new Signature(d.index).getType(constant_pool));
-                    Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature);
-                    if (sa != null)
-                        scan(new Signature(sa.signature_index).getType(constant_pool));
+                    scan(attrs);
                 } catch (ConstantPoolException e) {
                     throw new ClassFileError(e);
                 }
@@ -574,6 +601,43 @@
                 t.accept(this, null);
             }
 
+            void scan(Attributes attrs) {
+                try {
+                    Signature_attribute sa = (Signature_attribute)attrs.get(Attribute.Signature);
+                    if (sa != null)
+                        scan(sa.getParsedSignature().getType(constant_pool));
+
+                    scan((RuntimeVisibleAnnotations_attribute)
+                            attrs.get(Attribute.RuntimeVisibleAnnotations));
+                    scan((RuntimeVisibleParameterAnnotations_attribute)
+                            attrs.get(Attribute.RuntimeVisibleParameterAnnotations));
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            private void scan(RuntimeAnnotations_attribute attr) throws ConstantPoolException {
+                if (attr == null) {
+                    return;
+                }
+                for (int i = 0; i < attr.annotations.length; i++) {
+                    int index = attr.annotations[i].type_index;
+                    scan(new Signature(index).getType(constant_pool));
+                }
+            }
+
+            private void scan(RuntimeParameterAnnotations_attribute attr) throws ConstantPoolException {
+                if (attr == null) {
+                    return;
+                }
+                for (int param = 0; param < attr.parameter_annotations.length; param++) {
+                    for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
+                        int index = attr.parameter_annotations[param][i].type_index;
+                        scan(new Signature(index).getType(constant_pool));
+                    }
+                }
+            }
+
             void addClass(int index) throws ConstantPoolException {
                 if (index != 0) {
                     String name = constant_pool.getClassInfo(index).getBaseName();
@@ -698,6 +762,7 @@
                 findDependencies(type.paramTypes);
                 findDependencies(type.returnType);
                 findDependencies(type.throwsTypes);
+                findDependencies(type.typeParamTypes);
                 return null;
             }
 
@@ -709,7 +774,7 @@
 
             public Void visitClassType(ClassType type, Void p) {
                 findDependencies(type.outerType);
-                addDependency(type.name);
+                addDependency(type.getBinaryName());
                 findDependencies(type.typeArgs);
                 return null;
             }
--- a/langtools/src/share/classes/com/sun/tools/classfile/Dependency.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Dependency.java	Wed Jul 05 18:36:11 2017 +0200
@@ -71,7 +71,19 @@
          * dependency analysis.
          * @return the name of the class containing the location.
          */
+        String getName();
+
+        /**
+         * Get the fully-qualified name of the class containing the location.
+         * @return the fully-qualified name of the class containing the location.
+         */
         String getClassName();
+
+        /**
+         * Get the package name of the class containing the location.
+         * @return the package name of the class containing the location.
+         */
+        String getPackageName();
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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 com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.13.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class MethodParameters_attribute extends Attribute {
+
+    public final int method_parameter_table_length;
+    public final Entry[] method_parameter_table;
+
+    MethodParameters_attribute(ClassReader cr,
+                              int name_index,
+                              int length)
+        throws IOException {
+        super(name_index, length);
+
+        method_parameter_table_length = cr.readUnsignedByte();
+        method_parameter_table = new Entry[method_parameter_table_length];
+        for (int i = 0; i < method_parameter_table_length; i++)
+            method_parameter_table[i] = new Entry(cr);
+    }
+
+    public MethodParameters_attribute(ConstantPool constant_pool,
+                                      Entry[] method_parameter_table)
+        throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.MethodParameters),
+             method_parameter_table);
+    }
+
+    public MethodParameters_attribute(int name_index,
+                                      Entry[] method_parameter_table) {
+        super(name_index, 1 + method_parameter_table.length * Entry.length());
+        this.method_parameter_table_length = method_parameter_table.length;
+        this.method_parameter_table = method_parameter_table;
+    }
+
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitMethodParameters(this, data);
+    }
+
+    public static class Entry {
+        Entry(ClassReader cr) throws IOException {
+            name_index = cr.readUnsignedShort();
+            flags = cr.readInt();
+        }
+
+        public static int length() {
+            return 6;
+        }
+
+        public final int name_index;
+        public final int flags;
+    }
+
+}
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -321,7 +321,8 @@
             code.addContent(" ");
         }
         if (member.isMethod()) {
-            if (((MethodDoc)member).isAbstract()) {
+            if (!(member.containingClass().isInterface()) &&
+                    ((MethodDoc)member).isAbstract()) {
                 code.addContent("abstract ");
             }
             // This check for isDefault() and the default modifier needs to be
@@ -329,7 +330,7 @@
             // method summary section. Once the default modifier is added
             // to the Modifier list on DocEnv and once it is updated to use the
             // javax.lang.model.element.Modifier, we will need to remove this.
-            else if (((MethodDoc)member).isDefault()) {
+            if (((MethodDoc)member).isDefault()) {
                 code.addContent("default ");
             }
         }
@@ -561,11 +562,14 @@
         if (member instanceof MethodDoc && !member.isAnnotationTypeElement()) {
             int methodType = (member.isStatic()) ? MethodTypes.STATIC.value() :
                     MethodTypes.INSTANCE.value();
-            methodType = (classdoc.isInterface() || ((MethodDoc)member).isAbstract()) ?
-                    methodType | MethodTypes.ABSTRACT.value() :
-                    methodType | MethodTypes.CONCRETE.value();
-            if (((MethodDoc)member).isDefault()) {
-                methodType = methodType | MethodTypes.DEFAULT.value();
+            if (member.containingClass().isInterface()) {
+                methodType = (((MethodDoc) member).isAbstract())
+                        ? methodType | MethodTypes.ABSTRACT.value()
+                        : methodType | MethodTypes.DEFAULT.value();
+            } else {
+                methodType = (((MethodDoc) member).isAbstract())
+                        ? methodType | MethodTypes.ABSTRACT.value()
+                        : methodType | MethodTypes.CONCRETE.value();
             }
             if (Util.isDeprecated(member) || Util.isDeprecated(classdoc)) {
                 methodType = methodType | MethodTypes.DEPRECATED.value();
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -90,6 +90,16 @@
     protected boolean printedAnnotationHeading = false;
 
     /**
+     * To check whether the repeated annotations is documented or not.
+     */
+    private boolean isAnnotationDocumented = false;
+
+    /**
+     * To check whether the container annotations is documented or not.
+     */
+    private boolean isContainerDocumented = false;
+
+    /**
      * Constructor to construct the HtmlStandardWriter object.
      *
      * @param path File to be generated.
@@ -1793,50 +1803,66 @@
         StringBuilder annotation;
         for (int i = 0; i < descList.length; i++) {
             AnnotationTypeDoc annotationDoc = descList[i].annotationType();
-            if (! Util.isDocumentedAnnotation(annotationDoc)){
+            // If an annotation is not documented, do not add it to the list. If
+            // the annotation is of a repeatable type, and if it is not documented
+            // and also if its container annotation is not documented, do not add it
+            // to the list. If an annotation of a repeatable type is not documented
+            // but its container is documented, it will be added to the list.
+            if (! Util.isDocumentedAnnotation(annotationDoc) &&
+                    (!isAnnotationDocumented && !isContainerDocumented)) {
                 continue;
             }
             annotation = new StringBuilder();
+            isAnnotationDocumented = false;
             LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
                 LinkInfoImpl.CONTEXT_ANNOTATION, annotationDoc);
-            linkInfo.label = "@" + annotationDoc.name();
-            annotation.append(getLink(linkInfo));
             AnnotationDesc.ElementValuePair[] pairs = descList[i].elementValues();
-            if (pairs.length > 0) {
-                annotation.append('(');
+            // If the annotation is synthesized, do not print the container.
+            if (descList[i].isSynthesized()) {
                 for (int j = 0; j < pairs.length; j++) {
-                    if (j > 0) {
-                        annotation.append(",");
-                        if (linkBreak) {
-                            annotation.append(DocletConstants.NL);
-                            int spaces = annotationDoc.name().length() + 2;
-                            for (int k = 0; k < (spaces + indent); k++) {
-                                annotation.append(' ');
-                            }
-                        }
-                    }
-                    annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
-                        pairs[j].element(), pairs[j].element().name(), false));
-                    annotation.append('=');
                     AnnotationValue annotationValue = pairs[j].value();
                     List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
                     if (annotationValue.value() instanceof AnnotationValue[]) {
                         AnnotationValue[] annotationArray =
-                            (AnnotationValue[]) annotationValue.value();
-                        for (int k = 0; k < annotationArray.length; k++) {
-                            annotationTypeValues.add(annotationArray[k]);
-                        }
+                                (AnnotationValue[]) annotationValue.value();
+                        annotationTypeValues.addAll(Arrays.asList(annotationArray));
                     } else {
                         annotationTypeValues.add(annotationValue);
                     }
-                    annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
-                    for (Iterator<AnnotationValue> iter = annotationTypeValues.iterator(); iter.hasNext(); ) {
-                        annotation.append(annotationValueToString(iter.next()));
-                        annotation.append(iter.hasNext() ? "," : "");
+                    String sep = "";
+                    for (AnnotationValue av : annotationTypeValues) {
+                        annotation.append(sep);
+                        annotation.append(annotationValueToString(av));
+                        sep = " ";
                     }
-                    annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
                 }
-                annotation.append(")");
+            }
+            else if (isAnnotationArray(pairs)) {
+                // If the container has 1 or more value defined and if the
+                // repeatable type annotation is not documented, do not print
+                // the container.
+                if (pairs.length == 1 && isAnnotationDocumented) {
+                    AnnotationValue[] annotationArray =
+                            (AnnotationValue[]) (pairs[0].value()).value();
+                    List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
+                    annotationTypeValues.addAll(Arrays.asList(annotationArray));
+                    String sep = "";
+                    for (AnnotationValue av : annotationTypeValues) {
+                        annotation.append(sep);
+                        annotation.append(annotationValueToString(av));
+                        sep = " ";
+                    }
+                }
+                // If the container has 1 or more value defined and if the
+                // repeatable type annotation is not documented, print the container.
+                else {
+                    addAnnotations(annotationDoc, linkInfo, annotation, pairs,
+                        indent, false);
+                }
+            }
+            else {
+                addAnnotations(annotationDoc, linkInfo, annotation, pairs,
+                        indent, linkBreak);
             }
             annotation.append(linkBreak ? DocletConstants.NL : "");
             results.add(annotation.toString());
@@ -1844,6 +1870,91 @@
         return results;
     }
 
+    /**
+     * Add annotation to the annotation string.
+     *
+     * @param annotationDoc the annotation being documented
+     * @param linkInfo the information about the link
+     * @param annotation the annotation string to which the annotation will be added
+     * @param pairs annotation type element and value pairs
+     * @param indent the number of extra spaces to indent the annotations.
+     * @param linkBreak if true, add new line between each member value
+     */
+    private void addAnnotations(AnnotationTypeDoc annotationDoc, LinkInfoImpl linkInfo,
+            StringBuilder annotation, AnnotationDesc.ElementValuePair[] pairs,
+            int indent, boolean linkBreak) {
+        linkInfo.label = "@" + annotationDoc.name();
+        annotation.append(getLink(linkInfo));
+        if (pairs.length > 0) {
+            annotation.append('(');
+            for (int j = 0; j < pairs.length; j++) {
+                if (j > 0) {
+                    annotation.append(",");
+                    if (linkBreak) {
+                        annotation.append(DocletConstants.NL);
+                        int spaces = annotationDoc.name().length() + 2;
+                        for (int k = 0; k < (spaces + indent); k++) {
+                            annotation.append(' ');
+                        }
+                    }
+                }
+                annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
+                        pairs[j].element(), pairs[j].element().name(), false));
+                annotation.append('=');
+                AnnotationValue annotationValue = pairs[j].value();
+                List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
+                if (annotationValue.value() instanceof AnnotationValue[]) {
+                    AnnotationValue[] annotationArray =
+                            (AnnotationValue[]) annotationValue.value();
+                    annotationTypeValues.addAll(Arrays.asList(annotationArray));
+                } else {
+                    annotationTypeValues.add(annotationValue);
+                }
+                annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
+                String sep = "";
+                for (AnnotationValue av : annotationTypeValues) {
+                    annotation.append(sep);
+                    annotation.append(annotationValueToString(av));
+                    sep = ",";
+                }
+                annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
+                isContainerDocumented = false;
+            }
+            annotation.append(")");
+        }
+    }
+
+    /**
+     * Check if the annotation contains an array of annotation as a value. This
+     * check is to verify if a repeatable type annotation is present or not.
+     *
+     * @param pairs annotation type element and value pairs
+     *
+     * @return true if the annotation contains an array of annotation as a value.
+     */
+    private boolean isAnnotationArray(AnnotationDesc.ElementValuePair[] pairs) {
+        AnnotationValue annotationValue;
+        for (int j = 0; j < pairs.length; j++) {
+            annotationValue = pairs[j].value();
+            if (annotationValue.value() instanceof AnnotationValue[]) {
+                AnnotationValue[] annotationArray =
+                        (AnnotationValue[]) annotationValue.value();
+                if (annotationArray.length > 1) {
+                    if (annotationArray[0].value() instanceof AnnotationDesc) {
+                        AnnotationTypeDoc annotationDoc =
+                                ((AnnotationDesc) annotationArray[0].value()).annotationType();
+                        isContainerDocumented = true;
+                        if (Util.isDocumentedAnnotation(annotationDoc)) {
+                            isAnnotationDocumented = true;
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     private String annotationValueToString(AnnotationValue annotationValue) {
         if (annotationValue.value() instanceof Type) {
             Type type = (Type) annotationValue.value();
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1283,8 +1283,9 @@
                 List<Name> paramNames = savedParameterNames;
                 savedParameterNames = null;
                 // discard the provided names if the list of names is the wrong size.
-                if (paramNames == null || paramNames.size() != type.getParameterTypes().size())
+                if (paramNames == null || paramNames.size() != type.getParameterTypes().size()) {
                     paramNames = List.nil();
+                }
                 ListBuffer<VarSymbol> buf = new ListBuffer<VarSymbol>();
                 List<Name> remaining = paramNames;
                 // assert: remaining and paramNames are both empty or both
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 05 18:36:11 2017 +0200
@@ -38,6 +38,7 @@
 import javax.tools.JavaFileObject;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Queue;
@@ -177,29 +178,19 @@
          * attribution round must follow one or more speculative rounds.
          */
         Type check(ResultInfo resultInfo) {
+            return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
+        }
+
+        Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
             DeferredAttrContext deferredAttrContext =
                     resultInfo.checkContext.deferredAttrContext();
             Assert.check(deferredAttrContext != emptyDeferredAttrContext);
-            List<Type> stuckVars = stuckVars(tree, env, resultInfo);
             if (stuckVars.nonEmpty()) {
                 deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
                 return Type.noType;
             } else {
                 try {
-                    switch (deferredAttrContext.mode) {
-                        case SPECULATIVE:
-                            Assert.check(mode == null ||
-                                    (mode == AttrMode.SPECULATIVE &&
-                                    speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
-                            JCTree speculativeTree = attribSpeculative(tree, env, resultInfo);
-                            speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
-                            return speculativeTree.type;
-                        case CHECK:
-                            Assert.check(mode == AttrMode.SPECULATIVE);
-                            return attr.attribTree(tree, env, resultInfo);
-                    }
-                    Assert.error();
-                    return null;
+                    return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
                 } finally {
                     mode = deferredAttrContext.mode;
                 }
@@ -208,6 +199,43 @@
     }
 
     /**
+     * A completer for deferred types. Defines an entry point for type-checking
+     * a deferred type.
+     */
+    interface DeferredTypeCompleter {
+        /**
+         * Entry point for type-checking a deferred type. Depending on the
+         * circumstances, type-checking could amount to full attribution
+         * or partial structural check (aka potential applicability).
+         */
+        Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
+    }
+
+    /**
+     * A basic completer for deferred types. This completer type-checks a deferred type
+     * using attribution; depending on the attribution mode, this could be either standard
+     * or speculative attribution.
+     */
+    DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
+        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+            switch (deferredAttrContext.mode) {
+                case SPECULATIVE:
+                    Assert.check(dt.mode == null ||
+                            (dt.mode == AttrMode.SPECULATIVE &&
+                            dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
+                    JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
+                    dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
+                    return speculativeTree.type;
+                case CHECK:
+                    Assert.check(dt.mode == AttrMode.SPECULATIVE);
+                    return attr.attribTree(dt.tree, dt.env, resultInfo);
+            }
+            Assert.error();
+            return null;
+        }
+    };
+
+    /**
      * The 'mode' in which the deferred type is to be type-checked
      */
     public enum AttrMode {
@@ -498,10 +526,80 @@
                 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
             return List.nil();
         } else {
-            StuckChecker sc = new StuckChecker(resultInfo, env);
+            return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext());
+        }
+    }
+    //where
+        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) {
+            StuckChecker sc = new StuckChecker(pt, inferenceContext);
             sc.scan(tree);
             return List.from(sc.stuckVars);
         }
+
+    /**
+     * A special tree scanner that would only visit portions of a given tree.
+     * The set of nodes visited by the scanner can be customized at construction-time.
+     */
+    abstract static class FilterScanner extends TreeScanner {
+
+        final Filter<JCTree> treeFilter;
+
+        FilterScanner(final Set<JCTree.Tag> validTags) {
+            this.treeFilter = new Filter<JCTree>() {
+                public boolean accepts(JCTree t) {
+                    return validTags.contains(t.getTag());
+                }
+            };
+        }
+
+        @Override
+        public void scan(JCTree tree) {
+            if (tree != null) {
+                if (treeFilter.accepts(tree)) {
+                    super.scan(tree);
+                } else {
+                    skip(tree);
+                }
+            }
+        }
+
+        /**
+         * handler that is executed when a node has been discarded
+         */
+        abstract void skip(JCTree tree);
+    }
+
+    /**
+     * A tree scanner suitable for visiting the target-type dependent nodes of
+     * a given argument expression.
+     */
+    static class PolyScanner extends FilterScanner {
+
+        PolyScanner() {
+            super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
+        }
+
+        @Override
+        void skip(JCTree tree) {
+            //do nothing
+        }
+    }
+
+    /**
+     * A tree scanner suitable for visiting the target-type dependent nodes nested
+     * within a lambda expression body.
+     */
+    static class LambdaReturnScanner extends FilterScanner {
+
+        LambdaReturnScanner() {
+            super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
+                    FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
+        }
+
+        @Override
+        void skip(JCTree tree) {
+            //do nothing
+        }
     }
 
     /**
@@ -510,83 +608,32 @@
      * inferring types that make some of the nested expressions incompatible
      * with their corresponding instantiated target
      */
-    class StuckChecker extends TreeScanner {
+    class StuckChecker extends PolyScanner {
 
         Type pt;
-        Filter<JCTree> treeFilter;
         Infer.InferenceContext inferenceContext;
         Set<Type> stuckVars = new LinkedHashSet<Type>();
-        Env<AttrContext> env;
 
-        final Filter<JCTree> argsFilter = new Filter<JCTree>() {
-            public boolean accepts(JCTree t) {
-                switch (t.getTag()) {
-                    case CONDEXPR:
-                    case LAMBDA:
-                    case PARENS:
-                    case REFERENCE:
-                        return true;
-                    default:
-                        return false;
-                }
-            }
-        };
-
-        final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
-            public boolean accepts(JCTree t) {
-                switch (t.getTag()) {
-                    case BLOCK: case CASE: case CATCH: case DOLOOP:
-                    case FOREACHLOOP: case FORLOOP: case RETURN:
-                    case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
-                        return true;
-                    default:
-                        return false;
-                }
-            }
-        };
-
-        StuckChecker(ResultInfo resultInfo, Env<AttrContext> env) {
-            this.pt = resultInfo.pt;
-            this.inferenceContext = resultInfo.checkContext.inferenceContext();
-            this.treeFilter = argsFilter;
-            this.env = env;
-        }
-
-        @Override
-        public void scan(JCTree tree) {
-            if (tree != null && treeFilter.accepts(tree)) {
-                super.scan(tree);
-            }
+        StuckChecker(Type pt, Infer.InferenceContext inferenceContext) {
+            this.pt = pt;
+            this.inferenceContext = inferenceContext;
         }
 
         @Override
         public void visitLambda(JCLambda tree) {
-            Type prevPt = pt;
-            Filter<JCTree> prevFilter = treeFilter;
-            try {
-                if (inferenceContext.inferenceVars().contains(pt)) {
-                    stuckVars.add(pt);
-                }
-                if (!types.isFunctionalInterface(pt.tsym)) {
-                    return;
-                }
-                Type descType = types.findDescriptorType(pt);
-                List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
-                if (!TreeInfo.isExplicitLambda(tree) &&
-                        freeArgVars.nonEmpty()) {
-                    stuckVars.addAll(freeArgVars);
-                }
-                pt = descType.getReturnType();
-                if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
-                    scan(tree.getBody());
-                } else {
-                    treeFilter = lambdaBodyFilter;
-                    super.visitLambda(tree);
-                }
-            } finally {
-                pt = prevPt;
-                treeFilter = prevFilter;
+            if (inferenceContext.inferenceVars().contains(pt)) {
+                stuckVars.add(pt);
+            }
+            if (!types.isFunctionalInterface(pt.tsym)) {
+                return;
             }
+            Type descType = types.findDescriptorType(pt);
+            List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
+            if (!TreeInfo.isExplicitLambda(tree) &&
+                    freeArgVars.nonEmpty()) {
+                stuckVars.addAll(freeArgVars);
+            }
+            scanLambdaBody(tree, descType.getReturnType());
         }
 
         @Override
@@ -605,16 +652,19 @@
             stuckVars.addAll(freeArgVars);
         }
 
-        @Override
-        public void visitReturn(JCReturn tree) {
-            Filter<JCTree> prevFilter = treeFilter;
-            try {
-                treeFilter = argsFilter;
-                if (tree.expr != null) {
-                    scan(tree.expr);
-                }
-            } finally {
-                treeFilter = prevFilter;
+        void scanLambdaBody(JCLambda lambda, final Type pt) {
+            if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
+                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext));
+            } else {
+                LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
+                    @Override
+                    public void visitReturn(JCReturn tree) {
+                        if (tree.expr != null) {
+                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext));
+                        }
+                    }
+                };
+                lambdaScanner.scan(lambda.body);
             }
         }
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 05 18:36:11 2017 +0200
@@ -114,7 +114,7 @@
         }
     }
 
-    private final InferenceException inferenceException;
+    final InferenceException inferenceException;
 
 /***************************************************************************
  * Mini/Maximization of UndetVars
@@ -271,15 +271,19 @@
                                   boolean allowBoxing,
                                   boolean useVarargs,
                                   Resolve.MethodResolutionContext resolveContext,
+                                  Resolve.MethodCheck methodCheck,
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
         inferenceException.clear();
 
+        DeferredAttr.DeferredAttrContext deferredAttrContext =
+                resolveContext.deferredAttrContext(msym, inferenceContext);
+
         try {
-            rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
-                    argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
-                    new InferenceCheckHandler(inferenceContext));
+            methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
+
+            deferredAttrContext.complete();
 
             // minimize as yet undetermined type variables
             for (Type t : inferenceContext.undetvars) {
@@ -309,32 +313,6 @@
             inferenceContext.notifyChange(types);
         }
     }
-    //where
-
-        /** inference check handler **/
-        class InferenceCheckHandler implements Resolve.MethodCheckHandler {
-
-            InferenceContext inferenceContext;
-
-            public InferenceCheckHandler(InferenceContext inferenceContext) {
-                this.inferenceContext = inferenceContext;
-            }
-
-            public InapplicableMethodException arityMismatch() {
-                return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
-            }
-            public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
-                String key = varargs ?
-                        "infer.varargs.argument.mismatch" :
-                        "infer.no.conforming.assignment.exists";
-                return inferenceException.setMessage(key,
-                        inferenceContext.inferenceVars(), details);
-            }
-            public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
-                return inferenceException.setMessage("inaccessible.varargs.type",
-                        expected, Kinds.kindName(location), location);
-            }
-        }
 
     /** check that type parameters are within their bounds.
      */
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 18:36:11 2017 +0200
@@ -506,6 +506,7 @@
                         List<Type> typeargtypes,
                         boolean allowBoxing,
                         boolean useVarargs,
+                        MethodCheck methodCheck,
                         Warner warn) throws Infer.InferenceException {
 
         Type mt = types.memberType(site, m);
@@ -558,10 +559,11 @@
                                     allowBoxing,
                                     useVarargs,
                                     currentResolutionContext,
+                                    methodCheck,
                                     warn);
 
-        checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(),
-                                allowBoxing, useVarargs, warn);
+        methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
+                                argtypes, mt.getParameterTypes(), warn);
         return mt;
     }
 
@@ -578,7 +580,7 @@
             currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
             MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                    step.isBoxingRequired(), step.isVarargsRequired(), warn);
+                    step.isBoxingRequired(), step.isVarargsRequired(), resolveMethodCheck, warn);
         }
         finally {
             currentResolutionContext = prevContext;
@@ -595,80 +597,65 @@
                      List<Type> typeargtypes,
                      boolean allowBoxing,
                      boolean useVarargs,
+                     MethodCheck methodCheck,
                      Warner warn) {
         try {
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                                  allowBoxing, useVarargs, warn);
+                                  allowBoxing, useVarargs, methodCheck, warn);
         } catch (InapplicableMethodException ex) {
             return null;
         }
     }
 
-    /** Check if a parameter list accepts a list of args.
+    /**
+     * This interface defines an entry point that should be used to perform a
+     * method check. A method check usually consist in determining as to whether
+     * a set of types (actuals) is compatible with another set of types (formals).
+     * Since the notion of compatibility can vary depending on the circumstances,
+     * this interfaces allows to easily add new pluggable method check routines.
      */
-    boolean argumentsAcceptable(Env<AttrContext> env,
-                                Symbol msym,
+    interface MethodCheck {
+        /**
+         * Main method check routine. A method check usually consist in determining
+         * as to whether a set of types (actuals) is compatible with another set of
+         * types (formals). If an incompatibility is found, an unchecked exception
+         * is assumed to be thrown.
+         */
+        void argumentsAcceptable(Env<AttrContext> env,
+                                DeferredAttrContext deferredAttrContext,
                                 List<Type> argtypes,
                                 List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn) {
-        try {
-            checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn);
-            return true;
-        } catch (InapplicableMethodException ex) {
-            return false;
-        }
-    }
-    /**
-     * A check handler is used by the main method applicability routine in order
-     * to handle specific method applicability failures. It is assumed that a class
-     * implementing this interface should throw exceptions that are a subtype of
-     * InapplicableMethodException (see below). Such exception will terminate the
-     * method applicability check and propagate important info outwards (for the
-     * purpose of generating better diagnostics).
-     */
-    interface MethodCheckHandler {
-        /* The number of actuals and formals differ */
-        InapplicableMethodException arityMismatch();
-        /* An actual argument type does not conform to the corresponding formal type */
-        InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details);
-        /* The element type of a varargs is not accessible in the current context */
-        InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected);
+                                Warner warn);
     }
 
     /**
-     * Basic method check handler used within Resolve - all methods end up
-     * throwing InapplicableMethodException; a diagnostic fragment that describes
-     * the cause as to why the method is not applicable is set on the exception
-     * before it is thrown.
+     * Helper enum defining all method check diagnostics (used by resolveMethodCheck).
      */
-    MethodCheckHandler resolveHandler = new MethodCheckHandler() {
-            public InapplicableMethodException arityMismatch() {
-                return inapplicableMethodException.setMessage("arg.length.mismatch");
-            }
-            public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
-                String key = varargs ?
-                        "varargs.argument.mismatch" :
-                        "no.conforming.assignment.exists";
-                return inapplicableMethodException.setMessage(key,
-                        details);
-            }
-            public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
-                return inapplicableMethodException.setMessage("inaccessible.varargs.type",
-                        expected, Kinds.kindName(location), location);
-            }
-    };
-
-    void checkRawArgumentsAcceptable(Env<AttrContext> env,
-                                Symbol msym,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn) {
-        checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
-                allowBoxing, useVarargs, warn, resolveHandler);
+    enum MethodCheckDiag {
+        /**
+         * Actuals and formals differs in length.
+         */
+        ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"),
+        /**
+         * An actual is incompatible with a formal.
+         */
+        ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"),
+        /**
+         * An actual is incompatible with the varargs element type.
+         */
+        VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"),
+        /**
+         * The varargs element type is inaccessible.
+         */
+        INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type");
+
+        final String basicKey;
+        final String inferKey;
+
+        MethodCheckDiag(String basicKey, String inferKey) {
+            this.basicKey = basicKey;
+            this.inferKey = inferKey;
+        }
     }
 
     /**
@@ -689,68 +676,94 @@
      *
      * A method check handler (see above) is used in order to report errors.
      */
-    void checkRawArgumentsAcceptable(final Env<AttrContext> env,
-                                Symbol msym,
-                                DeferredAttr.AttrMode mode,
-                                final Infer.InferenceContext inferenceContext,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn,
-                                final MethodCheckHandler handler) {
-        Type varargsFormal = useVarargs ? formals.last() : null;
-
-        if (varargsFormal == null &&
-                argtypes.size() != formals.size()) {
-            throw handler.arityMismatch(); // not enough args
-        }
-
-        DeferredAttr.DeferredAttrContext deferredAttrContext =
-                deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext);
-
-        while (argtypes.nonEmpty() && formals.head != varargsFormal) {
-            ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn);
-            mresult.check(null, argtypes.head);
-            argtypes = argtypes.tail;
-            formals = formals.tail;
-        }
-
-        if (formals.head != varargsFormal) {
-            throw handler.arityMismatch(); // not enough args
-        }
-
-        if (useVarargs) {
-            //note: if applicability check is triggered by most specific test,
-            //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
-            final Type elt = types.elemtype(varargsFormal);
-            ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn);
-            while (argtypes.nonEmpty()) {
+    MethodCheck resolveMethodCheck = new MethodCheck() {
+        @Override
+        public void argumentsAcceptable(final Env<AttrContext> env,
+                                    DeferredAttrContext deferredAttrContext,
+                                    List<Type> argtypes,
+                                    List<Type> formals,
+                                    Warner warn) {
+            //should we expand formals?
+            boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
+
+            //inference context used during this method check
+            InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
+
+            Type varargsFormal = useVarargs ? formals.last() : null;
+
+            if (varargsFormal == null &&
+                    argtypes.size() != formals.size()) {
+                report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            while (argtypes.nonEmpty() && formals.head != varargsFormal) {
+                ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn);
                 mresult.check(null, argtypes.head);
                 argtypes = argtypes.tail;
+                formals = formals.tail;
             }
-            //check varargs element type accessibility
-            varargsAccessible(env, elt, handler, inferenceContext);
-        }
-
-        deferredAttrContext.complete();
-    }
-
-    void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
-        if (inferenceContext.free(t)) {
-            inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
-                @Override
-                public void typesInferred(InferenceContext inferenceContext) {
-                    varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
+
+            if (formals.head != varargsFormal) {
+                report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            if (useVarargs) {
+                //note: if applicability check is triggered by most specific test,
+                //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
+                final Type elt = types.elemtype(varargsFormal);
+                ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn);
+                while (argtypes.nonEmpty()) {
+                    mresult.check(null, argtypes.head);
+                    argtypes = argtypes.tail;
                 }
-            });
-        } else {
-            if (!isAccessible(env, t)) {
-                Symbol location = env.enclClass.sym;
-                throw handler.inaccessibleVarargs(location, t);
+                //check varargs element type accessibility
+                varargsAccessible(env, elt, inferenceContext);
             }
         }
-    }
+
+        private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
+            boolean inferDiag = inferenceContext != infer.emptyContext;
+            InapplicableMethodException ex = inferDiag ?
+                    infer.inferenceException : inapplicableMethodException;
+            if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
+                Object[] args2 = new Object[args.length + 1];
+                System.arraycopy(args, 0, args2, 1, args.length);
+                args2[0] = inferenceContext.inferenceVars();
+                args = args2;
+            }
+            throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
+        }
+
+        private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
+            if (inferenceContext.free(t)) {
+                inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
+                    @Override
+                    public void typesInferred(InferenceContext inferenceContext) {
+                        varargsAccessible(env, inferenceContext.asInstType(t, types), inferenceContext);
+                    }
+                });
+            } else {
+                if (!isAccessible(env, t)) {
+                    Symbol location = env.enclClass.sym;
+                    report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
+                }
+            }
+        }
+
+        private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
+                final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+            CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
+                MethodCheckDiag methodDiag = varargsCheck ?
+                                 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
+
+                @Override
+                public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                    report(methodDiag, deferredAttrContext.inferenceContext, details);
+                }
+            };
+            return new MethodResultInfo(to, checkContext);
+        }
+    };
 
     /**
      * Check context to be used during method applicability checks. A method check
@@ -758,23 +771,24 @@
      */
     abstract class MethodCheckContext implements CheckContext {
 
-        MethodCheckHandler handler;
-        boolean useVarargs;
-        Infer.InferenceContext inferenceContext;
+        boolean strict;
         DeferredAttrContext deferredAttrContext;
         Warner rsWarner;
 
-        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            this.handler = handler;
-            this.useVarargs = useVarargs;
-            this.inferenceContext = inferenceContext;
-            this.deferredAttrContext = deferredAttrContext;
-            this.rsWarner = rsWarner;
+        public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+           this.strict = strict;
+           this.deferredAttrContext = deferredAttrContext;
+           this.rsWarner = rsWarner;
+        }
+
+        public boolean compatible(Type found, Type req, Warner warn) {
+            return strict ?
+                    types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req, types), warn) :
+                    types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req, types), warn);
         }
 
         public void report(DiagnosticPosition pos, JCDiagnostic details) {
-            throw handler.argumentMismatch(useVarargs, details);
+            throw inapplicableMethodException.setMessage(details);
         }
 
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
@@ -782,7 +796,7 @@
         }
 
         public InferenceContext inferenceContext() {
-            return inferenceContext;
+            return deferredAttrContext.inferenceContext;
         }
 
         public DeferredAttrContext deferredAttrContext() {
@@ -791,56 +805,13 @@
     }
 
     /**
-     * Subclass of method check context class that implements strict method conversion.
-     * Strict method conversion checks compatibility between types using subtyping tests.
-     */
-    class StrictMethodContext extends MethodCheckContext {
-
-        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        }
-
-        public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
-        }
-    }
-
-    /**
-     * Subclass of method check context class that implements loose method conversion.
-     * Loose method conversion checks compatibility between types using method conversion tests.
+     * ResultInfo class to be used during method applicability checks. Check
+     * for deferred types goes through special path.
      */
-    class LooseMethodContext extends MethodCheckContext {
-
-        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        }
-
-        public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
-        }
-    }
-
-    /**
-     * Create a method check context to be used during method applicability check
-     */
-    ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
-            Infer.InferenceContext inferenceContext, DeferredAttr.DeferredAttrContext deferredAttrContext,
-            MethodCheckHandler methodHandler, Warner rsWarner) {
-        MethodCheckContext checkContext = allowBoxing ?
-                new LooseMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner) :
-                new StrictMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        return new MethodResultInfo(to, checkContext, deferredAttrContext);
-    }
-
     class MethodResultInfo extends ResultInfo {
 
-        DeferredAttr.DeferredAttrContext deferredAttrContext;
-
-        public MethodResultInfo(Type pt, CheckContext checkContext, DeferredAttr.DeferredAttrContext deferredAttrContext) {
+        public MethodResultInfo(Type pt, CheckContext checkContext) {
             attr.super(VAL, pt, checkContext);
-            this.deferredAttrContext = deferredAttrContext;
         }
 
         @Override
@@ -855,12 +826,12 @@
 
         @Override
         protected MethodResultInfo dup(Type newPt) {
-            return new MethodResultInfo(newPt, checkContext, deferredAttrContext);
+            return new MethodResultInfo(newPt, checkContext);
         }
 
         @Override
         protected ResultInfo dup(CheckContext newContext) {
-            return new MethodResultInfo(pt, newContext, deferredAttrContext);
+            return new MethodResultInfo(pt, newContext);
         }
     }
 
@@ -1071,7 +1042,7 @@
         Assert.check(sym.kind < AMBIGUOUS);
         try {
             Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
-                               allowBoxing, useVarargs, types.noWarnings);
+                               allowBoxing, useVarargs, resolveMethodCheck, types.noWarnings);
             if (!operator)
                 currentResolutionContext.addApplicableCandidate(sym, mt);
         } catch (InapplicableMethodException ex) {
@@ -1151,52 +1122,20 @@
                 if (m1Abstract && !m2Abstract) return m2;
                 if (m2Abstract && !m1Abstract) return m1;
                 // both abstract or both concrete
-                if (!m1Abstract && !m2Abstract)
-                    return ambiguityError(m1, m2);
-                // check that both signatures have the same erasure
-                if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
-                                       m2.erasure(types).getParameterTypes()))
-                    return ambiguityError(m1, m2);
-                // both abstract, neither overridden; merge throws clause and result type
-                Type mst = mostSpecificReturnType(mt1, mt2);
-                if (mst == null) {
-                    // Theoretically, this can't happen, but it is possible
-                    // due to error recovery or mixing incompatible class files
-                    return ambiguityError(m1, m2);
-                }
-                Symbol mostSpecific = mst == mt1 ? m1 : m2;
-                List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
-                Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
-                MethodSymbol result = new MethodSymbol(
-                        mostSpecific.flags(),
-                        mostSpecific.name,
-                        newSig,
-                        mostSpecific.owner) {
-                    @Override
-                    public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
-                        if (origin == site.tsym)
-                            return this;
-                        else
-                            return super.implementation(origin, types, checkResult);
-                        }
-                    };
-                return result;
+                return ambiguityError(m1, m2);
             }
             if (m1SignatureMoreSpecific) return m1;
             if (m2SignatureMoreSpecific) return m2;
             return ambiguityError(m1, m2);
         case AMBIGUOUS:
+            //check if m1 is more specific than all ambiguous methods in m2
             AmbiguityError e = (AmbiguityError)m2;
-            Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
-            Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
-            if (err1 == err2) return err1;
-            if (err1 == e.sym && err2 == e.sym2) return m2;
-            if (err1 instanceof AmbiguityError &&
-                err2 instanceof AmbiguityError &&
-                ((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
-                return ambiguityError(m1, m2);
-            else
-                return ambiguityError(err1, err2);
+            for (Symbol s : e.ambiguousSyms) {
+                if (mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs) != m1) {
+                    return e.addAmbiguousSymbol(m1);
+                }
+            }
+            return m1;
         default:
             throw new AssertionError();
         }
@@ -1274,12 +1213,19 @@
     }
     //where
     private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
-        noteWarner.clear();
-        Type mst = instantiate(env, site, m2, null,
-                types.lowerBounds(argtypes1), null,
-                allowBoxing, false, noteWarner);
-        return mst != null &&
-                !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
+        MethodResolutionContext prevContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            currentResolutionContext.step = allowBoxing ? BOX : BASIC;
+            noteWarner.clear();
+            Type mst = instantiate(env, site, m2, null,
+                    types.lowerBounds(argtypes1), null,
+                    allowBoxing, false, resolveMethodCheck, noteWarner);
+            return mst != null &&
+                    !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
+        } finally {
+            currentResolutionContext = prevContext;
+        }
     }
     //where
     private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
@@ -2366,9 +2312,11 @@
         try {
             currentResolutionContext = new MethodResolutionContext();
             Name name = treeinfo.operatorName(optag);
+            env.info.pendingResolutionPhase = currentResolutionContext.step = BASIC;
             Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                     null, false, false, true);
             if (boxingEnabled && sym.kind >= WRONG_MTHS)
+                env.info.pendingResolutionPhase = currentResolutionContext.step = BOX;
                 sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                  null, true, false, true);
             return accessMethod(sym, pos, env.enclClass.sym.type, name,
@@ -2524,6 +2472,10 @@
 
         @Override
         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                AmbiguityError a_err = (AmbiguityError)sym;
+                sym = a_err.mergeAbstracts(site);
+            }
             if (sym.kind >= AMBIGUOUS) {
                 //if nothing is found return the 'first' error
                 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
@@ -2579,6 +2531,10 @@
         abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
 
         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                AmbiguityError a_err = (AmbiguityError)sym;
+                sym = a_err.mergeAbstracts(site);
+            }
             //skip error reporting
             return sym;
         }
@@ -3014,9 +2970,7 @@
 
         @Override
         public Symbol access(Name name, TypeSymbol location) {
-            if (sym.kind >= AMBIGUOUS)
-                return ((ResolveError)sym).access(name, location);
-            else if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
+            if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
                 return types.createErrorType(name, location, sym.type).tsym;
             else
                 return sym;
@@ -3338,14 +3292,32 @@
      * (either methods, constructors or operands) are ambiguous
      * given an actual arguments/type argument list.
      */
-    class AmbiguityError extends InvalidSymbolError {
+    class AmbiguityError extends ResolveError {
 
         /** The other maximally specific symbol */
-        Symbol sym2;
+        List<Symbol> ambiguousSyms = List.nil();
+
+        @Override
+        public boolean exists() {
+            return true;
+        }
 
         AmbiguityError(Symbol sym1, Symbol sym2) {
-            super(AMBIGUOUS, sym1, "ambiguity error");
-            this.sym2 = sym2;
+            super(AMBIGUOUS, "ambiguity error");
+            ambiguousSyms = flatten(sym2).appendList(flatten(sym1));
+        }
+
+        private List<Symbol> flatten(Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                return ((AmbiguityError)sym).ambiguousSyms;
+            } else {
+                return List.of(sym);
+            }
+        }
+
+        AmbiguityError addAmbiguousSymbol(Symbol s) {
+            ambiguousSyms = ambiguousSyms.prepend(s);
+            return this;
         }
 
         @Override
@@ -3356,24 +3328,60 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes) {
-            AmbiguityError pair = this;
-            while (true) {
-                if (pair.sym.kind == AMBIGUOUS)
-                    pair = (AmbiguityError)pair.sym;
-                else if (pair.sym2.kind == AMBIGUOUS)
-                    pair = (AmbiguityError)pair.sym2;
-                else break;
-            }
-            Name sname = pair.sym.name;
-            if (sname == names.init) sname = pair.sym.owner.name;
+            List<Symbol> diagSyms = ambiguousSyms.reverse();
+            Symbol s1 = diagSyms.head;
+            Symbol s2 = diagSyms.tail.head;
+            Name sname = s1.name;
+            if (sname == names.init) sname = s1.owner.name;
             return diags.create(dkind, log.currentSource(),
                       pos, "ref.ambiguous", sname,
-                      kindName(pair.sym),
-                      pair.sym,
-                      pair.sym.location(site, types),
-                      kindName(pair.sym2),
-                      pair.sym2,
-                      pair.sym2.location(site, types));
+                      kindName(s1),
+                      s1,
+                      s1.location(site, types),
+                      kindName(s2),
+                      s2,
+                      s2.location(site, types));
+        }
+
+        /**
+         * If multiple applicable methods are found during overload and none of them
+         * is more specific than the others, attempt to merge their signatures.
+         */
+        Symbol mergeAbstracts(Type site) {
+            Symbol fst = ambiguousSyms.last();
+            Symbol res = fst;
+            for (Symbol s : ambiguousSyms.reverse()) {
+                Type mt1 = types.memberType(site, res);
+                Type mt2 = types.memberType(site, s);
+                if ((s.flags() & ABSTRACT) == 0 ||
+                        !types.overrideEquivalent(mt1, mt2) ||
+                        !types.isSameTypes(fst.erasure(types).getParameterTypes(),
+                                       s.erasure(types).getParameterTypes())) {
+                    //ambiguity cannot be resolved
+                    return this;
+                } else {
+                    Type mst = mostSpecificReturnType(mt1, mt2);
+                    if (mst == null) {
+                        // Theoretically, this can't happen, but it is possible
+                        // due to error recovery or mixing incompatible class files
+                        return this;
+                    }
+                    Symbol mostSpecific = mst == mt1 ? res : s;
+                    List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
+                    Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
+                    res = new MethodSymbol(
+                            mostSpecific.flags(),
+                            mostSpecific.name,
+                            newSig,
+                            mostSpecific.owner);
+                }
+            }
+            return res;
+        }
+
+        @Override
+        protected Symbol access(Name name, TypeSymbol location) {
+            return ambiguousSyms.last();
         }
     }
 
@@ -3450,6 +3458,10 @@
             candidates = candidates.append(c);
         }
 
+        DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
+            return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
+        }
+
         /**
          * This class represents an overload resolution candidate. There are two
          * kinds of candidates: applicable methods and inapplicable methods;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Jul 05 18:36:11 2017 +0200
@@ -217,6 +217,13 @@
      */
     boolean haveParameterNameIndices;
 
+    /** Set this to false every time we start reading a method
+     * and are saving parameter names.  Set it to true when we see
+     * MethodParameters, if it's set when we see a LocalVariableTable,
+     * then we ignore the parameter names from the LVT.
+     */
+    boolean sawMethodParameters;
+
     /**
      * The set of attribute names for which warnings have been generated for the current class
      */
@@ -984,7 +991,7 @@
             new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     int newbp = bp + attrLen;
-                    if (saveParameterNames) {
+                    if (saveParameterNames && !sawMethodParameters) {
                         // Pick up parameter names from the variable table.
                         // Parameter names are not explicitly identified as such,
                         // but all parameter name entries in the LocalVariableTable
@@ -1017,6 +1024,25 @@
                 }
             },
 
+            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
+                protected void read(Symbol sym, int attrlen) {
+                    int newbp = bp + attrlen;
+                    if (saveParameterNames) {
+                        sawMethodParameters = true;
+                        int numEntries = nextByte();
+                        parameterNameIndices = new int[numEntries];
+                        haveParameterNameIndices = true;
+                        for (int i = 0; i < numEntries; i++) {
+                            int nameIndex = nextChar();
+                            int flags = nextInt();
+                            parameterNameIndices[i] = nameIndex;
+                        }
+                    }
+                    bp = newbp;
+                }
+            },
+
+
             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
@@ -1826,6 +1852,7 @@
         } else
             Arrays.fill(parameterNameIndices, 0);
         haveParameterNameIndices = false;
+        sawMethodParameters = false;
     }
 
     /**
@@ -1845,12 +1872,16 @@
         // if no names were found in the class file, there's nothing more to do
         if (!haveParameterNameIndices)
             return;
-
-        int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
-        // the code in readMethod may have skipped the first parameter when
-        // setting up the MethodType. If so, we make a corresponding allowance
-        // here for the position of the first parameter.  Note that this
-        // assumes the skipped parameter has a width of 1 -- i.e. it is not
+        // If we get parameter names from MethodParameters, then we
+        // don't need to skip.
+        int firstParam = 0;
+        if (!sawMethodParameters) {
+            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
+            // the code in readMethod may have skipped the first
+            // parameter when setting up the MethodType. If so, we
+            // make a corresponding allowance here for the position of
+            // the first parameter.  Note that this assumes the
+            // skipped parameter has a width of 1 -- i.e. it is not
         // a double width type (long or double.)
         if (sym.name == names.init && currentOwner.hasOuterInstance()) {
             // Sometimes anonymous classes don't have an outer
@@ -1861,17 +1892,20 @@
         }
 
         if (sym.type != jvmType) {
-            // reading the method attributes has caused the symbol's type to
-            // be changed. (i.e. the Signature attribute.)  This may happen if
-            // there are hidden (synthetic) parameters in the descriptor, but
-            // not in the Signature.  The position of these hidden parameters
-            // is unspecified; for now, assume they are at the beginning, and
-            // so skip over them. The primary case for this is two hidden
-            // parameters passed into Enum constructors.
+                // reading the method attributes has caused the
+                // symbol's type to be changed. (i.e. the Signature
+                // attribute.)  This may happen if there are hidden
+                // (synthetic) parameters in the descriptor, but not
+                // in the Signature.  The position of these hidden
+                // parameters is unspecified; for now, assume they are
+                // at the beginning, and so skip over them. The
+                // primary case for this is two hidden parameters
+                // passed into Enum constructors.
             int skip = Code.width(jvmType.getParameterTypes())
                     - Code.width(sym.type.getParameterTypes());
             firstParam += skip;
         }
+        }
         List<Name> paramNames = List.nil();
         int index = firstParam;
         for (Type t: sym.type.getParameterTypes()) {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -725,6 +725,28 @@
         return acount;
     }
 
+    /**
+     * Write method parameter names attribute.
+     */
+    int writeMethodParametersAttr(MethodSymbol m) {
+        if (m.params != null && 0 != m.params.length()) {
+            int attrIndex = writeAttr(names.MethodParameters);
+            databuf.appendByte(m.params.length());
+            for (VarSymbol s : m.params) {
+                // TODO: expand to cover synthesized, once we figure out
+                // how to represent that.
+                final int flags = (int) s.flags() & (FINAL | SYNTHETIC);
+                // output parameter info
+                databuf.appendChar(pool.put(s.name));
+                databuf.appendInt(flags);
+            }
+            endAttr(attrIndex);
+            return 1;
+        } else
+            return 0;
+    }
+
+
     /** Write method parameter annotations;
      *  return number of attributes written.
      */
@@ -1034,6 +1056,8 @@
             endAttr(alenIdx);
             acount++;
         }
+        if (options.isSet(PARAMETERS))
+            acount += writeMethodParametersAttr(m);
         acount += writeMemberAttrs(m);
         acount += writeParameterAttrs(m);
         endAttrs(acountIdx, acount);
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java	Wed Jul 05 18:36:11 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
@@ -176,6 +176,8 @@
 
     PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
 
+    PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
+
     D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
 
     S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
@@ -309,7 +311,7 @@
 
     // This option exists only for the purpose of documenting itself.
     // It's actually implemented by the launcher.
-    J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO) {
+    J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) {
         @Override
         public boolean process(OptionHelper helper, String option) {
             throw new AssertionError
@@ -414,7 +416,7 @@
 
     // This option exists only for the purpose of documenting itself.
     // It's actually implemented by the CommandLine class.
-    AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO) {
+    AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) {
         @Override
         public boolean process(OptionHelper helper, String option) {
             throw new AssertionError("the @ flag should be caught by CommandLine.");
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties	Wed Jul 05 18:36:11 2017 +0200
@@ -55,6 +55,8 @@
     Specify where to find annotation processors
 javac.opt.processor=\
     Names of the annotation processors to run; bypasses default discovery process
+javac.opt.parameters=\
+    Generate metadata for reflection on method parameters
 javac.opt.proc.none.only=\
     Control whether annotation processing and/or compilation is done.
 javac.opt.d=\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Wed Jul 05 18:36:11 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
@@ -154,12 +154,13 @@
         }
         //we need to (i) replace all line terminators with a space and (ii) remove
         //occurrences of 'missing' in the Pretty output (generated when types are missing)
-        String res = s.toString().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
+        String res = s.toString().trim().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
         if (res.length() < maxLength) {
             return res;
         } else {
-            int split = (maxLength - trimSequence.length()) * 2 / 3;
-            return res.substring(0, split) + trimSequence + res.substring(split);
+            int head = (maxLength - trimSequence.length()) * 2 / 3;
+            int tail = maxLength - trimSequence.length() - head;
+            return res.substring(0, head) + trimSequence + res.substring(res.length() - tail);
         }
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Wed Jul 05 18:36:11 2017 +0200
@@ -132,6 +132,7 @@
     public final Name LineNumberTable;
     public final Name LocalVariableTable;
     public final Name LocalVariableTypeTable;
+    public final Name MethodParameters;
     public final Name RuntimeInvisibleAnnotations;
     public final Name RuntimeInvisibleParameterAnnotations;
     public final Name RuntimeInvisibleTypeAnnotations;
@@ -265,6 +266,7 @@
         LineNumberTable = fromString("LineNumberTable");
         LocalVariableTable = fromString("LocalVariableTable");
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
+        MethodParameters = fromString("MethodParameters");
         RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
         RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
         RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
--- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java	Wed Jul 05 18:36:11 2017 +0200
@@ -89,6 +89,15 @@
     }
 
     /**
+     * Check for the synthesized bit on the annotation.
+     *
+     * @return true if the annotation is synthesized.
+     */
+    public boolean isSynthesized() {
+        return annotation.isSynthesized();
+    }
+
+    /**
      * Returns a string representation of this annotation.
      * String is of one of the forms:
      *     @com.example.foo(name1=val1, name2=val2)
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java	Wed Jul 05 18:36:11 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
@@ -133,16 +133,6 @@
         this.programName = programName;
     }
 
-    @Override
-    protected int getDefaultMaxErrors() {
-        return Integer.MAX_VALUE;
-    }
-
-    @Override
-    protected int getDefaultMaxWarnings() {
-        return Integer.MAX_VALUE;
-    }
-
     public void setLocale(Locale locale) {
         this.locale = locale;
     }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java	Wed Jul 05 18:36:11 2017 +0200
@@ -86,16 +86,7 @@
      * Return true if this method is abstract
      */
     public boolean isAbstract() {
-        //### This is dubious, but old 'javadoc' apparently does it.
-        //### I regard this as a bug and an obstacle to treating the
-        //### doclet API as a proper compile-time reflection facility.
-        //### (maddox 09/26/2000)
-        if (containingClass().isInterface()) {
-            //### Don't force creation of ClassDocImpl for super here.
-            // Abstract modifier is implicit.  Strip/canonicalize it.
-            return false;
-        }
-        return Modifier.isAbstract(getModifiers());
+        return (Modifier.isAbstract(getModifiers()) && !isDefault());
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -46,6 +46,7 @@
 import com.sun.tools.classfile.LineNumberTable_attribute;
 import com.sun.tools.classfile.LocalVariableTable_attribute;
 import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
+import com.sun.tools.classfile.MethodParameters_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
@@ -386,6 +387,28 @@
         return null;
     }
 
+    private static final String format = "%-31s%s";
+
+    public Void visitMethodParameters(MethodParameters_attribute attr,
+                                      Void ignore) {
+
+        final String header = String.format(format, "Name", "Flags");
+        println("MethodParameters:");
+        indent(+1);
+        println(header);
+        for (MethodParameters_attribute.Entry entry :
+                 attr.method_parameter_table) {
+            String flagstr =
+                (0 != (entry.flags & ACC_FINAL) ? " final" : "") +
+                (0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : "");
+            println(String.format(format,
+                                  constantWriter.stringValue(entry.name_index),
+                                  flagstr));
+        }
+        indent(-1);
+        return null;
+    }
+
     public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleAnnotations:");
         indent(+1);
--- a/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, 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
@@ -206,7 +206,7 @@
             println("minor version: " + cf.minor_version);
             println("major version: " + cf.major_version);
             if (!options.compat)
-              writeList("flags: ", flags.getClassFlags(), NEWLINE);
+              writeList("flags: ", flags.getClassFlags(), "\n");
             indent(-1);
             constantWriter.writeConstantPool();
         } else {
@@ -383,7 +383,7 @@
             println("Signature: " + getValue(f.descriptor));
 
         if (options.verbose && !options.compat)
-            writeList("flags: ", flags.getFieldFlags(), NEWLINE);
+            writeList("flags: ", flags.getFieldFlags(), "\n");
 
         if (options.showAllAttrs) {
             for (Attribute attr: f.attributes)
@@ -480,7 +480,7 @@
         }
 
         if (options.verbose && !options.compat) {
-            writeList("flags: ", flags.getMethodFlags(), NEWLINE);
+            writeList("flags: ", flags.getMethodFlags(), "\n");
         }
 
         Code_attribute code = null;
@@ -749,5 +749,4 @@
     private int size;
     private ConstantPool constant_pool;
     private Method method;
-    private static final String NEWLINE = System.getProperty("line.separator", "\n");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * 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 com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
+import java.io.File;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * Represents the source of the class files.
+ */
+public class Archive {
+    private static Map<String,Archive> archiveForClass = new HashMap<String,Archive>();
+    public static Archive find(Location loc) {
+        return archiveForClass.get(loc.getName());
+    }
+
+    private final File file;
+    private final String filename;
+    private final DependencyRecorder recorder;
+    private final ClassFileReader reader;
+    public Archive(String name) {
+        this.file = null;
+        this.filename = name;
+        this.recorder = new DependencyRecorder();
+        this.reader = null;
+    }
+
+    public Archive(File f, ClassFileReader reader) {
+        this.file = f;
+        this.filename = f.getName();
+        this.recorder = new DependencyRecorder();
+        this.reader = reader;
+    }
+
+    public ClassFileReader reader() {
+        return reader;
+    }
+
+    public String getFileName() {
+        return filename;
+    }
+
+    public void addClass(String classFileName) {
+        Archive a = archiveForClass.get(classFileName);
+        assert(a == null || a == this); // ## issue warning?
+        if (!archiveForClass.containsKey(classFileName)) {
+            archiveForClass.put(classFileName, this);
+        }
+    }
+
+    public void addDependency(Dependency d) {
+        recorder.addDependency(d);
+    }
+
+    /**
+     * Returns a sorted map of a class to its dependencies.
+     */
+    public SortedMap<Location, SortedSet<Location>> getDependencies() {
+        DependencyRecorder.Filter filter = new DependencyRecorder.Filter() {
+            public boolean accept(Location origin, Location target) {
+                 return (archiveForClass.get(origin.getName()) !=
+                            archiveForClass.get(target.getName()));
+        }};
+
+        SortedMap<Location, SortedSet<Location>> result =
+            new TreeMap<Location, SortedSet<Location>>(locationComparator);
+        for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) {
+            Location o = e.getKey();
+            for (Location t : e.getValue()) {
+                if (filter.accept(o, t)) {
+                    SortedSet<Location> odeps = result.get(o);
+                    if (odeps == null) {
+                        odeps = new TreeSet<Location>(locationComparator);
+                        result.put(o, odeps);
+                    }
+                    odeps.add(t);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns the set of archives this archive requires.
+     */
+    public Set<Archive> getRequiredArchives() {
+        SortedSet<Archive> deps = new TreeSet<Archive>(new Comparator<Archive>() {
+            public int compare(Archive a1, Archive a2) {
+                return a1.toString().compareTo(a2.toString());
+            }
+        });
+
+        for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) {
+            Location o = e.getKey();
+            Archive origin = Archive.find(o);
+            for (Location t : e.getValue()) {
+                Archive target = Archive.find(t);
+                assert(origin != null && target != null);
+                if (origin != target) {
+                    if (!deps.contains(target)) {
+                        deps.add(target);
+                    }
+                }
+            }
+        }
+        return deps;
+    }
+
+    public String toString() {
+        return file != null ? file.getPath() : filename;
+    }
+
+    private static class DependencyRecorder {
+        static interface Filter {
+            boolean accept(Location origin, Location target);
+        }
+
+        public void addDependency(Dependency d) {
+            Set<Location> odeps = map.get(d.getOrigin());
+            if (odeps == null) {
+                odeps = new HashSet<Location>();
+                map.put(d.getOrigin(), odeps);
+            }
+            odeps.add(d.getTarget());
+        }
+
+        public Map<Location, Set<Location>> dependencies() {
+            return map;
+        }
+
+        private final Map<Location, Set<Location>> map =
+            new HashMap<Location, Set<Location>>();
+    }
+
+    private static Comparator<Location> locationComparator =
+        new Comparator<Location>() {
+            public int compare(Location o1, Location o2) {
+                return o1.toString().compareTo(o2.toString());
+            }
+        };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,326 @@
+/*
+ * 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 com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Dependencies.ClassFileError;
+import java.io.*;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * ClassFileReader reads ClassFile(s) of a given path that can be
+ * a .class file, a directory, or a JAR file.
+ */
+public class ClassFileReader {
+    /**
+     * Returns a ClassFileReader instance of a given path.
+     */
+    public static ClassFileReader newInstance(File path) throws IOException {
+        if (!path.exists()) {
+            throw new FileNotFoundException(path.getAbsolutePath());
+        }
+
+        if (path.isDirectory()) {
+            return new DirectoryReader(path.toPath());
+        } else if (path.getName().endsWith(".jar")) {
+            return new JarFileReader(path.toPath());
+        } else {
+            return new ClassFileReader(path.toPath());
+        }
+    }
+
+    protected final Path path;
+    protected final String baseFileName;
+    private ClassFileReader(Path path) {
+        this.path = path;
+        this.baseFileName = path.getFileName() != null
+                                ? path.getFileName().toString()
+                                : path.toString();
+    }
+
+    public String getFileName() {
+        return baseFileName;
+    }
+
+    /**
+     * Returns the ClassFile matching the given binary name
+     * or a fully-qualified class name.
+     */
+    public ClassFile getClassFile(String name) throws IOException {
+        if (name.indexOf('.') > 0) {
+            int i = name.lastIndexOf('.');
+            String pathname = name.replace('.', File.separatorChar) + ".class";
+            if (baseFileName.equals(pathname) ||
+                    baseFileName.equals(pathname.substring(0, i) + "$" +
+                                        pathname.substring(i+1, pathname.length()))) {
+                return readClassFile(path);
+            }
+        } else {
+            if (baseFileName.equals(name.replace('/', File.separatorChar) + ".class")) {
+                return readClassFile(path);
+            }
+        }
+        return null;
+    }
+
+    public Iterable<ClassFile> getClassFiles() throws IOException {
+        return new Iterable<ClassFile>() {
+            public Iterator<ClassFile> iterator() {
+                return new FileIterator();
+            }
+        };
+    }
+
+    protected ClassFile readClassFile(Path p) throws IOException {
+        InputStream is = null;
+        try {
+            is = Files.newInputStream(p);
+            return ClassFile.read(is);
+        } catch (ConstantPoolException e) {
+            throw new ClassFileError(e);
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    class FileIterator implements Iterator<ClassFile> {
+        int count;
+        FileIterator() {
+            this.count = 0;
+        }
+        public boolean hasNext() {
+            return count == 0 && baseFileName.endsWith(".class");
+        }
+
+        public ClassFile next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            try {
+                ClassFile cf = readClassFile(path);
+                count++;
+                return cf;
+            } catch (IOException e) {
+                throw new ClassFileError(e);
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+
+    public String toString() {
+        return path.toString();
+    }
+
+    private static class DirectoryReader extends ClassFileReader {
+        DirectoryReader(Path path) throws IOException {
+            super(path);
+        }
+
+        public ClassFile getClassFile(String name) throws IOException {
+            if (name.indexOf('.') > 0) {
+                int i = name.lastIndexOf('.');
+                String pathname = name.replace('.', File.separatorChar) + ".class";
+                Path p = path.resolve(pathname);
+                if (!p.toFile().exists()) {
+                    p = path.resolve(pathname.substring(0, i) + "$" +
+                                     pathname.substring(i+1, pathname.length()));
+                }
+                if (p.toFile().exists()) {
+                    return readClassFile(p);
+                }
+            } else {
+                Path p = path.resolve(name + ".class");
+                if (p.toFile().exists()) {
+                    return readClassFile(p);
+                }
+            }
+            return null;
+        }
+
+        public Iterable<ClassFile> getClassFiles() throws IOException {
+            final Iterator<ClassFile> iter = new DirectoryIterator();
+            return new Iterable<ClassFile>() {
+                public Iterator<ClassFile> iterator() {
+                    return iter;
+                }
+            };
+        }
+
+        private List<Path> walkTree(Path dir) throws IOException {
+            final List<Path> files = new ArrayList<Path>();
+            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                        throws IOException {
+                    if (file.toFile().getName().endsWith(".class")) {
+                        files.add(file);
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+            return files;
+        }
+
+        class DirectoryIterator implements Iterator<ClassFile> {
+            private List<Path> entries;
+            private int index = 0;
+            DirectoryIterator() throws IOException {
+                entries = walkTree(path);
+                index = 0;
+            }
+
+            public boolean hasNext() {
+                return index != entries.size();
+            }
+
+            public ClassFile next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+                Path path = entries.get(index++);
+                try {
+                    return readClassFile(path);
+                } catch (IOException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        }
+    }
+
+    private static class JarFileReader extends ClassFileReader {
+        final JarFile jarfile;
+        JarFileReader(Path path) throws IOException {
+            super(path);
+            this.jarfile = new JarFile(path.toFile());
+        }
+
+        public ClassFile getClassFile(String name) throws IOException {
+            if (name.indexOf('.') > 0) {
+                int i = name.lastIndexOf('.');
+                String entryName = name.replace('.', '/') + ".class";
+                JarEntry e = jarfile.getJarEntry(entryName);
+                if (e == null) {
+                    e = jarfile.getJarEntry(entryName.substring(0, i) + "$"
+                            + entryName.substring(i + 1, entryName.length()));
+                }
+                if (e != null) {
+                    return readClassFile(e);
+                }
+            } else {
+                JarEntry e = jarfile.getJarEntry(name + ".class");
+                if (e != null) {
+                    return readClassFile(e);
+                }
+            }
+            return null;
+        }
+
+        private ClassFile readClassFile(JarEntry e) throws IOException {
+            InputStream is = null;
+            try {
+                is = jarfile.getInputStream(e);
+                return ClassFile.read(is);
+            } catch (ConstantPoolException ex) {
+                throw new ClassFileError(ex);
+            } finally {
+                if (is != null)
+                    is.close();
+            }
+        }
+
+        public Iterable<ClassFile> getClassFiles() throws IOException {
+            final Iterator<ClassFile> iter = new JarFileIterator();
+            return new Iterable<ClassFile>() {
+                public Iterator<ClassFile> iterator() {
+                    return iter;
+                }
+            };
+        }
+
+        class JarFileIterator implements Iterator<ClassFile> {
+            private Enumeration<JarEntry> entries;
+            private JarEntry nextEntry;
+            JarFileIterator() {
+                this.entries = jarfile.entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry e = entries.nextElement();
+                    String name = e.getName();
+                    if (name.endsWith(".class")) {
+                        this.nextEntry = e;
+                        break;
+                    }
+                }
+            }
+
+            public boolean hasNext() {
+                return nextEntry != null;
+            }
+
+            public ClassFile next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+
+                ClassFile cf;
+                try {
+                    cf = readClassFile(nextEntry);
+                } catch (IOException ex) {
+                    throw new ClassFileError(ex);
+                }
+                JarEntry entry = nextEntry;
+                nextEntry = null;
+                while (entries.hasMoreElements()) {
+                    JarEntry e = entries.nextElement();
+                    String name = e.getName();
+                    if (name.endsWith(".class")) {
+                        nextEntry = e;
+                        break;
+                    }
+                }
+                return cf;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,650 @@
+/*
+ * 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 com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Dependencies;
+import com.sun.tools.classfile.Dependencies.ClassFileError;
+import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
+import java.io.*;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation for the jdeps tool for static class dependency analysis.
+ */
+class JdepsTask {
+    class BadArgs extends Exception {
+        static final long serialVersionUID = 8765093759964640721L;
+        BadArgs(String key, Object... args) {
+            super(JdepsTask.this.getMessage(key, args));
+            this.key = key;
+            this.args = args;
+        }
+
+        BadArgs showUsage(boolean b) {
+            showUsage = b;
+            return this;
+        }
+        final String key;
+        final Object[] args;
+        boolean showUsage;
+    }
+
+    static abstract class Option {
+        Option(boolean hasArg, String... aliases) {
+            this.hasArg = hasArg;
+            this.aliases = aliases;
+        }
+
+        boolean isHidden() {
+            return false;
+        }
+
+        boolean matches(String opt) {
+            for (String a : aliases) {
+                if (a.equals(opt)) {
+                    return true;
+                } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        boolean ignoreRest() {
+            return false;
+        }
+
+        abstract void process(JdepsTask task, String opt, String arg) throws BadArgs;
+        final boolean hasArg;
+        final String[] aliases;
+    }
+
+    static abstract class HiddenOption extends Option {
+        HiddenOption(boolean hasArg, String... aliases) {
+            super(hasArg, aliases);
+        }
+
+        boolean isHidden() {
+            return true;
+        }
+    }
+
+    static Option[] recognizedOptions = {
+        new Option(false, "-h", "-?", "--help") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.help = true;
+            }
+        },
+        new Option(false, "-s", "--summary") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.showSummary = true;
+                task.options.verbose = Options.Verbose.SUMMARY;
+            }
+        },
+        new Option(false, "-v", "--verbose") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.verbose = Options.Verbose.VERBOSE;
+            }
+        },
+        new Option(true, "-V", "--verbose-level") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                switch (arg) {
+                    case "package":
+                        task.options.verbose = Options.Verbose.PACKAGE;
+                        break;
+                    case "class":
+                        task.options.verbose = Options.Verbose.CLASS;
+                        break;
+                    default:
+                        throw task.new BadArgs("err.invalid.arg.for.option", opt);
+                }
+            }
+        },
+        new Option(true, "-c", "--classpath") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.classpath = arg;
+            }
+        },
+        new Option(true, "-p", "--package") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.packageNames.add(arg);
+            }
+        },
+        new Option(true, "-e", "--regex") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.regex = arg;
+            }
+        },
+        new Option(false, "-P", "--profile") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.showProfile = true;
+            }
+        },
+        new Option(false, "-R", "--recursive") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.depth = 0;
+            }
+        },
+        new HiddenOption(true, "-d", "--depth") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                try {
+                    task.options.depth = Integer.parseInt(arg);
+                } catch (NumberFormatException e) {
+                    throw task.new BadArgs("err.invalid.arg.for.option", opt);
+                }
+            }
+        },
+        new Option(false, "--version") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.version = true;
+            }
+        },
+        new HiddenOption(false, "--fullversion") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.fullVersion = true;
+            }
+        },
+
+    };
+
+    private static final String PROGNAME = "jdeps";
+    private final Options options = new Options();
+    private final List<String> classes = new ArrayList<String>();
+
+    private PrintWriter log;
+    void setLog(PrintWriter out) {
+        log = out;
+    }
+
+    /**
+     * Result codes.
+     */
+    static final int EXIT_OK = 0, // Completed with no errors.
+                     EXIT_ERROR = 1, // Completed but reported errors.
+                     EXIT_CMDERR = 2, // Bad command-line arguments
+                     EXIT_SYSERR = 3, // System error or resource exhaustion.
+                     EXIT_ABNORMAL = 4;// terminated abnormally
+
+    int run(String[] args) {
+        if (log == null) {
+            log = new PrintWriter(System.out);
+        }
+        try {
+            handleOptions(args);
+            if (options.help) {
+                showHelp();
+            }
+            if (options.version || options.fullVersion) {
+                showVersion(options.fullVersion);
+            }
+            if (classes.isEmpty() && !options.wildcard) {
+                if (options.help || options.version || options.fullVersion) {
+                    return EXIT_OK;
+                } else {
+                    showHelp();
+                    return EXIT_CMDERR;
+                }
+            }
+            if (options.regex != null && options.packageNames.size() > 0) {
+                showHelp();
+                return EXIT_CMDERR;
+            }
+            if (options.showSummary && options.verbose != Options.Verbose.SUMMARY) {
+                showHelp();
+                return EXIT_CMDERR;
+            }
+            boolean ok = run();
+            return ok ? EXIT_OK : EXIT_ERROR;
+        } catch (BadArgs e) {
+            reportError(e.key, e.args);
+            if (e.showUsage) {
+                log.println(getMessage("main.usage.summary", PROGNAME));
+            }
+            return EXIT_CMDERR;
+        } catch (IOException e) {
+            return EXIT_ABNORMAL;
+        } finally {
+            log.flush();
+        }
+    }
+
+    private final List<Archive> sourceLocations = new ArrayList<Archive>();
+    private final Archive NOT_FOUND = new Archive(getMessage("artifact.not.found"));
+    private boolean run() throws IOException {
+        findDependencies();
+        switch (options.verbose) {
+            case VERBOSE:
+            case CLASS:
+                printClassDeps(log);
+                break;
+            case PACKAGE:
+                printPackageDeps(log);
+                break;
+            case SUMMARY:
+                for (Archive origin : sourceLocations) {
+                    for (Archive target : origin.getRequiredArchives()) {
+                        log.format("%-30s -> %s%n", origin, target);
+                    }
+                }
+                break;
+            default:
+                throw new InternalError("Should not reach here");
+        }
+        return true;
+    }
+
+    private boolean isValidClassName(String name) {
+        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+            return false;
+        }
+        for (int i=1; i < name.length(); i++) {
+            char c = name.charAt(i);
+            if (c != '.'  && !Character.isJavaIdentifierPart(c)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void findDependencies() throws IOException {
+        Dependency.Finder finder = Dependencies.getClassDependencyFinder();
+        Dependency.Filter filter;
+        if (options.regex != null) {
+            filter = Dependencies.getRegexFilter(Pattern.compile(options.regex));
+        } else if (options.packageNames.size() > 0) {
+            filter = Dependencies.getPackageFilter(options.packageNames, false);
+        } else {
+            filter = new Dependency.Filter() {
+                public boolean accepts(Dependency dependency) {
+                    return !dependency.getOrigin().equals(dependency.getTarget());
+                }
+            };
+        }
+
+        List<Archive> archives = new ArrayList<Archive>();
+        Deque<String> roots = new LinkedList<String>();
+        for (String s : classes) {
+            File f = new File(s);
+            if (f.exists()) {
+                archives.add(new Archive(f, ClassFileReader.newInstance(f)));
+            } else {
+                if (isValidClassName(s)) {
+                    roots.add(s);
+                } else {
+                    warning("warn.invalid.arg", s);
+                }
+            }
+        }
+
+        List<Archive> classpaths = new ArrayList<Archive>(); // for class file lookup
+        if (options.wildcard) {
+            // include all archives from classpath to the initial list
+            archives.addAll(getClassPathArchives(options.classpath));
+        } else {
+            classpaths.addAll(getClassPathArchives(options.classpath));
+        }
+        classpaths.addAll(PlatformClassPath.getArchives());
+
+        // add all archives to the source locations for reporting
+        sourceLocations.addAll(archives);
+        sourceLocations.addAll(classpaths);
+
+        // Work queue of names of classfiles to be searched.
+        // Entries will be unique, and for classes that do not yet have
+        // dependencies in the results map.
+        Deque<String> deque = new LinkedList<String>();
+        Set<String> doneClasses = new HashSet<String>();
+
+        // get the immediate dependencies of the input files
+        for (Archive a : archives) {
+            for (ClassFile cf : a.reader().getClassFiles()) {
+                String classFileName;
+                try {
+                    classFileName = cf.getName();
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+                a.addClass(classFileName);
+                if (!doneClasses.contains(classFileName)) {
+                    doneClasses.add(classFileName);
+                }
+                for (Dependency d : finder.findDependencies(cf)) {
+                    if (filter.accepts(d)) {
+                        String cn = d.getTarget().getName();
+                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
+                            deque.add(cn);
+                        }
+                        a.addDependency(d);
+                    }
+                }
+            }
+        }
+
+        // add Archive for looking up classes from the classpath
+        // for transitive dependency analysis
+        Deque<String> unresolved = roots;
+        int depth = options.depth > 0 ? options.depth : Integer.MAX_VALUE;
+        do {
+            String name;
+            while ((name = unresolved.poll()) != null) {
+                if (doneClasses.contains(name)) {
+                    continue;
+                }
+                ClassFile cf = null;
+                for (Archive a : classpaths) {
+                    cf = a.reader().getClassFile(name);
+                    if (cf != null) {
+                        String classFileName;
+                        try {
+                            classFileName = cf.getName();
+                        } catch (ConstantPoolException e) {
+                            throw new ClassFileError(e);
+                        }
+                        a.addClass(classFileName);
+                        if (!doneClasses.contains(classFileName)) {
+                            // if name is a fully-qualified class name specified
+                            // from command-line, this class might already be parsed
+                            doneClasses.add(classFileName);
+                            if (depth > 0) {
+                                for (Dependency d : finder.findDependencies(cf)) {
+                                    if (filter.accepts(d)) {
+                                        String cn = d.getTarget().getName();
+                                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
+                                            deque.add(cn);
+                                        }
+                                        a.addDependency(d);
+                                    }
+                                }
+                            }
+                        }
+                        break;
+                    }
+                }
+                if (cf == null) {
+                    NOT_FOUND.addClass(name);
+                }
+            }
+            unresolved = deque;
+            deque = new LinkedList<String>();
+        } while (!unresolved.isEmpty() && depth-- > 0);
+    }
+
+    private void printPackageDeps(PrintWriter out) {
+        for (Archive source : sourceLocations) {
+            SortedMap<Location, SortedSet<Location>> deps = source.getDependencies();
+            if (deps.isEmpty())
+                continue;
+
+            for (Archive target : source.getRequiredArchives()) {
+                out.format("%s -> %s%n", source, target);
+            }
+
+            Map<String, Archive> pkgs = new TreeMap<String, Archive>();
+            SortedMap<String, Archive> targets = new TreeMap<String, Archive>();
+            String pkg = "";
+            for (Map.Entry<Location, SortedSet<Location>> e : deps.entrySet()) {
+                String cn = e.getKey().getClassName();
+                String p = packageOf(e.getKey());
+                Archive origin = Archive.find(e.getKey());
+                assert origin != null;
+                if (!pkgs.containsKey(p)) {
+                    pkgs.put(p, origin);
+                } else if (pkgs.get(p) != origin) {
+                    warning("warn.split.package", p, origin, pkgs.get(p));
+                }
+
+                if (!p.equals(pkg)) {
+                    printTargets(out, targets);
+                    pkg = p;
+                    targets.clear();
+                    out.format("   %s (%s)%n", p, origin.getFileName());
+                }
+
+                for (Location t : e.getValue()) {
+                    p = packageOf(t);
+                    Archive target = Archive.find(t);
+                    if (!targets.containsKey(p)) {
+                        targets.put(p, target);
+                    }
+                }
+            }
+            printTargets(out, targets);
+            out.println();
+        }
+    }
+
+    private void printTargets(PrintWriter out, Map<String, Archive> targets) {
+        for (Map.Entry<String, Archive> t : targets.entrySet()) {
+            String pn = t.getKey();
+            out.format("      -> %-40s %s%n", pn, getPackageInfo(pn, t.getValue()));
+        }
+    }
+
+    private String getPackageInfo(String pn, Archive source) {
+        if (PlatformClassPath.contains(source)) {
+            String name = PlatformClassPath.getProfileName(pn);
+            if (name.isEmpty()) {
+                return "JDK internal API (" + source.getFileName() + ")";
+            }
+            return options.showProfile ? name : "";
+        }
+        return source.getFileName();
+    }
+
+    private static String packageOf(Location loc) {
+        String pkg = loc.getPackageName();
+        return pkg.isEmpty() ? "<unnamed>" : pkg;
+    }
+
+    private void printClassDeps(PrintWriter out) {
+        for (Archive source : sourceLocations) {
+            SortedMap<Location, SortedSet<Location>> deps = source.getDependencies();
+            if (deps.isEmpty())
+                continue;
+
+            for (Archive target : source.getRequiredArchives()) {
+                out.format("%s -> %s%n", source, target);
+            }
+            out.format("%s%n", source);
+            for (Map.Entry<Location, SortedSet<Location>> e : deps.entrySet()) {
+                String cn = e.getKey().getClassName();
+                Archive origin = Archive.find(e.getKey());
+                out.format("   %s (%s)%n", cn, origin.getFileName());
+                for (Location t : e.getValue()) {
+                    cn = t.getClassName();
+                    Archive target = Archive.find(t);
+                    out.format("      -> %-60s %s%n", cn, getPackageInfo(t.getPackageName(), target));
+                }
+            }
+            out.println();
+        }
+    }
+    public void handleOptions(String[] args) throws BadArgs {
+        // process options
+        for (int i=0; i < args.length; i++) {
+            if (args[i].charAt(0) == '-') {
+                String name = args[i];
+                Option option = getOption(name);
+                String param = null;
+                if (option.hasArg) {
+                    if (name.startsWith("--") && name.indexOf('=') > 0) {
+                        param = name.substring(name.indexOf('=') + 1, name.length());
+                    } else if (i + 1 < args.length) {
+                        param = args[++i];
+                    }
+                    if (param == null || param.isEmpty() || param.charAt(0) == '-') {
+                        throw new BadArgs("err.missing.arg", name).showUsage(true);
+                    }
+                }
+                option.process(this, name, param);
+                if (option.ignoreRest()) {
+                    i = args.length;
+                }
+            } else {
+                // process rest of the input arguments
+                for (; i < args.length; i++) {
+                    String name = args[i];
+                    if (name.charAt(0) == '-') {
+                        throw new BadArgs("err.option.after.class", name).showUsage(true);
+                    }
+                    if (name.equals("*") || name.equals("\"*\"")) {
+                        options.wildcard = true;
+                    } else {
+                        classes.add(name);
+                    }
+                }
+            }
+        }
+    }
+
+    private Option getOption(String name) throws BadArgs {
+        for (Option o : recognizedOptions) {
+            if (o.matches(name)) {
+                return o;
+            }
+        }
+        throw new BadArgs("err.unknown.option", name).showUsage(true);
+    }
+
+    private void reportError(String key, Object... args) {
+        log.println(getMessage("error.prefix") + " " + getMessage(key, args));
+    }
+
+    private void warning(String key, Object... args) {
+        log.println(getMessage("warn.prefix") + " " + getMessage(key, args));
+    }
+
+    private void showHelp() {
+        log.println(getMessage("main.usage", PROGNAME));
+        for (Option o : recognizedOptions) {
+            String name = o.aliases[0].substring(1); // there must always be at least one name
+            name = name.charAt(0) == '-' ? name.substring(1) : name;
+            if (o.isHidden() || name.equals("h")) {
+                continue;
+            }
+            log.println(getMessage("main.opt." + name));
+        }
+    }
+
+    private void showVersion(boolean full) {
+        log.println(version(full ? "full" : "release"));
+    }
+
+    private String version(String key) {
+        // key=version:  mm.nn.oo[-milestone]
+        // key=full:     mm.mm.oo[-milestone]-build
+        if (ResourceBundleHelper.versionRB == null) {
+            return System.getProperty("java.version");
+        }
+        try {
+            return ResourceBundleHelper.versionRB.getString(key);
+        } catch (MissingResourceException e) {
+            return getMessage("version.unknown", System.getProperty("java.version"));
+        }
+    }
+
+    public String getMessage(String key, Object... args) {
+        try {
+            return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
+        } catch (MissingResourceException e) {
+            throw new InternalError("Missing message: " + key);
+        }
+    }
+
+    private static class Options {
+        enum Verbose {
+            CLASS,
+            PACKAGE,
+            SUMMARY,
+            VERBOSE
+        };
+
+        boolean help;
+        boolean version;
+        boolean fullVersion;
+        boolean showFlags;
+        boolean showProfile;
+        boolean showSummary;
+        boolean wildcard;
+        String regex;
+        String classpath = "";
+        int depth = 1;
+        Verbose verbose = Verbose.PACKAGE;
+        Set<String> packageNames = new HashSet<String>();
+    }
+
+    private static class ResourceBundleHelper {
+        static final ResourceBundle versionRB;
+        static final ResourceBundle bundle;
+
+        static {
+            Locale locale = Locale.getDefault();
+            try {
+                bundle = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdeps", locale);
+            } catch (MissingResourceException e) {
+                throw new InternalError("Cannot find jdeps resource bundle for locale " + locale);
+            }
+            try {
+                versionRB = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.version");
+            } catch (MissingResourceException e) {
+                throw new InternalError("version.resource.missing");
+            }
+        }
+    }
+
+    private List<Archive> getArchives(List<String> filenames) throws IOException {
+        List<Archive> result = new ArrayList<Archive>();
+        for (String s : filenames) {
+            File f = new File(s);
+            if (f.exists()) {
+                result.add(new Archive(f, ClassFileReader.newInstance(f)));
+            } else {
+                warning("warn.file.not.exist", s);
+            }
+        }
+        return result;
+    }
+
+    private List<Archive> getClassPathArchives(String paths) throws IOException {
+        List<Archive> result = new ArrayList<Archive>();
+        if (paths.isEmpty()) {
+            return result;
+        }
+        for (String p : paths.split(File.pathSeparator)) {
+            if (p.length() > 0) {
+                File f = new File(p);
+                if (f.exists()) {
+                    result.add(new Archive(f, ClassFileReader.newInstance(f)));
+                }
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Main.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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 com.sun.tools.jdeps;
+
+import java.io.*;
+
+/**
+ *
+ * Usage:
+ *    jdeps [options] files ...
+ * where options include:
+ *    -p package-name   restrict analysis to classes in this package
+ *                      (may be given multiple times)
+ *    -e regex          restrict analysis to packages matching pattern
+ *                      (-p and -e are exclusive)
+ *    -v                show class-level dependencies
+ *                      default: package-level dependencies
+ *    -r --recursive    transitive dependencies analysis
+ *    -classpath paths  Classpath to locate class files
+ *    -all              process all class files in the given classpath
+ */
+public class Main {
+    public static void main(String... args) throws Exception {
+        JdepsTask t = new JdepsTask();
+        int rc = t.run(args);
+        System.exit(rc);
+    }
+
+
+    /**
+     * Entry point that does <i>not</i> call System.exit.
+     *
+     * @param args command line arguments
+     * @param out output stream
+     * @return an exit code. 0 means success, non-zero means an error occurred.
+     */
+    public static int run(String[] args, PrintWriter out) {
+        JdepsTask t = new JdepsTask();
+        t.setLog(out);
+        return t.run(args);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * 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 com.sun.tools.jdeps;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+
+/**
+ * ClassPath for Java SE and JDK
+ */
+class PlatformClassPath {
+    /*
+     * Profiles for Java SE
+     *
+     * This is a temporary workaround until a common API is defined for langtools
+     * to determine which profile a given classname belongs to.  The list of
+     * packages and profile names are hardcoded in jdk.properties and
+     * split packages are not supported.
+     */
+    static class Profile {
+        final String name;
+        final Set<String> packages;
+
+        Profile(String name) {
+            this.name = name;
+            this.packages = new HashSet<String>();
+        }
+    }
+
+    private final static String JAVAFX = "javafx";
+    private final static Map<String,Profile> map = getProfilePackages();
+    static String getProfileName(String packageName) {
+        Profile profile = map.get(packageName);
+        if (packageName.startsWith(JAVAFX + ".")) {
+            profile = map.get(JAVAFX);
+        }
+        return profile != null ? profile.name : "";
+    }
+
+    private final static List<Archive> javaHomeArchives = init();
+    static List<Archive> getArchives() {
+        return javaHomeArchives;
+    }
+
+    static boolean contains(Archive archive) {
+        return javaHomeArchives.contains(archive);
+    }
+
+    private static List<Archive> init() {
+        List<Archive> result = new ArrayList<Archive>();
+        String javaHome = System.getProperty("java.home");
+        List<File> files = new ArrayList<File>();
+        File jre = new File(javaHome, "jre");
+        File lib = new File(javaHome, "lib");
+
+        try {
+            if (jre.exists() && jre.isDirectory()) {
+                result.addAll(addJarFiles(new File(jre, "lib")));
+                result.addAll(addJarFiles(lib));
+            } else if (lib.exists() && lib.isDirectory()) {
+                // either a JRE or a jdk build image
+                File classes = new File(javaHome, "classes");
+                if (classes.exists() && classes.isDirectory()) {
+                    // jdk build outputdir
+                    result.add(new Archive(classes, ClassFileReader.newInstance(classes)));
+                }
+                // add other JAR files
+                result.addAll(addJarFiles(lib));
+            } else {
+                throw new RuntimeException("\"" + javaHome + "\" not a JDK home");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        // add a JavaFX profile if there is jfxrt.jar
+        for (Archive archive : result) {
+            if (archive.getFileName().equals("jfxrt.jar")) {
+                map.put(JAVAFX, new Profile("jfxrt.jar"));
+            }
+        }
+        return result;
+    }
+
+    private static List<Archive> addJarFiles(File f) throws IOException {
+        final List<Archive> result = new ArrayList<Archive>();
+        final Path root = f.toPath();
+        final Path ext = root.resolve("ext");
+        Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+                throws IOException
+            {
+                if (dir.equals(root) || dir.equals(ext)) {
+                    return FileVisitResult.CONTINUE;
+                } else {
+                    // skip other cobundled JAR files
+                    return FileVisitResult.SKIP_SUBTREE;
+                }
+            }
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                throws IOException
+            {
+                File f = file.toFile();
+                String fn = f.getName();
+                if (fn.endsWith(".jar") && !fn.equals("alt-rt.jar")) {
+                    result.add(new Archive(f, ClassFileReader.newInstance(f)));
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+        return result;
+    }
+
+    private static Map<String,Profile> getProfilePackages() {
+        Map<String,Profile> map = new HashMap<String,Profile>();
+
+        // read the properties as a ResourceBundle as the build compiles
+        // the properties file into Java class.  Another alternative is
+        // to load it as Properties and fix the build to exclude this file.
+        ResourceBundle profileBundle =
+            ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdk");
+
+        int i=1;
+        String key;
+        while (profileBundle.containsKey((key = "profile." + i + ".name"))) {
+            Profile profile = new Profile(profileBundle.getString(key));
+            String n = profileBundle.getString("profile." + i + ".packages");
+            String[] pkgs = n.split("\\s+");
+            for (String p : pkgs) {
+                if (p.isEmpty()) continue;
+                assert(map.containsKey(p) == false);
+                profile.packages.add(p);
+                map.put(p, profile);
+            }
+            i++;
+        }
+        return map;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,57 @@
+main.usage.summary=\
+Usage: {0} <options> <classes...>\n\
+use -h, -? or --help for a list of possible options
+
+main.usage=\
+Usage: {0} <options> <classes...>\n\
+where <classes> can be a pathname to a .class file, a directory, a JAR file,\n\
+or a fully-qualified classname or wildcard "*".  Possible options include:
+
+error.prefix=Error:
+warn.prefix=Warning:
+
+main.opt.h=\
+\  -h -?      --help                    Print this usage message
+
+main.opt.version=\
+\             --version                 Version information
+
+main.opt.V=\
+\  -V <level> --verbose-level=<level>   Print package-level or class-level dependencies\n\
+\                                       Valid levels are: "package" and "class"
+
+main.opt.v=\
+\  -v         --verbose                 Print additional information
+
+main.opt.s=\
+\  -s         --summary                 Print dependency summary only
+
+main.opt.p=\
+\  -p <pkg name> --package=<pkg name>   Restrict analysis to classes in this package\n\
+\                                       (may be given multiple times)
+
+main.opt.e=\
+\  -e <regex> --regex=<regex>           Restrict analysis to packages matching pattern\n\
+\                                       (-p and -e are exclusive)
+
+main.opt.P=\
+\  -P         --profile                 Show profile or the file containing a package
+
+main.opt.c=\
+\  -c <path>  --classpath=<path>        Specify where to find class files
+
+main.opt.R=\
+\  -R         --recursive               Recursively traverse all dependencies
+
+main.opt.d=\
+\  -d <depth> --depth=<depth>           Specify the depth of the transitive dependency analysis
+
+err.unknown.option=unknown option: {0}
+err.missing.arg=no value given for {0}
+err.internal.error=internal error: {0} {1} {2}
+err.invalid.arg.for.option=invalid argument for option: {0}
+err.option.after.class=option must be specified before classes: {0}
+warn.invalid.arg=Invalid classname or pathname not exist: {0}
+warn.split.package=package {0} defined in {1} {2}
+
+artifact.not.found=not found
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdk.properties	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,262 @@
+# This properties file does not need localization.
+
+profile.1.name = compact1
+profile.1.packages = \
+    java.io \
+    java.lang \
+    java.lang.annotation \
+    java.lang.invoke \
+    java.lang.ref \
+    java.lang.reflect \
+    java.math \
+    java.net \
+    java.nio \
+    java.nio.channels \
+    java.nio.channels.spi \
+    java.nio.charset \
+    java.nio.charset.spi \
+    java.nio.file \
+    java.nio.file.attribute \
+    java.nio.file.spi \
+    java.security \
+    java.security.cert \
+    java.security.interfaces \
+    java.security.spec \
+    java.text \
+    java.text.spi \
+    java.util \
+    java.util.concurrent \
+    java.util.concurrent.atomic \
+    java.util.concurrent.locks \
+    java.util.jar \
+    java.util.logging \
+    java.util.regex \
+    java.util.spi \
+    java.util.zip \
+    javax.crypto \
+    javax.crypto.interfaces \
+    javax.crypto.spec \
+    javax.security.auth \
+    javax.security.auth.callback \
+    javax.security.auth.login \
+    javax.security.auth.spi \
+    javax.security.auth.x500 \
+    javax.net \
+    javax.net.ssl \
+    javax.security.cert \
+    \
+    com.sun.net.ssl \
+    com.sun.nio.file \
+    com.sun.nio.sctp \
+    com.sun.security.auth \
+    com.sun.security.auth.login
+
+profile.2.name = compact2
+profile.2.packages = \
+    java.sql \
+    javax.sql \
+    javax.xml \
+    javax.xml.datatype \
+    javax.xml.namespace \
+    javax.xml.parsers \
+    javax.xml.stream \
+    javax.xml.stream.events \
+    javax.xml.stream.util \
+    javax.xml.transform \
+    javax.xml.transform.dom \
+    javax.xml.transform.sax \
+    javax.xml.transform.stax \
+    javax.xml.transform.stream \
+    javax.xml.validation \
+    javax.xml.xpath \
+    org.w3c.dom \
+    org.w3c.dom.bootstrap \
+    org.w3c.dom.events \
+    org.w3c.dom.ls \
+    org.xml.sax \
+    org.xml.sax.ext \
+    org.xml.sax.helpers \
+    java.rmi \
+    java.rmi.activation \
+    java.rmi.dgc \
+    java.rmi.registry \
+    java.rmi.server \
+    javax.rmi.ssl \
+    javax.transaction \
+    javax.transaction.xa \
+    \
+    com.sun.net.httpserver \
+    com.sun.net.httpserver.spi
+
+profile.3.name = compact3
+profile.3.packages = \
+    java.lang.instrument \
+    java.lang.management \
+    java.security.acl \
+    java.util.prefs \
+    javax.management \
+    javax.management.loading \
+    javax.management.modelmbean \
+    javax.management.monitor \
+    javax.management.openmbean \
+    javax.management.relation \
+    javax.management.remote \
+    javax.management.remote.rmi \
+    javax.management.timer \
+    javax.naming \
+    javax.naming.directory \
+    javax.naming.event \
+    javax.naming.ldap \
+    javax.naming.spi \
+    javax.sql.rowset \
+    javax.sql.rowset.serial \
+    javax.sql.rowset.spi \
+    javax.security.auth.kerberos \
+    javax.security.sasl \
+    javax.script \
+    javax.smartcardio \
+    javax.xml.crypto \
+    javax.xml.crypto.dom \
+    javax.xml.crypto.dsig \
+    javax.xml.crypto.dsig.dom \
+    javax.xml.crypto.dsig.keyinfo \
+    javax.xml.crypto.dsig.spec \
+    javax.annotation.processing \
+    javax.lang.model \
+    javax.lang.model.element \
+    javax.lang.model.type \
+    javax.lang.model.util \
+    javax.tools \
+    javax.tools.annotation \
+    org.ietf.jgss \
+    \
+    com.sun.management \
+    com.sun.security.auth.callback \
+    com.sun.security.auth.module \
+    com.sun.security.jgss
+
+profile.4.name = Full JRE
+profile.4.packages = \
+    java.applet \
+    java.awt \
+    java.awt.color \
+    java.awt.datatransfer \
+    java.awt.dnd \
+    java.awt.dnd.peer \
+    java.awt.event \
+    java.awt.font \
+    java.awt.geom \
+    java.awt.im \
+    java.awt.im.spi \
+    java.awt.image \
+    java.awt.image.renderable \
+    java.awt.peer \
+    java.awt.print \
+    java.beans \
+    java.beans.beancontext \
+    javax.accessibility \
+    javax.imageio \
+    javax.imageio.event \
+    javax.imageio.metadata \
+    javax.imageio.plugins.bmp \
+    javax.imageio.plugins.jpeg \
+    javax.imageio.spi \
+    javax.imageio.stream \
+    javax.print \
+    javax.print.attribute \
+    javax.print.attribute.standard \
+    javax.print.event \
+    javax.sound.midi \
+    javax.sound.midi.spi \
+    javax.sound.sampled \
+    javax.sound.sampled.spi \
+    javax.swing \
+    javax.swing.border \
+    javax.swing.colorchooser \
+    javax.swing.event \
+    javax.swing.filechooser \
+    javax.swing.plaf \
+    javax.swing.plaf.basic \
+    javax.swing.plaf.metal \
+    javax.swing.plaf.multi \
+    javax.swing.plaf.nimbus \
+    javax.swing.plaf.synth \
+    javax.swing.table \
+    javax.swing.text \
+    javax.swing.text.html \
+    javax.swing.text.html.parser \
+    javax.swing.text.rtf \
+    javax.swing.tree \
+    javax.swing.undo \
+    javax.activation \
+    javax.jws \
+    javax.jws.soap \
+    javax.rmi \
+    javax.rmi.CORBA \
+    javax.xml.bind \
+    javax.xml.bind.annotation \
+    javax.xml.bind.annotation.adapters \
+    javax.xml.bind.attachment \
+    javax.xml.bind.helpers \
+    javax.xml.bind.util \
+    javax.xml.soap \
+    javax.xml.ws \
+    javax.xml.ws.handler \
+    javax.xml.ws.handler.soap \
+    javax.xml.ws.http \
+    javax.xml.ws.soap \
+    javax.xml.ws.spi \
+    javax.xml.ws.spi.http \
+    javax.xml.ws.wsaddressing \
+    javax.annotation \
+    org.omg.CORBA \
+    org.omg.CORBA.DynAnyPackage \
+    org.omg.CORBA.ORBPackage \
+    org.omg.CORBA.TypeCodePackage \
+    org.omg.CORBA.portable \
+    org.omg.CORBA_2_3 \
+    org.omg.CORBA_2_3.portable \
+    org.omg.CosNaming \
+    org.omg.CosNaming.NamingContextExtPackage \
+    org.omg.CosNaming.NamingContextPackage \
+    org.omg.Dynamic \
+    org.omg.DynamicAny \
+    org.omg.DynamicAny.DynAnyFactoryPackage \
+    org.omg.DynamicAny.DynAnyPackage \
+    org.omg.IOP \
+    org.omg.IOP.CodecFactoryPackage \
+    org.omg.IOP.CodecPackage \
+    org.omg.Messaging \
+    org.omg.PortableInterceptor \
+    org.omg.PortableInterceptor.ORBInitInfoPackage \
+    org.omg.PortableServer \
+    org.omg.PortableServer.CurrentPackage \
+    org.omg.PortableServer.POAManagerPackage \
+    org.omg.PortableServer.POAPackage \
+    org.omg.PortableServer.ServantLocatorPackage \
+    org.omg.PortableServer.portable \
+    org.omg.SendingContext \
+    org.omg.stub.java.rmi \
+    org.omg.stub.javax.management.remote.rmi
+
+# Remaining JDK supported API
+profile.5.name = JDK tools
+profile.5.packages = \
+    com.sun.jdi \
+    com.sun.jdi.connect \
+    com.sun.jdi.connect.spi \
+    com.sun.jdi.event \
+    com.sun.jdi.request \
+    com.sun.javadoc \
+    com.sun.tools.doclets \
+    com.sun.tools.doctree \
+    com.sun.source.tree \
+    com.sun.source.util \
+    com.sun.tools.attach \
+    com.sun.tools.attach.spi \
+    com.sun.tools.jconsole \
+    com.sun.tools.javac \
+    com.sun.tools.javah \
+    com.sun.tools.javap \
+    com.sun.tools.javadoc \
+    com.sun.servicetag
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/version.properties-template	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+jdk=$(JDK_VERSION)
+full=$(FULL_VERSION)
+release=$(RELEASE)
--- a/langtools/src/share/classes/javax/lang/model/element/Element.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/javax/lang/model/element/Element.java	Wed Jul 05 18:36:11 2017 +0200
@@ -179,6 +179,10 @@
      * instance initializer}, an empty name is returned.
      *
      * @return the simple name of this element
+     * @see PackageElement#getSimpleName
+     * @see ExecutableElement#getSimpleName
+     * @see TypeElement#getSimpleName
+     * @see VariableElement#getSimpleName
      */
     Name getSimpleName();
 
@@ -202,6 +206,11 @@
      * {@linkplain TypeParameterElement#getGenericElement the
      * generic element} of the type parameter is returned.
      *
+     * <li> If this is a {@linkplain
+     * VariableElement#getEnclosingElement method or constructor
+     * parameter}, {@linkplain ExecutableElement the executable
+     * element} which declares the parameter is returned.
+     *
      * </ul>
      *
      * @return the enclosing element, or {@code null} if there is none
--- a/langtools/src/share/classes/javax/lang/model/element/VariableElement.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/javax/lang/model/element/VariableElement.java	Wed Jul 05 18:36:11 2017 +0200
@@ -62,4 +62,29 @@
      * @jls 4.12.4 final Variables
      */
     Object getConstantValue();
+
+    /**
+     * Returns the simple name of this variable element.
+     *
+     * <p>For method and constructor parameters, the name of each
+     * parameter must be distinct from the names of all other
+     * parameters of the same executable.  If the original source
+     * names are not available, an implementation may synthesize names
+     * subject to the distinctness requirement above.
+     *
+     * @return the simple name of this variable element
+     */
+    @Override
+    Name getSimpleName();
+
+    /**
+     * Returns the enclosing element of this variable.
+     *
+     * The enclosing element of a method or constructor parameter is
+     * the executable declaring the parameter.
+     *
+     * @return the enclosing element of this variable
+     */
+    @Override
+    Element getEnclosingElement();
 }
--- a/langtools/src/share/classes/javax/lang/model/element/package-info.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/src/share/classes/javax/lang/model/element/package-info.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -48,9 +48,12 @@
  * {@linkplain java.lang.annotation.RetentionPolicy#SOURCE source}
  * {@linkplain java.lang.annotation.Retention retention} cannot be
  * recovered from class files and class files might not be able to
- * provide source position information.  The {@linkplain
- * javax.lang.model.element.Modifier modifiers} on an element may
- * differ in some cases including
+ * provide source position information.
+ *
+ * Names of parameters may not be recoverable from class files.
+ *
+ * The {@linkplain javax.lang.model.element.Modifier modifiers} on an
+ * element may differ in some cases including:
  *
  * <ul>
  * <li> {@code strictfp} on a class or interface
--- a/langtools/test/Makefile	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/Makefile	Wed Jul 05 18:36:11 2017 +0200
@@ -229,7 +229,7 @@
 all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary
 	@echo "Testing completed successfully"
 
-jtreg apt javac javadoc javah javap: $(JPRT_CLEAN) jtreg-tests $(JPRT_ARCHIVE_BUNDLE) jtreg-summary
+jtreg apt javac javadoc javah javap jdeps: $(JPRT_CLEAN) jtreg-tests $(JPRT_ARCHIVE_BUNDLE) jtreg-summary
 	@echo "Testing completed successfully"
 
 jck-compiler: $(JPRT_CLEAN) jck-compiler-tests $(JPRT_ARCHIVE_BUNDLE) jck-compiler-summary
@@ -246,6 +246,7 @@
 javadoc:	JTREG_TESTDIRS = tools/javadoc com/sun/javadoc
 javah:		JTREG_TESTDIRS = tools/javah
 javap:		JTREG_TESTDIRS = tools/javap
+jdeps:		JTREG_TESTDIRS = tools/jdeps
 
 # Run jtreg tests
 #
@@ -426,7 +427,7 @@
 
 # Phony targets (e.g. these are not filenames)
 .PHONY: all clean \
-	jtreg javac javadoc javah javap jtreg-tests jtreg-summary check-jtreg \
+	jtreg javac javadoc javah javap jdeps jtreg-tests jtreg-summary check-jtreg \
 	jck-compiler jck-compiler-tests jck-compiler-summary \
 	jck-runtime jck-runtime-tests jck-runtime-summary check-jck
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testAbstractMethod/TestAbstractMethod.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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      8004891
+ * @summary  Make sure that the abstract method is identified correctly
+ *           if the abstract modifier is present explicitly or implicitly.
+ * @author   bpatel
+ * @library  ../lib/
+ * @build    JavadocTester TestAbstractMethod
+ * @run main TestAbstractMethod
+ */
+
+public class TestAbstractMethod extends JavadocTester {
+
+    //Test information.
+    private static final String BUG_ID = "8004891";
+
+    //Javadoc arguments.
+    private static final String[] ARGS = new String[] {
+        "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg"
+    };
+
+    //Input for string search tests.
+    private static final String[][] TEST = {
+        {BUG_ID + FS + "pkg" + FS + "A.html",
+            "<td class=\"colFirst\"><code>default void</code></td>"},
+        {BUG_ID + FS + "pkg" + FS + "A.html",
+            "<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
+            "All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
+            "<span id=\"t2\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span><span id=\"t3\" " +
+            "class=\"tableTab\"><span><a href=\"javascript:show(4);\">" +
+            "Abstract Methods</a></span><span class=\"tabEnd\">&nbsp;</span>" +
+            "</span><span id=\"t5\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(16);\">Default Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
+        {BUG_ID + FS + "pkg" + FS + "B.html",
+            "<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
+            "All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
+            "<span id=\"t2\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span><span id=\"t3\" " +
+            "class=\"tableTab\"><span><a href=\"javascript:show(4);\">Abstract " +
+            "Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
+            "<span id=\"t4\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(8);\">Concrete Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
+        {BUG_ID + FS + "pkg" + FS + "B.html",
+            "<td class=\"colFirst\"><code>abstract void</code></td>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
+            "All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
+            "<span id=\"t2\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span>" +
+            "<span id=\"t5\" class=\"tableTab\"><span>" +
+            "<a href=\"javascript:show(16);\">Default Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<td class=\"colFirst\"><code>default void</code></td>"}
+    };
+    private static final String[][] NEGATED_TEST = {
+        {BUG_ID + FS + "pkg" + FS + "A.html",
+            "<td class=\"colFirst\"><code>abstract void</code></td>"},
+        {BUG_ID + FS + "pkg" + FS + "B.html",
+            "<span><a href=\"javascript:show(16);\">Default Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span>"},
+        {BUG_ID + FS + "pkg" + FS + "B.html",
+            "<td class=\"colFirst\"><code>default void</code></td>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<span><a href=\"javascript:show(4);\">Abstract Methods</a></span>" +
+            "<span class=\"tabEnd\">&nbsp;</span>"}
+    };
+
+    /**
+     * The entry point of the test.
+     * @param args the array of command line arguments.
+     */
+    public static void main(String[] args) {
+        TestAbstractMethod tester = new TestAbstractMethod();
+        run(tester, ARGS, TEST, NEGATED_TEST);
+        tester.printSummary();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugId() {
+        return BUG_ID;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugName() {
+        return getClass().getName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testAbstractMethod/pkg/A.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+public interface A {
+
+    public void method1();
+
+    public default void defaultMethod() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testAbstractMethod/pkg/B.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+public abstract class B {
+
+    public abstract void method1();
+
+    public void method2() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testAbstractMethod/pkg/C.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+public interface C {
+
+    public default void onlyMethod() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/TestRepeatedAnnotations.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,187 @@
+/*
+ * 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      8005092
+ * @summary  Test repeated annotations output.
+ * @author   bpatel
+ * @library  ../lib/
+ * @build    JavadocTester TestRepeatedAnnotations
+ * @run main TestRepeatedAnnotations
+ */
+
+public class TestRepeatedAnnotations extends JavadocTester {
+
+    //Test information.
+    private static final String BUG_ID = "8005092";
+
+    //Javadoc arguments.
+    private static final String[] ARGS = new String[] {
+        "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "pkg1"
+    };
+
+    //Input for string search tests.
+    private static final String[][] TEST = {
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/ContaineeRegDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeRegDoc</a> " +
+            "<a href=\"../pkg/ContaineeRegDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeRegDoc</a>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/RegContainerDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContainerDoc</a>" +
+            "(<a href=\"../pkg/RegContainerDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeNotDoc</a>," +
+            "<a href=\"../pkg/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeNotDoc</a>})"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/ContainerSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContainerSynthDoc</a>(" +
+            "<a href=\"../pkg/ContainerSynthDoc.html#value()\">value</a>=" +
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a>)"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
+            "<a href=\"../pkg/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
+
+        {BUG_ID + FS + "pkg" + FS + "D.html",
+            "<a href=\"../pkg/RegDoc.html\" title=\"annotation in pkg\">@RegDoc</a>" +
+            "(<a href=\"../pkg/RegDoc.html#x()\">x</a>=1)"},
+        {BUG_ID + FS + "pkg" + FS + "D.html",
+            "<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>" +
+            "(<a href=\"../pkg/RegArryDoc.html#y()\">y</a>=1)"},
+        {BUG_ID + FS + "pkg" + FS + "D.html",
+            "<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>" +
+            "(<a href=\"../pkg/RegArryDoc.html#y()\">y</a>={1,2})"},
+        {BUG_ID + FS + "pkg" + FS + "D.html",
+            "<a href=\"../pkg/NonSynthDocContainer.html\" " +
+            "title=\"annotation in pkg\">@NonSynthDocContainer</a>" +
+            "(<a href=\"../pkg/NonSynthDocContainer.html#value()\">value</a>=" +
+            "<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>)"},
+
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/RegContainerValDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContainerValDoc</a>" +
+            "(<a href=\"../pkg1/RegContainerValDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg1/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContaineeNotDoc</a>," +
+            "<a href=\"../pkg1/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContaineeNotDoc</a>}," +
+            "<a href=\"../pkg1/RegContainerValDoc.html#y()\">y</a>=3)"},
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/ContainerValDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContainerValDoc</a>" +
+            "(<a href=\"../pkg1/ContainerValDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg1/ContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeNotDoc</a>," +
+            "<a href=\"../pkg1/ContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeNotDoc</a>}," +
+            "<a href=\"../pkg1/ContainerValDoc.html#x()\">x</a>=1)"}
+    };
+
+    private static final String[][] NEGATED_TEST = {
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/RegContaineeDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeDoc</a> " +
+            "<a href=\"../pkg/RegContaineeDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeDoc</a>"},
+        {BUG_ID + FS + "pkg" + FS + "C.html",
+            "<a href=\"../pkg/RegContainerNotDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContainerNotDoc</a>" +
+            "(<a href=\"../pkg/RegContainerNotDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeNotDoc</a>," +
+            "<a href=\"../pkg/RegContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg\">@RegContaineeNotDoc</a>})"},
+
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeSynthDoc</a> " +
+            "<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeSynthDoc</a>"},
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/RegContainerValNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContainerValNotDoc</a>" +
+            "(<a href=\"../pkg1/RegContainerValNotDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg1/RegContaineeDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContaineeDoc</a>," +
+            "<a href=\"../pkg1/RegContaineeDoc.html\" " +
+            "title=\"annotation in pkg1\">@RegContaineeDoc</a>}," +
+            "<a href=\"../pkg1/RegContainerValNotDoc.html#y()\">y</a>=4)"},
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/ContainerValNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContainerValNotDoc</a>" +
+            "(<a href=\"../pkg1/ContainerValNotDoc.html#value()\">value</a>={" +
+            "<a href=\"../pkg1/ContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeNotDoc</a>," +
+            "<a href=\"../pkg1/ContaineeNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeNotDoc</a>}," +
+            "<a href=\"../pkg1/ContainerValNotDoc.html#x()\">x</a>=2)"},
+        {BUG_ID + FS + "pkg1" + FS + "C.html",
+            "<a href=\"../pkg1/ContainerSynthNotDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContainerSynthNotDoc</a>(" +
+            "<a href=\"../pkg1/ContainerSynthNotDoc.html#value()\">value</a>=" +
+            "<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
+            "title=\"annotation in pkg1\">@ContaineeSynthDoc</a>)"}
+    };
+
+    /**
+     * The entry point of the test.
+     * @param args the array of command line arguments.
+     */
+    public static void main(String[] args) {
+        TestRepeatedAnnotations tester = new TestRepeatedAnnotations();
+        run(tester, ARGS, TEST, NEGATED_TEST);
+        tester.printSummary();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugId() {
+        return BUG_ID;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugName() {
+        return getClass().getName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/C.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+@ContainerSynthDoc(value={@ContaineeSynthDoc,@ContaineeSynthDoc})
+@ContainerRegDoc(value={@ContaineeRegDoc,@ContaineeRegDoc})
+@RegContainerDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc})
+@ContainerRegNotDoc(value={@RegContaineeDoc,@RegContaineeDoc})
+@RegContainerNotDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc})
+@ContaineeSynthDoc @ContaineeSynthDoc @ContaineeSynthDoc
+public class C {
+
+    @ContainerSynthDoc(value={@ContaineeSynthDoc})
+    public void test1() {}
+
+    @ContaineeSynthDoc @ContaineeSynthDoc
+    public void test2() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeRegDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation contained by ContainerRegDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface ContaineeRegDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented synthesized annotation contained by ContainerSynthDoc.
+ * It will be used to annotate Class C and a method in the class using a synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+@ContainedBy(ContainerSynthDoc.class)
+public @interface ContaineeSynthDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerRegDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation container for ContaineeRegDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface ContainerRegDoc {
+
+    ContaineeRegDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerRegNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation container for RegContaineeDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface ContainerRegNotDoc {
+
+    RegContaineeDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented synthesized annotation container for ContaineeSynthDoc.
+ * It will be used to annotate Class C and a method in the class using a synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+@ContainerFor(ContaineeSynthDoc.class)
+public @interface ContainerSynthDoc {
+
+    ContaineeSynthDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/D.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+@RegDoc(x=1)
+public class D {
+
+    @RegArryDoc(y={1})
+    public void test1() {}
+
+    @RegArryDoc(y={1,2})
+    public void test2() {}
+
+    @NonSynthDocContainer(value={@RegArryDoc})
+    public void test3() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/NonSynthDocContainer.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation.
+ * It will be used to annotate methods in class D.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface NonSynthDocContainer {
+
+    RegArryDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegArryDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation.
+ * It will be used to annotate methods in Class D.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegArryDoc {
+
+    int[] y();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegContaineeDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation contained by ContainerRegNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegContaineeDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegContaineeNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation contained by RegContainerNotDoc
+ * and RegContainerDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface RegContaineeNotDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegContainerDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation container for RegContainerDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegContainerDoc {
+
+    RegContaineeNotDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegContainerNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation container for RegContaineeNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface RegContainerNotDoc {
+
+    RegContaineeNotDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/RegDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation.
+ * It will be used to annotate Class D.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegDoc {
+
+    int x();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/C.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+@ContainerSynthNotDoc(value={@ContaineeSynthDoc,@ContaineeSynthDoc})
+@RegContainerValDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc},y=3)
+@ContainerValDoc(value={@ContaineeNotDoc,@ContaineeNotDoc},x=1)
+@RegContainerValNotDoc(value={@RegContaineeDoc,@RegContaineeDoc},y=4)
+@ContainerValNotDoc(value={@ContaineeNotDoc,@ContaineeNotDoc},x=2)
+public class C {
+
+    @ContainerSynthNotDoc(value={@ContaineeSynthDoc})
+    public void test1() {}
+
+    @ContaineeSynthDoc @ContaineeSynthDoc
+    public void test2() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation contained by ContainerValNotDoc
+ * and ContainerValDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface ContaineeNotDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented synthesized annotation contained by ContainerSynthNotDoc.
+ * It will be used to annotate Class C and methods in the class using a synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+@ContainedBy(ContainerSynthNotDoc.class)
+public @interface ContaineeSynthDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented synthesized annotation container for ContaineeSynthDoc.
+ * It will be used to annotate Class C and methods in the class using a synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@ContainerFor(ContaineeSynthDoc.class)
+public @interface ContainerSynthNotDoc {
+
+    ContaineeSynthDoc[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerValDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation container for ContaineeNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface ContainerValDoc {
+
+    ContaineeNotDoc[] value();
+
+    int x();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerValNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation container for ContaineeNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface ContainerValNotDoc {
+
+    ContaineeNotDoc[] value();
+
+    int x();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContaineeDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation contained by RegContainerValNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegContaineeDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContaineeNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation contained by RegContainerValDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface RegContaineeNotDoc {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContainerValDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a documented annotation container for RegContaineeNotDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+@Documented
+public @interface RegContainerValDoc {
+
+    RegContaineeNotDoc[] value();
+
+    int y();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContainerValNotDoc.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package pkg1;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is a non-documented annotation container for RegContaineeDoc.
+ * It will be used to annotate Class C using a non-synthesized form.
+ *
+ * @author Bhavesh Patel
+ */
+public @interface RegContainerValNotDoc {
+
+    RegContaineeDoc[] value();
+
+    int y();
+}
--- a/langtools/test/tools/doclint/DocLintTester.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/doclint/DocLintTester.java	Wed Jul 05 18:36:11 2017 +0200
@@ -107,7 +107,7 @@
 
     private static final Pattern dirFileLine = Pattern.compile(
             "(?m)"                          // multi-line mode
-            + "^([^: ]+?)"                  // directory part of file name
+            + "^(.*?)"                      // directory part of file name
             + "([A-Za-z0-9.]+:[0-9]+:)");   // file name and line number
 
     String removeFileNames(String s) {
--- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, 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
@@ -26,14 +26,19 @@
  * @bug     6769027
  * @summary Source line should be displayed immediately after the first diagnostic line
  * @author  Maurizio Cimadamore
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
  * @run main/othervm T6769027
  */
+
 import java.net.URI;
 import java.util.regex.Matcher;
 import javax.tools.*;
 import com.sun.tools.javac.util.*;
 
-public class T6769027 {
+public class T6769027
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum OutputKind {
         RAW("rawDiagnostics","rawDiagnostics"),
@@ -314,7 +319,7 @@
 
         @Override
         protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) {
-            return new java.io.PrintWriter(System.out);
+            return outWriter;
         }
 
         @Override
@@ -323,13 +328,42 @@
         }
     }
 
-    int nerrors = 0;
+    OutputKind outputKind;
+    ErrorKind errorKind;
+    MultilineKind multiKind;
+    MultilinePolicy multiPolicy;
+    PositionKind posKind;
+    XDiagsSource xdiagsSource;
+    XDiagsCompact xdiagsCompact;
+    CaretKind caretKind;
+    SourceLineKind sourceLineKind;
+    IndentKind summaryIndent;
+    IndentKind detailsIndent;
+    IndentKind sourceIndent;
+    IndentKind subdiagsIndent;
 
-    void exec(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
+    T6769027(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
             MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
             XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
             IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
             IndentKind subdiagsIndent) {
+        this.outputKind = outputKind;
+        this.errorKind = errorKind;
+        this.multiKind = multiKind;
+        this.multiPolicy = multiPolicy;
+        this.posKind = posKind;
+        this.xdiagsSource = xdiagsSource;
+        this.xdiagsCompact = xdiagsCompact;
+        this.caretKind = caretKind;
+        this.sourceLineKind = sourceLineKind;
+        this.summaryIndent = summaryIndent;
+        this.detailsIndent = detailsIndent;
+        this.sourceIndent = sourceIndent;
+        this.subdiagsIndent = subdiagsIndent;
+    }
+
+    @Override
+    public void run() {
         Context ctx = new Context();
         Options options = Options.instance(ctx);
         outputKind.init(options);
@@ -362,23 +396,10 @@
             d = new JCDiagnostic.MultilineDiagnostic(d, subdiags);
         }
         String diag = log.getDiagnosticFormatter().format(d, messages.getCurrentLocale());
-        checkOutput(diag,
-                outputKind,
-                errorKind,
-                multiKind,
-                multiPolicy,
-                posKind,
-                xdiagsSource,
-                xdiagsCompact,
-                caretKind,
-                sourceLineKind,
-                summaryIndent,
-                detailsIndent,
-                sourceIndent,
-                subdiagsIndent);
+        checkOutput(diag);
     }
 
-    void test() {
+    public static void main(String[] args) throws Exception {
         for (OutputKind outputKind : OutputKind.values()) {
             for (ErrorKind errKind : ErrorKind.values()) {
                 for (MultilineKind multiKind : MultilineKind.values()) {
@@ -392,7 +413,7 @@
                                                 for (IndentKind detailsIndent : IndentKind.values()) {
                                                     for (IndentKind sourceIndent : IndentKind.values()) {
                                                         for (IndentKind subdiagsIndent : IndentKind.values()) {
-                                                            exec(outputKind,
+                                                            pool.execute(new T6769027(outputKind,
                                                                 errKind,
                                                                 multiKind,
                                                                 multiPolicy,
@@ -404,7 +425,7 @@
                                                                 summaryIndent,
                                                                 detailsIndent,
                                                                 sourceIndent,
-                                                                subdiagsIndent);
+                                                                subdiagsIndent));
                                                         }
                                                     }
                                                 }
@@ -418,15 +439,11 @@
                 }
             }
         }
-        if (nerrors != 0)
-            throw new AssertionError(nerrors + " errors found");
+
+        checkAfterExec(false);
     }
 
-    void printInfo(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
-            MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
-            XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
-            IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
-            IndentKind subdiagsIndent, String errorLine) {
+    void printInfo(String msg, String errorLine) {
         String sep = "*********************************************************";
         String desc = "raw=" + outputKind + " pos=" + posKind + " key=" + errorKind.key() +
                 " multiline=" + multiKind +" multiPolicy=" + multiPolicy.value +
@@ -434,18 +451,14 @@
                 " caret=" + caretKind + " sourcePosition=" + sourceLineKind +
                 " summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent +
                 " sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent;
-        System.out.println(sep);
-        System.out.println(desc);
-        System.out.println(sep);
-        System.out.println(msg);
-        System.out.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
+        errWriter.println(sep);
+        errWriter.println(desc);
+        errWriter.println(sep);
+        errWriter.println(msg);
+        errWriter.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
     }
 
-    void checkOutput(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
-            MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
-            XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
-            IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
-            IndentKind subdiagsIndent) {
+    void checkOutput(String msg) {
         boolean shouldPrintSource = posKind == PositionKind.POS &&
                 xdiagsSource != XDiagsSource.NO_SOURCE &&
                 (xdiagsSource == XDiagsSource.SOURCE ||
@@ -453,7 +466,8 @@
         String errorLine = posKind.getOutput(outputKind) +
                 errorKind.getOutput(outputKind, summaryIndent, detailsIndent);
         if (xdiagsCompact != XDiagsCompact.COMPACT)
-            errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy, summaryIndent, detailsIndent, subdiagsIndent);
+            errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy,
+                    summaryIndent, detailsIndent, subdiagsIndent);
         String[] lines = errorLine.split("\n");
         if (xdiagsCompact == XDiagsCompact.COMPACT) {
             errorLine = lines[0];
@@ -474,26 +488,9 @@
         }
 
         if (!msg.equals(errorLine)) {
-            printInfo(msg,
-                    outputKind,
-                    errorKind,
-                    multiKind,
-                    multiPolicy,
-                    posKind,
-                    xdiagsSource,
-                    xdiagsCompact,
-                    caretKind,
-                    sourceLineKind,
-                    summaryIndent,
-                    detailsIndent,
-                    sourceIndent,
-                    subdiagsIndent,
-                    errorLine);
-            nerrors++;
+            printInfo(msg, errorLine);
+            errCount.incrementAndGet();
         }
     }
 
-    public static void main(String... args) throws Exception {
-        new T6769027().test();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/MethodParameters.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,344 @@
+/*
+ * 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 8004727
+ * @summary javac should generate method parameters correctly.
+ */
+// key: opt.arg.parameters
+import com.sun.tools.classfile.*;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.main.Main;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import java.io.*;
+import javax.lang.model.element.*;
+import java.util.*;
+
+public class MethodParameters {
+
+    static final String Foo_name = "Foo";
+    static final String Foo_contents =
+        "public class Foo {\n" +
+        "  Foo() {}\n" +
+        "  void foo0() {}\n" +
+        "  void foo2(int j, int k) {}\n" +
+        "}";
+    static final String Bar_name = "Bar";
+    static final String Bar_contents =
+        "public class Bar {\n" +
+        "  Bar(int i) {}" +
+        "  Foo foo() { return new Foo(); }\n" +
+        "}";
+    static final String Baz_name = "Baz";
+    static final String Baz_contents =
+        "public class Baz {\n" +
+        "  int baz;" +
+        "  Baz(int i) {}" +
+        "}";
+    static final String Qux_name = "Qux";
+    static final String Qux_contents =
+        "public class Qux extends Baz {\n" +
+        "  Qux(int i) { super(i); }" +
+        "}";
+    static final File classesdir = new File("methodparameters");
+
+    public static void main(String... args) throws Exception {
+        new MethodParameters().run();
+    }
+
+    void run() throws Exception {
+        classesdir.mkdir();
+        final File Foo_java =
+            writeFile(classesdir, Foo_name + ".java", Foo_contents);
+        final File Bar_java =
+            writeFile(classesdir, Bar_name + ".java", Bar_contents);
+        final File Baz_java =
+            writeFile(classesdir, Baz_name + ".java", Baz_contents);
+        System.err.println("Test compile with -parameter");
+        compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath());
+        // First test: make sure javac doesn't choke to death on
+        // MethodParameter attributes
+        System.err.println("Test compile with classfile containing MethodParameter attributes");
+        compile("-parameters", "-d", classesdir.getPath(),
+                "-cp", classesdir.getPath(), Bar_java.getPath());
+        System.err.println("Examine class foo");
+        checkFoo();
+        checkBar();
+        System.err.println("Test debug information conflict");
+        compile("-g", "-parameters", "-d", classesdir.getPath(),
+                "-cp", classesdir.getPath(), Baz_java.getPath());
+        System.err.println("Introducing debug information conflict");
+        Baz_java.delete();
+        modifyBaz(false);
+        System.err.println("Checking language model");
+        inspectBaz();
+        System.err.println("Permuting attributes");
+        modifyBaz(true);
+        System.err.println("Checking language model");
+        inspectBaz();
+
+        if(0 != errors)
+            throw new Exception("MethodParameters test failed with " +
+                                errors + " errors");
+    }
+
+    void inspectBaz() throws Exception {
+        final File Qux_java =
+            writeFile(classesdir, Qux_name + ".java", Qux_contents);
+        final String[] args = { "-XDsave-parameter-names", "-d",
+                                classesdir.getPath(),
+                                "-cp", classesdir.getPath(),
+                                Qux_java.getPath() };
+        final StringWriter sw = new StringWriter();
+        final PrintWriter pw = new PrintWriter(sw);
+
+        // We need to be able to crack open javac and look at its data
+        // structures.  We'll rig up a compiler instance, but keep its
+        // Context, thus allowing us to get at the ClassReader.
+        Context context = new Context();
+        Main comp =  new Main("javac", pw);
+        JavacFileManager.preRegister(context);
+
+        // Compile Qux, which uses Baz.
+        comp.compile(args, context);
+        pw.close();
+        final String out = sw.toString();
+        if (out.length() > 0)
+            System.err.println(out);
+
+        // Now get the class reader, construct a name for Baz, and load it.
+        com.sun.tools.javac.jvm.ClassReader cr =
+            com.sun.tools.javac.jvm.ClassReader.instance(context);
+        Name name = Names.instance(context).fromString(Baz_name);
+
+        // Now walk down the language model and check the name of the
+        // parameter.
+        final Element baz = cr.loadClass(name);
+        for (Element e : baz.getEnclosedElements()) {
+            if (e instanceof ExecutableElement) {
+                final ExecutableElement ee = (ExecutableElement) e;
+                final List<? extends VariableElement> params =
+                    ee.getParameters();
+                if (1 != params.size())
+                    throw new Exception("Classfile Baz badly formed: wrong number of methods");
+                final VariableElement param = params.get(0);
+                if (!param.getSimpleName().contentEquals("baz")) {
+                    errors++;
+                    System.err.println("javac did not correctly resolve the metadata conflict, parameter's name reads as " + param.getSimpleName());
+                } else
+                    System.err.println("javac did correctly resolve the metadata conflict");
+            }
+        }
+    }
+
+    void modifyBaz(boolean flip) throws Exception {
+        final File Baz_class = new File(classesdir, Baz_name + ".class");
+        final ClassFile baz = ClassFile.read(Baz_class);
+        final int ind = baz.constant_pool.getUTF8Index("baz");
+        MethodParameters_attribute mpattr = null;
+        int mpind = 0;
+        Code_attribute cattr = null;
+        int cind = 0;
+
+        // Find the indexes of the MethodParameters and the Code attributes
+        if (baz.methods.length != 1)
+            throw new Exception("Classfile Baz badly formed: wrong number of methods");
+        if (!baz.methods[0].getName(baz.constant_pool).equals("<init>"))
+            throw new Exception("Classfile Baz badly formed: method has name " +
+                                baz.methods[0].getName(baz.constant_pool));
+        for (int i = 0; i < baz.methods[0].attributes.attrs.length; i++) {
+            if (baz.methods[0].attributes.attrs[i] instanceof
+                MethodParameters_attribute) {
+                mpattr = (MethodParameters_attribute)
+                    baz.methods[0].attributes.attrs[i];
+                mpind = i;
+            } else if (baz.methods[0].attributes.attrs[i] instanceof
+                       Code_attribute) {
+                cattr = (Code_attribute) baz.methods[0].attributes.attrs[i];
+                cind = i;
+            }
+        }
+        if (null == mpattr)
+            throw new Exception("Classfile Baz badly formed: no method parameters info");
+        if (null == cattr)
+            throw new Exception("Classfile Baz badly formed: no local variable table");
+
+        int flags = mpattr.method_parameter_table[0].flags;
+
+        // Alter the MethodParameters attribute, changing the name of
+        // the parameter from i to baz.  This requires Black Magic...
+        //
+        // The (well-designed) classfile library (correctly) does not
+        // allow us to mess around with the attribute data structures,
+        // or arbitrarily generate new ones.
+        //
+        // Instead, we install a new subclass of Attribute that
+        // hijacks the Visitor pattern and outputs the sequence of
+        // bytes that we want.  This only works in this particular
+        // instance, because we know we'll only every see one kind of
+        // visitor.
+        //
+        // If anyone ever changes the makeup of the Baz class, or
+        // tries to install some kind of visitor that gets run prior
+        // to serialization, this will break.
+        baz.methods[0].attributes.attrs[mpind] =
+            new Attribute(mpattr.attribute_name_index,
+                          mpattr.attribute_length) {
+                public <R, D> R accept(Visitor<R, D> visitor, D data) {
+                    if (data instanceof ByteArrayOutputStream) {
+                        ByteArrayOutputStream out =
+                            (ByteArrayOutputStream) data;
+                        out.write(1);
+                        out.write((ind >> 8) & 0xff);
+                        out.write(ind & 0xff);
+                        out.write((flags >> 24) & 0xff);
+                        out.write((flags >> 16) & 0xff);
+                        out.write((flags >> 8) & 0xff);
+                        out.write(flags & 0xff);
+                    } else
+                        throw new RuntimeException("Output stream is of type " + data.getClass() + ", which is not handled by this test.  Update the test and it should work.");
+                    return null;
+                }
+            };
+
+        // Flip the code and method attributes.  This is for checking
+        // that order doesn't matter.
+        if (flip) {
+            baz.methods[0].attributes.attrs[mpind] = cattr;
+            baz.methods[0].attributes.attrs[cind] = mpattr;
+        }
+
+        new ClassWriter().write(baz, Baz_class);
+    }
+
+    // Run a bunch of structural tests on foo to make sure it looks right.
+    void checkFoo() throws Exception {
+        final File Foo_class = new File(classesdir, Foo_name + ".class");
+        final ClassFile foo = ClassFile.read(Foo_class);
+        for (int i = 0; i < foo.methods.length; i++) {
+            System.err.println("Examine method Foo." + foo.methods[i].getName(foo.constant_pool));
+            if (foo.methods[i].getName(foo.constant_pool).equals("foo2")) {
+                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
+                    if (foo.methods[i].attributes.attrs[j] instanceof
+                        MethodParameters_attribute) {
+                        MethodParameters_attribute mp =
+                            (MethodParameters_attribute)
+                            foo.methods[i].attributes.attrs[j];
+                        System.err.println("Foo.foo2 should have 2 parameters: j and k");
+                        if (2 != mp.method_parameter_table_length)
+                            error("expected 2 method parameter entries in foo2, got " +
+                                  mp.method_parameter_table_length);
+                        else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("j"))
+                            error("expected first parameter to foo2 to be \"j\", got \"" +
+                                  foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
+                                  "\" instead");
+                        else if  (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index).equals("k"))
+                            error("expected first parameter to foo2 to be \"k\", got \"" +
+                                  foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index) +
+                                  "\" instead");
+                    }
+            }
+            else if (foo.methods[i].getName(foo.constant_pool).equals("<init>")) {
+                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) {
+                    if (foo.methods[i].attributes.attrs[j] instanceof
+                        MethodParameters_attribute)
+                        error("Zero-argument constructor shouldn't have MethodParameters");
+                }
+            }
+            else if (foo.methods[i].getName(foo.constant_pool).equals("foo0")) {
+                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
+                    if (foo.methods[i].attributes.attrs[j] instanceof
+                        MethodParameters_attribute)
+                        error("Zero-argument method shouldn't have MethodParameters");
+            }
+            else
+                error("Unknown method " + foo.methods[i].getName(foo.constant_pool) + " showed up in class Foo");
+        }
+    }
+
+    // Run a bunch of structural tests on Bar to make sure it looks right.
+    void checkBar() throws Exception {
+        final File Bar_class = new File(classesdir, Bar_name + ".class");
+        final ClassFile bar = ClassFile.read(Bar_class);
+        for (int i = 0; i < bar.methods.length; i++) {
+            System.err.println("Examine method Bar." + bar.methods[i].getName(bar.constant_pool));
+            if (bar.methods[i].getName(bar.constant_pool).equals("<init>")) {
+                for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++)
+                    if (bar.methods[i].attributes.attrs[j] instanceof
+                        MethodParameters_attribute) {
+                        MethodParameters_attribute mp =
+                            (MethodParameters_attribute)
+                            bar.methods[i].attributes.attrs[j];
+                        System.err.println("Bar constructor should have 1 parameter: i");
+                        if (1 != mp.method_parameter_table_length)
+                            error("expected 1 method parameter entries in constructor, got " +
+                                  mp.method_parameter_table_length);
+                        else if (!bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("i"))
+                            error("expected first parameter to foo2 to be \"i\", got \"" +
+                                  bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
+                                  "\" instead");
+                    }
+            }
+            else if (bar.methods[i].getName(bar.constant_pool).equals("foo")) {
+                for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) {
+                    if (bar.methods[i].attributes.attrs[j] instanceof
+                        MethodParameters_attribute)
+                        error("Zero-argument constructor shouldn't have MethodParameters");
+                }
+            }
+        }
+    }
+
+    String compile(String... args) throws Exception {
+        System.err.println("compile: " + Arrays.asList(args));
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        int rc = com.sun.tools.javac.Main.compile(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (out.length() > 0)
+            System.err.println(out);
+        if (rc != 0)
+            error("compilation failed, rc=" + rc);
+        return out;
+    }
+
+    File writeFile(File dir, String path, String body) throws IOException {
+        File f = new File(dir, path);
+        f.getParentFile().mkdirs();
+        FileWriter out = new FileWriter(f);
+        out.write(body);
+        out.close();
+        return f;
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
--- a/langtools/test/tools/javac/T7093325.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/T7093325.java	Wed Jul 05 18:36:11 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
@@ -25,35 +25,29 @@
  * @test
  * @bug 7093325
  * @summary Redundant entry in bytecode exception table
+ * @library lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main T7093325
  */
 
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
 import com.sun.source.util.JavacTask;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.ConstantPool.*;
 import com.sun.tools.classfile.Method;
-import com.sun.tools.javac.api.JavacTool;
 
-import java.io.File;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-
-public class T7093325 {
-
-    /** global decls ***/
-
-    // Create a single file manager and reuse it for each compile to save time.
-    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-
-    //statistics
-    static int checkCount = 0;
+public class T7093325
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum StatementKind {
         THROW("throw new RuntimeException();", false, false),
@@ -89,7 +83,8 @@
             if (this.ordinal() == 0) {
                 return catchStr;
             } else {
-                return CatchArity.values()[this.ordinal() - 1].catchers() + catchStr;
+                return CatchArity.values()[this.ordinal() - 1].catchers() +
+                        catchStr;
             }
         }
     }
@@ -98,31 +93,36 @@
         for (CatchArity ca : CatchArity.values()) {
             for (StatementKind stmt0 : StatementKind.values()) {
                 if (ca.ordinal() == 0) {
-                    new T7093325(ca, stmt0).compileAndCheck();
+                    pool.execute(new T7093325(ca, stmt0));
                     continue;
                 }
                 for (StatementKind stmt1 : StatementKind.values()) {
                     if (ca.ordinal() == 1) {
-                        new T7093325(ca, stmt0, stmt1).compileAndCheck();
+                        pool.execute(new T7093325(ca, stmt0, stmt1));
                         continue;
                     }
                     for (StatementKind stmt2 : StatementKind.values()) {
                         if (ca.ordinal() == 2) {
-                            new T7093325(ca, stmt0, stmt1, stmt2).compileAndCheck();
+                            pool.execute(new T7093325(ca, stmt0, stmt1, stmt2));
                             continue;
                         }
                         for (StatementKind stmt3 : StatementKind.values()) {
                             if (ca.ordinal() == 3) {
-                                new T7093325(ca, stmt0, stmt1, stmt2, stmt3).compileAndCheck();
+                                pool.execute(
+                                    new T7093325(ca, stmt0, stmt1, stmt2, stmt3));
                                 continue;
                             }
                             for (StatementKind stmt4 : StatementKind.values()) {
                                 if (ca.ordinal() == 4) {
-                                    new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4).compileAndCheck();
+                                    pool.execute(
+                                        new T7093325(ca, stmt0, stmt1,
+                                                     stmt2, stmt3, stmt4));
                                     continue;
                                 }
                                 for (StatementKind stmt5 : StatementKind.values()) {
-                                    new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4, stmt5).compileAndCheck();
+                                    pool.execute(
+                                        new T7093325(ca, stmt0, stmt1, stmt2,
+                                                     stmt3, stmt4, stmt5));
                                 }
                             }
                         }
@@ -131,7 +131,7 @@
             }
         }
 
-        System.out.println("Total checks made: " + checkCount);
+        checkAfterExec();
     }
 
     /** instance decls **/
@@ -144,17 +144,18 @@
         this.stmts = stmts;
     }
 
-    void compileAndCheck() throws Exception {
+    @Override
+    public void run() {
+        int id = checkCount.incrementAndGet();
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavaSource source = new JavaSource();
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
+        JavaSource source = new JavaSource(id);
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), null,
                 null, null, Arrays.asList(source));
         ct.call();
-        verifyBytecode(source);
+        verifyBytecode(source, id);
     }
 
-    void verifyBytecode(JavaSource source) {
-        checkCount++;
+    void verifyBytecode(JavaSource source, int id) {
         boolean lastInlined = false;
         boolean hasCode = false;
         int gapsCount = 0;
@@ -172,11 +173,12 @@
 
         //System.out.printf("gaps %d \n %s \n", gapsCount, source.toString());
 
-        File compiledTest = new File("Test.class");
+        File compiledTest = new File(String.format("Test%s.class", id));
         try {
             ClassFile cf = ClassFile.read(compiledTest);
             if (cf == null) {
-                throw new Error("Classfile not found: " + compiledTest.getName());
+                throw new Error("Classfile not found: " +
+                                compiledTest.getName());
             }
 
             Method test_method = null;
@@ -232,7 +234,7 @@
                 "class C extends RuntimeException {} \n" +
                 "class D extends RuntimeException {} \n" +
                 "class E extends RuntimeException {} \n" +
-                "class Test {\n" +
+                "class Test#ID {\n" +
                 "   void test() {\n" +
                 "   try { #S0 } #C finally { System.out.println(); }\n" +
                 "   }\n" +
@@ -240,10 +242,12 @@
 
         String source;
 
-        public JavaSource() {
-            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+        public JavaSource(int id) {
+            super(URI.create(String.format("myfo:/Test%s.java", id)),
+                  JavaFileObject.Kind.SOURCE);
             source = source_template.replace("#C", ca.catchers());
             source = source.replace("#S0", stmts[0].stmt);
+            source = source.replace("#ID", String.valueOf(id));
             for (int i = 1; i < ca.ordinal() + 1; i++) {
                 source = source.replace("#S" + i, stmts[i].stmt);
             }
@@ -259,4 +263,5 @@
             return source;
         }
     }
+
 }
--- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java	Wed Jul 05 18:36:11 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
@@ -25,23 +25,26 @@
  * @test
  * @bug 8002099
  * @summary Add support for intersection types in cast expression
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main/timeout=360 IntersectionTypeCastTest
  */
 
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
 import javax.tools.ToolProvider;
 
-public class IntersectionTypeCastTest {
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
 
-    static int checkCount = 0;
+public class IntersectionTypeCastTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     interface Type {
         boolean subtypeOf(Type that);
@@ -59,7 +62,8 @@
         String typeStr;
         InterfaceKind superInterface;
 
-        InterfaceKind(String declStr, String typeStr, InterfaceKind superInterface) {
+        InterfaceKind(String declStr, String typeStr,
+                InterfaceKind superInterface) {
             this.declStr = declStr;
             this.typeStr = typeStr;
             this.superInterface = superInterface;
@@ -67,7 +71,8 @@
 
         @Override
         public boolean subtypeOf(Type that) {
-            return this == that || superInterface == that || that == ClassKind.OBJECT;
+            return this == that || superInterface == that ||
+                   that == ClassKind.OBJECT;
         }
 
         @Override
@@ -88,19 +93,27 @@
 
     enum ClassKind implements Type {
         OBJECT(null, "Object"),
-        CA("#M class CA implements A { }\n", "CA", InterfaceKind.A),
-        CB("#M class CB implements B { }\n", "CB", InterfaceKind.B),
-        CAB("#M class CAB implements A, B { }\n", "CAB", InterfaceKind.A, InterfaceKind.B),
-        CC("#M class CC implements C { }\n", "CC", InterfaceKind.C, InterfaceKind.A),
-        CCA("#M class CCA implements C, A { }\n", "CCA", InterfaceKind.C, InterfaceKind.A),
-        CCB("#M class CCB implements C, B { }\n", "CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
-        CCAB("#M class CCAB implements C, A, B { }\n", "CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
+        CA("#M class CA implements A { }\n", "CA",
+           InterfaceKind.A),
+        CB("#M class CB implements B { }\n", "CB",
+           InterfaceKind.B),
+        CAB("#M class CAB implements A, B { }\n", "CAB",
+            InterfaceKind.A, InterfaceKind.B),
+        CC("#M class CC implements C { }\n", "CC",
+           InterfaceKind.C, InterfaceKind.A),
+        CCA("#M class CCA implements C, A { }\n", "CCA",
+            InterfaceKind.C, InterfaceKind.A),
+        CCB("#M class CCB implements C, B { }\n", "CCB",
+            InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
+        CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
+             InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
 
         String declTemplate;
         String typeStr;
         List<InterfaceKind> superInterfaces;
 
-        ClassKind(String declTemplate, String typeStr, InterfaceKind... superInterfaces) {
+        ClassKind(String declTemplate, String typeStr,
+                InterfaceKind... superInterfaces) {
             this.declTemplate = declTemplate;
             this.typeStr = typeStr;
             this.superInterfaces = List.from(superInterfaces);
@@ -114,7 +127,8 @@
 
         @Override
         public boolean subtypeOf(Type that) {
-            return this == that || superInterfaces.contains(that) || that == OBJECT;
+            return this == that || superInterfaces.contains(that) ||
+                    that == OBJECT;
         }
 
         @Override
@@ -170,9 +184,11 @@
         }
 
         String getCast() {
-            String temp = kind.castTemplate.replaceAll("#C", types[0].asString());
+            String temp = kind.castTemplate.replaceAll("#C",
+                    types[0].asString());
             for (int i = 0; i < kind.interfaceBounds ; i++) {
-                temp = temp.replace(String.format("#I%d", i), types[i + 1].asString());
+                temp = temp.replace(String.format("#I%d", i),
+                                    types[i + 1].asString());
             }
             return temp;
         }
@@ -195,7 +211,8 @@
                             t1.subtypeOf(t2) ||
                             t2.subtypeOf(t1) ||
                             (t1.isInterface() && t2.isInterface()) || //side-cast (1)
-                            (mod == ModifierKind.NONE && (t1.isInterface() != t2.isInterface())); //side-cast (2)
+                            (mod == ModifierKind.NONE &&
+                            (t1.isInterface() != t2.isInterface())); //side-cast (2)
                     if (!compat) return false;
                 }
             }
@@ -204,18 +221,15 @@
     }
 
     public static void main(String... args) throws Exception {
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (ModifierKind mod : ModifierKind.values()) {
             for (CastInfo cast1 : allCastInfo()) {
                 for (CastInfo cast2 : allCastInfo()) {
-                    new IntersectionTypeCastTest(mod, cast1, cast2).run(comp, fm);
+                    pool.execute(
+                        new IntersectionTypeCastTest(mod, cast1, cast2));
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+        checkAfterExec();
     }
 
     static List<CastInfo> allCastInfo() {
@@ -235,11 +249,14 @@
                         } else {
                             for (InterfaceKind intf2 : InterfaceKind.values()) {
                                 if (kind.interfaceBounds == 2) {
-                                    buf.append(new CastInfo(kind, clazz, intf1, intf2));
+                                    buf.append(
+                                            new CastInfo(kind, clazz, intf1, intf2));
                                     continue;
                                 } else {
                                     for (InterfaceKind intf3 : InterfaceKind.values()) {
-                                        buf.append(new CastInfo(kind, clazz, intf1, intf2, intf3));
+                                        buf.append(
+                                                new CastInfo(kind, clazz, intf1,
+                                                             intf2, intf3));
                                         continue;
                                     }
                                 }
@@ -265,6 +282,22 @@
         this.diagChecker = new DiagnosticChecker();
     }
 
+    @Override
+    public void run() {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
+                Arrays.asList("-XDallowIntersectionTypes"),
+                null, Arrays.asList(source));
+        try {
+            ct.analyze();
+        } catch (Throwable ex) {
+            throw new AssertionError("Error thrown when compiling the following code:\n" +
+                    source.getCharContent(true));
+        }
+        check();
+    }
+
     class JavaSource extends SimpleJavaFileObject {
 
         String bodyTemplate = "class Test {\n" +
@@ -282,7 +315,8 @@
             for (InterfaceKind ik : InterfaceKind.values()) {
                 source += ik.declStr;
             }
-            source += bodyTemplate.replaceAll("#C1", cast1.getCast()).replaceAll("#C2", cast2.getCast());
+            source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
+                    replaceAll("#C2", cast2.getCast());
         }
 
         @Override
@@ -291,21 +325,11 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
-                Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
-        try {
-            ct.analyze();
-        } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
-        }
-        check();
-    }
+    void check() {
+        checkCount.incrementAndGet();
 
-    void check() {
-        checkCount++;
-
-        boolean errorExpected = cast1.hasDuplicateTypes() || cast2.hasDuplicateTypes();
+        boolean errorExpected = cast1.hasDuplicateTypes() ||
+                cast2.hasDuplicateTypes();
 
         errorExpected |= !cast2.compatibleWith(mod, cast1);
 
@@ -317,7 +341,8 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
 
@@ -327,4 +352,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java	Wed Jul 05 18:36:11 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
@@ -24,25 +24,25 @@
 /*
  * @test
  * @summary Automatic test for checking correctness of default super/this resolution
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main TestDefaultSuperCall
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+
+import com.sun.source.util.JavacTask;
 
-public class TestDefaultSuperCall {
-
-    static int checkCount = 0;
+public class TestDefaultSuperCall
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum InterfaceKind {
         DEFAULT("interface A extends B { default void m() { } }"),
@@ -212,7 +212,7 @@
         List<String> elementsWithMethod;
 
         Shape(ElementKind... elements) {
-            System.err.println("elements = " + Arrays.toString(elements));
+            errWriter.println("elements = " + Arrays.toString(elements));
             enclosingElements = new ArrayList<>();
             enclosingNames = new ArrayList<>();
             elementsWithMethod = new ArrayList<>();
@@ -231,28 +231,26 @@
                     elementsWithMethod.add(prevName);
                 }
                 String element = ek.templateDecl.replaceAll("#N", name);
-                shapeStr = shapeStr == null ? element : shapeStr.replaceAll("#B", element);
+                shapeStr = shapeStr ==
+                        null ? element : shapeStr.replaceAll("#B", element);
                 prevName = name;
             }
         }
 
         String getShape(QualifierKind qk, ExprKind ek) {
             String methName = ek == ExprKind.THIS ? "test" : "m";
-            String call = qk.getQualifier(this) + "." + ek.exprStr + "." + methName + "();";
+            String call = qk.getQualifier(this) + "." +
+                    ek.exprStr + "." + methName + "();";
             return shapeStr.replaceAll("#B", call);
         }
 
         String enclosingAt(int index) {
-            return index < enclosingNames.size() ? enclosingNames.get(index) : "BAD";
+            return index < enclosingNames.size() ?
+                    enclosingNames.get(index) : "BAD";
         }
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (InterfaceKind ik : InterfaceKind.values()) {
             for (PruneKind pk : PruneKind.values()) {
                 for (ElementKind ek1 : ElementKind.values()) {
@@ -264,10 +262,14 @@
                             for (ElementKind ek4 : ElementKind.values()) {
                                 if (!ek4.isAllowedEnclosing(ek3, false)) continue;
                                 for (ElementKind ek5 : ElementKind.values()) {
-                                    if (!ek5.isAllowedEnclosing(ek4, false) || ek5.isClassDecl()) continue;
+                                    if (!ek5.isAllowedEnclosing(ek4, false) ||
+                                            ek5.isClassDecl()) continue;
                                     for (QualifierKind qk : QualifierKind.values()) {
                                         for (ExprKind ek : ExprKind.values()) {
-                                            new TestDefaultSuperCall(ik, pk, new Shape(ek1, ek2, ek3, ek4, ek5), qk, ek).run(comp, fm);
+                                            pool.execute(
+                                                    new TestDefaultSuperCall(ik, pk,
+                                                    new Shape(ek1, ek2, ek3,
+                                                    ek4, ek5), qk, ek));
                                         }
                                     }
                                 }
@@ -277,7 +279,8 @@
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     InterfaceKind ik;
@@ -288,7 +291,8 @@
     JavaSource source;
     DiagnosticChecker diagChecker;
 
-    TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh, QualifierKind qk, ExprKind ek) {
+    TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
+            QualifierKind qk, ExprKind ek) {
         this.ik = ik;
         this.pk = pk;
         this.sh = sh;
@@ -321,13 +325,14 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
         try {
             ct.analyze();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
+            processException(ex);
+            return;
         }
         check();
     }
@@ -370,7 +375,8 @@
 
             int lastIdx = sh.enclosingElements.size() - 1;
             boolean found = lastIdx == -1 ? false :
-                    sh.enclosingElements.get(lastIdx).hasSuper() && qk.allowSuperCall(ik, pk);
+                    sh.enclosingElements.get(lastIdx).hasSuper() &&
+                    qk.allowSuperCall(ik, pk);
 
             errorExpected |= !found;
             if (!found) {
@@ -378,9 +384,10 @@
             }
         }
 
-        checkCount++;
+        checkCount.incrementAndGet();
         if (diagChecker.errorFound != errorExpected) {
-            throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) +
+            throw new AssertionError("Problem when compiling source:\n" +
+                    source.getCharContent(true) +
                     "\nenclosingElems: " + sh.enclosingElements +
                     "\nenclosingNames: " + sh.enclosingNames +
                     "\nelementsWithMethod: " + sh.elementsWithMethod +
@@ -392,15 +399,17 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
 
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
-                System.err.println(diagnostic.getMessage(Locale.getDefault()));
+                errWriter.println(diagnostic.getMessage(Locale.getDefault()));
                 errorFound = true;
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/failover/CheckAttributedTree.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -21,7 +21,15 @@
  * questions.
  */
 
-import com.sun.source.util.TaskEvent;
+/*
+ * @test
+ * @bug 6970584
+ * @summary assorted position errors in compiler syntax trees
+ * @library ../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main CheckAttributedTree -q -r -et ERRONEOUS .
+ */
+
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
@@ -34,6 +42,20 @@
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.Element;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
@@ -49,23 +71,14 @@
 import javax.swing.text.BadLocationException;
 import javax.swing.text.DefaultHighlighter;
 import javax.swing.text.Highlighter;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
 import javax.tools.Diagnostic;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
 
 import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.TaskEvent;
 import com.sun.source.util.JavacTask;
 import com.sun.source.util.TaskListener;
-import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.tree.EndPosTable;
@@ -76,11 +89,6 @@
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.util.Pair;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import javax.lang.model.element.Element;
-
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -95,13 +103,7 @@
  * covering any new language features that may be tested in this test suite.
  */
 
-/*
- * @test
- * @bug 6970584
- * @summary assorted position errors in compiler syntax trees
- * @run main CheckAttributedTree -q -r -et ERRONEOUS .
- */
-public class CheckAttributedTree {
+public class CheckAttributedTree extends JavacTestingAbstractThreadedTest {
     /**
      * Main entry point.
      * If test.src is set, program runs in jtreg mode, and will throw an Error
@@ -110,9 +112,10 @@
      * args is the value of ${test.src}. In jtreg mode, the -r option can be
      * given to change the default base directory to the root test directory.
      */
-    public static void main(String... args) {
+    public static void main(String... args) throws Exception {
         String testSrc = System.getProperty("test.src");
         File baseDir = (testSrc == null) ? null : new File(testSrc);
+        throwAssertionOnError = false;
         boolean ok = new CheckAttributedTree().run(baseDir, args);
         if (!ok) {
             if (testSrc != null)  // jtreg mode
@@ -130,7 +133,7 @@
      * @param args command line args
      * @return true if successful or in gui mode
      */
-    boolean run(File baseDir, String... args) {
+    boolean run(File baseDir, String... args) throws Exception {
         if (args.length == 0) {
             usage(System.out);
             return true;
@@ -145,8 +148,10 @@
                 gui = true;
             else if (arg.equals("-q"))
                 quiet = true;
-            else if (arg.equals("-v"))
+            else if (arg.equals("-v")) {
                 verbose = true;
+                printAll = true;
+            }
             else if (arg.equals("-t") && i + 1 < args.length)
                 tags.add(args[++i]);
             else if (arg.equals("-ef") && i + 1 < args.length)
@@ -179,12 +184,11 @@
                 error("File not found: " + file);
         }
 
-        if (fileCount != 1)
-            System.err.println(fileCount + " files read");
-        if (errors > 0)
-            System.err.println(errors + " errors");
+        if (fileCount.get() != 1)
+            errWriter.println(fileCount + " files read");
+        checkAfterExec(false);
 
-        return (gui || errors == 0);
+        return (gui || errCount.get() == 0);
     }
 
     /**
@@ -215,7 +219,7 @@
      * for java files.
      * @param file the file or directory to test
      */
-    void test(File file) {
+    void test(final File file) {
         if (excludeFiles.contains(file)) {
             if (!quiet)
                 error("File " + file + " excluded");
@@ -230,20 +234,24 @@
         }
 
         if (file.isFile() && file.getName().endsWith(".java")) {
-            try {
-                if (verbose)
-                    System.err.println(file);
-                fileCount++;
-                NPETester p = new NPETester();
-                p.test(read(file));
-            } catch (AttributionException e) {
-                if (!quiet) {
-                    error("Error attributing " + file + "\n" + e.getMessage());
+            pool.execute(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (verbose)
+                            errWriter.println(file);
+                        fileCount.incrementAndGet();
+                        NPETester p = new NPETester();
+                        p.test(read(file));
+                    } catch (AttributionException e) {
+                        if (!quiet) {
+                            error("Error attributing " + file + "\n" + e.getMessage());
+                        }
+                    } catch (IOException e) {
+                        error("Error reading " + file + ": " + e);
+                    }
                 }
-            } catch (IOException e) {
-                error("Error reading " + file + ": " + e);
-            }
-            return;
+            });
         }
 
         if (!quiet)
@@ -254,8 +262,6 @@
     StringWriter sw = new StringWriter();
     PrintWriter pw = new PrintWriter(sw);
     Reporter r = new Reporter(pw);
-    JavacTool tool = JavacTool.create();
-    StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null);
 
     /**
      * Read a file.
@@ -265,11 +271,10 @@
      * @throws TreePosTest.ParseException if any errors occur while parsing the file
      */
     List<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
-        JavacTool tool = JavacTool.create();
         r.errors = 0;
-        Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
+        Iterable<? extends JavaFileObject> files = fm.get().getJavaFileObjects(file);
         String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" };
-        JavacTask task = tool.getTask(pw, fm, r, Arrays.asList(opts), null, files);
+        JavacTask task = (JavacTask)comp.getTask(pw, fm.get(), r, Arrays.asList(opts), null, files);
         final List<Element> analyzedElems = new ArrayList<>();
         task.setTaskListener(new TaskListener() {
             public void started(TaskEvent e) {
@@ -308,13 +313,9 @@
      */
     void error(String msg) {
         System.err.println(msg);
-        errors++;
+        errCount.incrementAndGet();
     }
 
-    /** Number of files that have been analyzed. */
-    int fileCount;
-    /** Number of errors reported. */
-    int errors;
     /** Flag: don't report irrelevant files. */
     boolean quiet;
     /** Flag: show errors in GUI viewer. */
@@ -385,7 +386,8 @@
                         viewer = new Viewer();
                     viewer.addEntry(sourcefile, label, encl, self);
                 }
-                error(label + self.toString() + " encl: " + encl.toString() + " in file: " + sourcefile + "  " + self.tree);
+                error(label + self.toString() + " encl: " + encl.toString() +
+                        " in file: " + sourcefile + "  " + self.tree);
             }
         }
 
@@ -754,4 +756,8 @@
             final Info self;
         }
     }
+
+    /** Number of files that have been analyzed. */
+    static AtomicInteger fileCount = new AtomicInteger();
+
 }
--- a/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java	Wed Jul 05 18:36:11 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
@@ -25,21 +25,21 @@
  * @test
  * @bug 7046778
  * @summary Project Coin: problem with diamond and member inner classes
+ * @library ../../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main DiamondAndInnerClassTest
  */
 
 import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
 
-public class DiamondAndInnerClassTest {
-
-    static int checkCount = 0;
+public class DiamondAndInnerClassTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum TypeArgumentKind {
         NONE(""),
@@ -151,11 +151,6 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (InnerClassDeclArity innerClassDeclArity : InnerClassDeclArity.values()) {
             for (TypeQualifierArity declType : TypeQualifierArity.values()) {
                 if (!declType.matches(innerClassDeclArity)) continue;
@@ -168,53 +163,79 @@
                             //no diamond on decl site
                             if (taDecl1 == TypeArgumentKind.DIAMOND) continue;
                             for (TypeArgumentKind taSite1 : TypeArgumentKind.values()) {
-                                boolean isSiteRaw = taSite1 == TypeArgumentKind.NONE;
+                                boolean isSiteRaw =
+                                        taSite1 == TypeArgumentKind.NONE;
                                 //diamond only allowed on the last type qualifier
                                 if (taSite1 == TypeArgumentKind.DIAMOND &&
-                                        innerClassDeclArity != InnerClassDeclArity.ONE) continue;
+                                        innerClassDeclArity !=
+                                        InnerClassDeclArity.ONE)
+                                    continue;
                                 for (ArgumentKind arg1 : ArgumentKind.values()) {
                                     if (innerClassDeclArity == innerClassDeclArity.ONE) {
-                                        new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
-                                                argList, new TypeArgumentKind[] {taDecl1},
-                                                new TypeArgumentKind[] {taSite1}, new ArgumentKind[] {arg1}).run(comp, fm);
+                                        pool.execute(
+                                                new DiamondAndInnerClassTest(
+                                                innerClassDeclArity, declType,
+                                                newClassType, argList,
+                                                new TypeArgumentKind[] {taDecl1},
+                                                new TypeArgumentKind[] {taSite1},
+                                                new ArgumentKind[] {arg1}));
                                         continue;
                                     }
                                     for (TypeArgumentKind taDecl2 : TypeArgumentKind.values()) {
                                         //no rare types
-                                        if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE)) continue;
+                                        if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE))
+                                            continue;
                                         //no diamond on decl site
-                                        if (taDecl2 == TypeArgumentKind.DIAMOND) continue;
+                                        if (taDecl2 == TypeArgumentKind.DIAMOND)
+                                            continue;
                                         for (TypeArgumentKind taSite2 : TypeArgumentKind.values()) {
                                             //no rare types
-                                            if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE)) continue;
+                                            if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE))
+                                                continue;
                                             //diamond only allowed on the last type qualifier
                                             if (taSite2 == TypeArgumentKind.DIAMOND &&
-                                                    innerClassDeclArity != InnerClassDeclArity.TWO) continue;
+                                                    innerClassDeclArity != InnerClassDeclArity.TWO)
+                                                continue;
                                             for (ArgumentKind arg2 : ArgumentKind.values()) {
                                                 if (innerClassDeclArity == innerClassDeclArity.TWO) {
-                                                    new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
-                                                            argList, new TypeArgumentKind[] {taDecl1, taDecl2},
+                                                    pool.execute(
+                                                            new DiamondAndInnerClassTest(
+                                                            innerClassDeclArity,
+                                                            declType,
+                                                            newClassType,
+                                                            argList,
+                                                            new TypeArgumentKind[] {taDecl1, taDecl2},
                                                             new TypeArgumentKind[] {taSite1, taSite2},
-                                                            new ArgumentKind[] {arg1, arg2}).run(comp, fm);
+                                                            new ArgumentKind[] {arg1, arg2}));
                                                     continue;
                                                 }
                                                 for (TypeArgumentKind taDecl3 : TypeArgumentKind.values()) {
                                                     //no rare types
-                                                    if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE)) continue;
+                                                    if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE))
+                                                        continue;
                                                     //no diamond on decl site
-                                                    if (taDecl3 == TypeArgumentKind.DIAMOND) continue;
+                                                    if (taDecl3 == TypeArgumentKind.DIAMOND)
+                                                        continue;
                                                     for (TypeArgumentKind taSite3 : TypeArgumentKind.values()) {
                                                         //no rare types
-                                                        if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE)) continue;
+                                                        if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE))
+                                                            continue;
                                                         //diamond only allowed on the last type qualifier
                                                         if (taSite3 == TypeArgumentKind.DIAMOND &&
-                                                                innerClassDeclArity != InnerClassDeclArity.THREE) continue;
+                                                            innerClassDeclArity != InnerClassDeclArity.THREE)
+                                                            continue;
                                                         for (ArgumentKind arg3 : ArgumentKind.values()) {
-                                                            if (innerClassDeclArity == innerClassDeclArity.THREE) {
-                                                                new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
-                                                                        argList, new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3},
+                                                            if (innerClassDeclArity ==
+                                                                    innerClassDeclArity.THREE) {
+                                                                pool.execute(
+                                                                        new DiamondAndInnerClassTest(
+                                                                        innerClassDeclArity,
+                                                                        declType,
+                                                                        newClassType,
+                                                                        argList,
+                                                                        new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3},
                                                                         new TypeArgumentKind[] {taSite1, taSite2, taSite3},
-                                                                        new ArgumentKind[] {arg1, arg2, arg3}).run(comp, fm);
+                                                                        new ArgumentKind[] {arg1, arg2, arg3}));
                                                                 continue;
                                                             }
                                                         }
@@ -230,7 +251,8 @@
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     InnerClassDeclArity innerClassDeclArity;
@@ -244,9 +266,9 @@
     DiagnosticChecker diagChecker;
 
     DiamondAndInnerClassTest(InnerClassDeclArity innerClassDeclArity,
-            TypeQualifierArity declType, TypeQualifierArity siteType, ArgumentListArity argList,
-            TypeArgumentKind[] declTypeArgumentKinds, TypeArgumentKind[] siteTypeArgumentKinds,
-            ArgumentKind[] argumentKinds) {
+            TypeQualifierArity declType, TypeQualifierArity siteType,
+            ArgumentListArity argList, TypeArgumentKind[] declTypeArgumentKinds,
+            TypeArgumentKind[] siteTypeArgumentKinds, ArgumentKind[] argumentKinds) {
         this.innerClassDeclArity = innerClassDeclArity;
         this.declType = declType;
         this.siteType = siteType;
@@ -267,9 +289,9 @@
         public JavaSource() {
             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
             source = innerClassDeclArity.classDeclStr.replace("#B", bodyTemplate)
-                             .replace("#D", declType.getType(declTypeArgumentKinds))
-                             .replace("#S", siteType.getType(siteTypeArgumentKinds))
-                             .replace("#AL", argList.getArgs(argumentKinds));
+                    .replace("#D", declType.getType(declTypeArgumentKinds))
+                    .replace("#S", siteType.getType(siteTypeArgumentKinds))
+                    .replace("#AL", argList.getArgs(argumentKinds));
         }
 
         @Override
@@ -278,36 +300,39 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    @Override
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
         try {
             ct.analyze();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
+            throw new AssertionError("Error thrown when compiling the following code:\n" +
+                    source.getCharContent(true));
         }
         check();
     }
 
     void check() {
-        checkCount++;
+        checkCount.incrementAndGet();
 
         boolean errorExpected = false;
 
-        TypeArgumentKind[] expectedArgKinds = new TypeArgumentKind[innerClassDeclArity.n];
+        TypeArgumentKind[] expectedArgKinds =
+                new TypeArgumentKind[innerClassDeclArity.n];
 
         for (int i = 0 ; i < innerClassDeclArity.n ; i++) {
             if (!declTypeArgumentKinds[i].compatible(siteTypeArgumentKinds[i])) {
                 errorExpected = true;
                 break;
             }
-            expectedArgKinds[i] = siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND ?
+            expectedArgKinds[i] = siteTypeArgumentKinds[i] ==
+                    TypeArgumentKind.DIAMOND ?
                 declTypeArgumentKinds[i] : siteTypeArgumentKinds[i];
         }
 
         if (!errorExpected) {
             for (int i = 0 ; i < innerClassDeclArity.n ; i++) {
-                //System.out.println("check " + expectedArgKinds[i] + " against " + argumentKinds[i]);
                 if (!expectedArgKinds[i].compatible(argumentKinds[i])) {
                     errorExpected = true;
                     break;
@@ -323,7 +348,8 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
 
@@ -333,4 +359,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java	Wed Jul 05 18:36:11 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
@@ -24,22 +24,23 @@
 /*
  * @test
  * @bug 7062745
- * @summary  Regression: difference in overload resolution when two methods are maximally specific
+ * @summary  Regression: difference in overload resolution when two methods
+ * are maximally specific
+ * @library ../../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main GenericOverrideTest
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class GenericOverrideTest {
-
-    static int checkCount = 0;
+public class GenericOverrideTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum SignatureKind {
         NON_GENERIC(""),
@@ -126,11 +127,6 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (SignatureKind sig1 : SignatureKind.values()) {
             for (ReturnTypeKind rt1 : ReturnTypeKind.values()) {
                 for (TypeArgumentKind ta1 : TypeArgumentKind.values()) {
@@ -141,8 +137,12 @@
                                 if (!ta2.compatibleWith(sig2)) continue;
                                 for (ReturnTypeKind rt3 : ReturnTypeKind.values()) {
                                     for (TypeArgumentKind ta3 : TypeArgumentKind.values()) {
-                                        if (!ta3.compatibleWith(SignatureKind.NON_GENERIC)) continue;
-                                        new GenericOverrideTest(sig1, rt1, ta1, sig2, rt2, ta2, rt3, ta3).run(comp, fm);
+                                        if (!ta3.compatibleWith(SignatureKind.NON_GENERIC))
+                                            continue;
+                                        pool.execute(
+                                                new GenericOverrideTest(sig1,
+                                                rt1, ta1, sig2, rt2,
+                                                ta2, rt3, ta3));
                                     }
                                 }
                             }
@@ -151,7 +151,8 @@
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     SignatureKind sig1, sig2;
@@ -161,7 +162,8 @@
     DiagnosticChecker diagChecker;
 
     GenericOverrideTest(SignatureKind sig1, ReturnTypeKind rt1, TypeArgumentKind ta1,
-            SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2, ReturnTypeKind rt3, TypeArgumentKind ta3) {
+            SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2,
+            ReturnTypeKind rt3, TypeArgumentKind ta3) {
         this.sig1 = sig1;
         this.sig2 = sig2;
         this.rt1 = rt1;
@@ -204,19 +206,21 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    @Override
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
         try {
             ct.analyze();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
+            throw new AssertionError("Error thrown when compiling the following code:\n" +
+                    source.getCharContent(true));
         }
         check();
     }
 
     void check() {
-        checkCount++;
+        checkCount.incrementAndGet();
 
         boolean errorExpected = false;
         int mostSpecific = 0;
@@ -234,14 +238,17 @@
         //check that either TA1 <= TA2 or TA2 <= TA1 (unless most specific return found above is raw)
         if (!errorExpected) {
             if (ta1 != ta2) {
-                boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) || ta2.moreSpecificThan(ta1, true);
+                boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) ||
+                        ta2.moreSpecificThan(ta1, true);
                 if (!ta1.moreSpecificThan(ta2, useStrictCheck) &&
                         !ta2.moreSpecificThan(ta1, useStrictCheck)) {
                     errorExpected = true;
                 } else {
                     int mostSpecific2 = ta1.moreSpecificThan(ta2, useStrictCheck) ? 1 : 2;
                     if (mostSpecific != 0 && mostSpecific2 != mostSpecific) {
-                        errorExpected = mostSpecific == 1 ? ta1 != TypeArgumentKind.NONE : ta2 != TypeArgumentKind.NONE;
+                        errorExpected = mostSpecific == 1 ?
+                                ta1 != TypeArgumentKind.NONE :
+                                ta2 != TypeArgumentKind.NONE;
                     } else {
                         mostSpecific = mostSpecific2;
                     }
@@ -273,7 +280,8 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
 
@@ -283,4 +291,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java	Wed Jul 05 18:36:11 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
@@ -27,20 +27,24 @@
  * @summary Add lambda tests
  *  perform several automated checks in lambda conversion, esp. around accessibility
  * @author  Maurizio Cimadamore
+ * @library ../lib
+ * @build JavacTestingAbstractThreadedTest
  * @run main FunctionalInterfaceConversionTest
  */
 
-import com.sun.source.util.JavacTask;
+import java.io.IOException;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
 import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class FunctionalInterfaceConversionTest {
+public class FunctionalInterfaceConversionTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum PackageKind {
         NO_PKG(""),
@@ -139,8 +143,6 @@
     }
 
     public static void main(String[] args) throws Exception {
-        final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
         for (PackageKind samPkg : PackageKind.values()) {
             for (ModifierKind modKind : ModifierKind.values()) {
                 for (SamKind samKind : SamKind.values()) {
@@ -150,8 +152,11 @@
                                 for (TypeKind argType : TypeKind.values()) {
                                     for (TypeKind thrownType : TypeKind.values()) {
                                         for (ExprKind exprKind : ExprKind.values()) {
-                                            new FunctionalInterfaceConversionTest(samPkg, modKind, samKind,
-                                                    samMeth, clientMeth, retType, argType, thrownType, exprKind).test(comp, fm);
+                                            pool.execute(
+                                                new FunctionalInterfaceConversionTest(
+                                                    samPkg, modKind, samKind,
+                                                    samMeth, clientMeth, retType,
+                                                    argType, thrownType, exprKind));
                                         }
                                     }
                                 }
@@ -161,6 +166,8 @@
                 }
             }
         }
+
+        checkAfterExec(false);
     }
 
     PackageKind samPkg;
@@ -175,24 +182,30 @@
     DiagnosticChecker dc;
 
     SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") {
+        @Override
         public String toString() {
             return template.replaceAll("#P", samPkg.getPkgDecl()).
-                    replaceAll("#C", samKind.getSam(samMeth.getMethod(retType, argType, thrownType)));
+                    replaceAll("#C", samKind.getSam(
+                    samMeth.getMethod(retType, argType, thrownType)));
         }
     };
 
-    SourceFile pkgClassSourceFile = new SourceFile("PackageClass.java",
-                                                   "#P\n #M class PackageClass extends Exception { }") {
+    SourceFile pkgClassSourceFile =
+            new SourceFile("PackageClass.java",
+                           "#P\n #M class PackageClass extends Exception { }") {
+        @Override
         public String toString() {
             return template.replaceAll("#P", samPkg.getPkgDecl()).
                     replaceAll("#M", modKind.modifier_str);
         }
     };
 
-    SourceFile clientSourceFile = new SourceFile("Client.java",
-                                                 "#I\n abstract class Client { \n" +
-                                                 "  Sam s = #E;\n" +
-                                                 "  #M \n }") {
+    SourceFile clientSourceFile =
+            new SourceFile("Client.java",
+                           "#I\n abstract class Client { \n" +
+                           "  Sam s = #E;\n" +
+                           "  #M \n }") {
+        @Override
         public String toString() {
             return template.replaceAll("#I", samPkg.getImportStat())
                     .replaceAll("#E", exprKind.exprStr)
@@ -200,9 +213,10 @@
         }
     };
 
-    FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind, SamKind samKind,
-            MethodKind samMeth, MethodKind clientMeth, TypeKind retType, TypeKind argType,
-            TypeKind thrownType, ExprKind exprKind) {
+    FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind,
+            SamKind samKind, MethodKind samMeth, MethodKind clientMeth,
+            TypeKind retType, TypeKind argType, TypeKind thrownType,
+            ExprKind exprKind) {
         this.samPkg = samPkg;
         this.modKind = modKind;
         this.samKind = samKind;
@@ -215,12 +229,20 @@
         this.dc = new DiagnosticChecker();
     }
 
-    void test(JavaCompiler comp, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)comp.getTask(null, fm, dc,
-                null, null, Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
-        ct.analyze();
+    @Override
+    public void run() {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null,
+                Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
+        try {
+            ct.analyze();
+        } catch (IOException ex) {
+            throw new AssertionError("Test failing with cause", ex.getCause());
+        }
         if (dc.errorFound == checkSamConversion()) {
-            throw new AssertionError(samSourceFile + "\n\n" + pkgClassSourceFile + "\n\n" + clientSourceFile);
+            throw new AssertionError(samSourceFile + "\n\n" +
+                pkgClassSourceFile + "\n\n" + clientSourceFile);
         }
     }
 
@@ -264,13 +286,16 @@
             return toString();
         }
 
+        @Override
         public abstract String toString();
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound = false;
 
+        @Override
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
                 errorFound = true;
--- a/langtools/test/tools/javac/lambda/LambdaParserTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java	Wed Jul 05 18:36:11 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
@@ -27,21 +27,21 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  Add parser support for lambda expressions
+ * @library ../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main LambdaParserTest
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class LambdaParserTest {
-
-    static int checkCount = 0;
+public class LambdaParserTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum LambdaKind {
         NILARY_EXPR("()->x"),
@@ -173,25 +173,26 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (LambdaKind lk : LambdaKind.values()) {
             for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
-                if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) continue;
+                if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
+                    continue;
                 for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
-                    if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) continue;
+                    if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
+                        continue;
                     for (ModifierKind mk1 : ModifierKind.values()) {
-                        if (mk1 != ModifierKind.NONE && lk.isShort()) continue;
-                        if (lk.arity() < 1 && mk1 != ModifierKind.NONE) continue;
+                        if (mk1 != ModifierKind.NONE && lk.isShort())
+                            continue;
+                        if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
+                            continue;
                         for (ModifierKind mk2 : ModifierKind.values()) {
-                            if (lk.arity() < 2 && mk2 != ModifierKind.NONE) continue;
+                            if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
+                                continue;
                             for (SubExprKind sk : SubExprKind.values()) {
                                 for (ExprKind ek : ExprKind.values()) {
-                                    new LambdaParserTest(pk1, pk2, mk1, mk2, lk, sk, ek)
-                                            .run(comp, fm);
+                                    pool.execute(
+                                        new LambdaParserTest(pk1, pk2, mk1,
+                                                             mk2, lk, sk, ek));
                                 }
                             }
                         }
@@ -199,7 +200,8 @@
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     LambdaParameterKind pk1;
@@ -212,8 +214,9 @@
     JavaSource source;
     DiagnosticChecker diagChecker;
 
-    LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, ModifierKind mk1,
-            ModifierKind mk2, LambdaKind lk, SubExprKind sk, ExprKind ek) {
+    LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
+            ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
+            SubExprKind sk, ExprKind ek) {
         this.pk1 = pk1;
         this.pk2 = pk2;
         this.mk1 = mk1;
@@ -235,7 +238,8 @@
 
         public JavaSource() {
             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
-            source = template.replaceAll("#E", ek.expressionString(pk1, pk2, mk1, mk2, lk, sk));
+            source = template.replaceAll("#E",
+                    ek.expressionString(pk1, pk2, mk1, mk2, lk, sk));
         }
 
         @Override
@@ -244,19 +248,20 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
         try {
             ct.parse();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true));
+            processException(ex);
+            return;
         }
         check();
     }
 
     void check() {
-        checkCount++;
+        checkCount.incrementAndGet();
 
         boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
                 (lk.arity() > 1 && !mk2.compatibleWith(pk2));
@@ -275,7 +280,8 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
 
@@ -285,4 +291,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, 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
@@ -27,21 +27,21 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  Add parser support for method references
+ * @library ../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main MethodReferenceParserTest
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class MethodReferenceParserTest {
-
-    static int checkCount = 0;
+public class MethodReferenceParserTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum ReferenceKind {
         METHOD_REF("#Q::#Gm"),
@@ -88,7 +88,8 @@
             this.contextTemplate = contextTemplate;
         }
 
-        String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
+        String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk,
+                GenericKind gk, SubExprKind sk) {
             return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
         }
     }
@@ -165,25 +166,21 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (ReferenceKind rk : ReferenceKind.values()) {
             for (QualifierKind qk : QualifierKind.values()) {
                 for (GenericKind gk : GenericKind.values()) {
                     for (SubExprKind sk : SubExprKind.values()) {
                         for (ExprKind ek : ExprKind.values()) {
                             for (ContextKind ck : ContextKind.values()) {
-                                new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck).run(comp, fm);
+                                pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck));
                             }
                         }
                     }
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     ReferenceKind rk;
@@ -227,19 +224,21 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    @Override
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
         try {
             ct.parse();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true));
+            processException(ex);
+            return;
         }
         check();
     }
 
     void check() {
-        checkCount++;
+        checkCount.incrementAndGet();
 
         if (diagChecker.errorFound != rk.erroneous()) {
             throw new Error("invalid diagnostics for source:\n" +
@@ -259,4 +258,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/lambda/TargetType21.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/TargetType21.java	Wed Jul 05 18:36:11 2017 +0200
@@ -25,7 +25,7 @@
     <R,A> void call(SAM3<R,A> sam) { }
 
     void test() {
-        call(x -> { throw new Exception(); }); //ok - resolves to call(SAM1)
+        call(x -> { throw new Exception(); }); //ambiguous
         call(x -> { System.out.println(""); }); //ok - resolves to call(SAM2)
         call(x -> { return (Object) null; }); //error - call(SAM3) is not applicable because of cyclic inference
         call(x -> { return null; }); ////ok - resolves to call(SAM1)
--- a/langtools/test/tools/javac/lambda/TargetType21.out	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/TargetType21.out	Wed Jul 05 18:36:11 2017 +0200
@@ -1,3 +1,3 @@
 TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM2), TargetType21
-TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @755,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
+TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @737,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
 2 errors
--- a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java	Wed Jul 05 18:36:11 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
@@ -28,7 +28,9 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  Add back-end support for invokedynamic
- *
+ * @library ../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main TestInvokeDynamic
  */
 
 import com.sun.source.tree.MethodInvocationTree;
@@ -66,7 +68,6 @@
 
 import javax.tools.Diagnostic;
 import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
 import javax.tools.StandardJavaFileManager;
@@ -74,69 +75,80 @@
 
 import static com.sun.tools.javac.jvm.ClassFile.*;
 
-public class TestInvokeDynamic {
-
-    static int checkCount = 0;
+public class TestInvokeDynamic
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum StaticArgumentKind {
         STRING("Hello!", "String", "Ljava/lang/String;") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_String_info) &&
-                        ((CONSTANT_String_info)cpInfo).getString().equals(value);
+                        ((CONSTANT_String_info)cpInfo).getString()
+                        .equals(value);
             }
         },
         CLASS(null, "Class<?>", "Ljava/lang/Class;") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_Class_info) &&
-                        ((CONSTANT_Class_info)cpInfo).getName().equals("java/lang/String");
+                        ((CONSTANT_Class_info)cpInfo).getName()
+                        .equals("java/lang/String");
             }
         },
         INTEGER(1, "int", "I") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_Integer_info) &&
-                        ((CONSTANT_Integer_info)cpInfo).value == ((Integer)value).intValue();
+                        ((CONSTANT_Integer_info)cpInfo).value ==
+                        ((Integer)value).intValue();
             }
         },
         LONG(1L, "long", "J") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_Long_info) &&
-                        ((CONSTANT_Long_info)cpInfo).value == ((Long)value).longValue();
+                        ((CONSTANT_Long_info)cpInfo).value ==
+                        ((Long)value).longValue();
             }
         },
         FLOAT(1.0f, "float", "F") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_Float_info) &&
-                        ((CONSTANT_Float_info)cpInfo).value == ((Float)value).floatValue();
+                        ((CONSTANT_Float_info)cpInfo).value ==
+                        ((Float)value).floatValue();
             }
         },
         DOUBLE(1.0, "double","D") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_Double_info) &&
-                        ((CONSTANT_Double_info)cpInfo).value == ((Double)value).doubleValue();
+                        ((CONSTANT_Double_info)cpInfo).value ==
+                        ((Double)value).doubleValue();
             }
         },
         METHOD_HANDLE(null, "MethodHandle", "Ljava/lang/invoke/MethodHandle;") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
-                if (!(cpInfo instanceof CONSTANT_MethodHandle_info)) return false;
-                CONSTANT_MethodHandle_info handleInfo = (CONSTANT_MethodHandle_info)cpInfo;
+                if (!(cpInfo instanceof CONSTANT_MethodHandle_info))
+                    return false;
+                CONSTANT_MethodHandle_info handleInfo =
+                        (CONSTANT_MethodHandle_info)cpInfo;
                 return handleInfo.getCPRefInfo().getClassName().equals("Array") &&
                         handleInfo.reference_kind == RefKind.REF_invokeVirtual &&
-                        handleInfo.getCPRefInfo().getNameAndTypeInfo().getName().equals("clone") &&
-                        handleInfo.getCPRefInfo().getNameAndTypeInfo().getType().equals("()Ljava/lang/Object;");
+                        handleInfo.getCPRefInfo()
+                        .getNameAndTypeInfo().getName().equals("clone") &&
+                        handleInfo.getCPRefInfo()
+                        .getNameAndTypeInfo().getType().equals("()Ljava/lang/Object;");
             }
         },
         METHOD_TYPE(null, "MethodType", "Ljava/lang/invoke/MethodType;") {
             @Override
             boolean check(CPInfo cpInfo) throws Exception {
                 return (cpInfo instanceof CONSTANT_MethodType_info) &&
-                        ((CONSTANT_MethodType_info)cpInfo).getType().equals("()Ljava/lang/Object;");
+                        ((CONSTANT_MethodType_info)cpInfo).getType()
+                        .equals("()Ljava/lang/Object;");
             }
         };
 
@@ -144,7 +156,8 @@
         String sourceTypeStr;
         String bytecodeTypeStr;
 
-        StaticArgumentKind(Object value, String sourceTypeStr, String bytecodeTypeStr) {
+        StaticArgumentKind(Object value, String sourceTypeStr,
+                String bytecodeTypeStr) {
             this.value = value;
             this.sourceTypeStr = sourceTypeStr;
             this.bytecodeTypeStr = bytecodeTypeStr;
@@ -163,7 +176,8 @@
                 case CLASS:
                     return syms.stringType.tsym;
                 case METHOD_HANDLE:
-                    return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod, types);
+                    return new Pool.MethodHandle(REF_invokeVirtual,
+                            syms.arrayCloneMethod, types);
                 case METHOD_TYPE:
                     return syms.arrayCloneMethod.type;
                 default:
@@ -186,23 +200,21 @@
     }
 
     public static void main(String... args) throws Exception {
-        // Create a single file manager and compiler and reuse it for each compile to save time.
-        StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         for (StaticArgumentsArity arity : StaticArgumentsArity.values()) {
             if (arity.arity == 0) {
-                new TestInvokeDynamic(arity).compileAndCheck(fm, tool);
+                pool.execute(new TestInvokeDynamic(arity));
             } else {
                 for (StaticArgumentKind sak1 : StaticArgumentKind.values()) {
                     if (arity.arity == 1) {
-                        new TestInvokeDynamic(arity, sak1).compileAndCheck(fm, tool);
+                        pool.execute(new TestInvokeDynamic(arity, sak1));
                     } else {
                         for (StaticArgumentKind sak2 : StaticArgumentKind.values()) {
                             if (arity.arity == 2) {
-                                new TestInvokeDynamic(arity, sak1, sak2).compileAndCheck(fm, tool);
+                                pool.execute(new TestInvokeDynamic(arity, sak1, sak2));
                             } else {
                                 for (StaticArgumentKind sak3 : StaticArgumentKind.values()) {
-                                    new TestInvokeDynamic(arity, sak1, sak2, sak3).compileAndCheck(fm, tool);
+                                    pool.execute(
+                                        new TestInvokeDynamic(arity, sak1, sak2, sak3));
                                 }
                             }
                         }
@@ -211,23 +223,23 @@
             }
         }
 
-        System.out.println("Total checks made: " + checkCount);
+        checkAfterExec();
     }
 
     StaticArgumentsArity arity;
     StaticArgumentKind[] saks;
-    JavaSource source;
     DiagChecker dc;
 
     TestInvokeDynamic(StaticArgumentsArity arity, StaticArgumentKind... saks) {
         this.arity = arity;
         this.saks = saks;
-        source = new JavaSource();
         dc = new DiagChecker();
     }
 
-    void compileAndCheck(JavaFileManager fm, JavaCompiler tool) throws Exception {
-        JavacTaskImpl ct = (JavacTaskImpl)tool.getTask(null, fm, dc,
+    public void run() {
+        int id = checkCount.incrementAndGet();
+        JavaSource source = new JavaSource(id);
+        JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
                 null, null, Arrays.asList(source));
         Context context = ct.getContext();
         Symtab syms = Symtab.instance(context);
@@ -238,16 +250,20 @@
             ct.generate();
         } catch (Throwable t) {
             t.printStackTrace();
-            throw new AssertionError(String.format("Error thrown when compiling following code\n%s", source.source));
+            throw new AssertionError(
+                    String.format("Error thrown when compiling following code\n%s",
+                    source.source));
         }
         if (dc.diagFound) {
-            throw new AssertionError(String.format("Diags found when compiling following code\n%s\n\n%s", source.source, dc.printDiags()));
+            throw new AssertionError(
+                    String.format("Diags found when compiling following code\n%s\n\n%s",
+                    source.source, dc.printDiags()));
         }
-        verifyBytecode();
+        verifyBytecode(id);
     }
 
-    void verifyBytecode() {
-        File compiledTest = new File("Test.class");
+    void verifyBytecode(int id) {
+        File compiledTest = new File(String.format("Test%d.class", id));
         try {
             ClassFile cf = ClassFile.read(compiledTest);
             Method testMethod = null;
@@ -260,7 +276,8 @@
             if (testMethod == null) {
                 throw new Error("Test method not found");
             }
-            Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
+            Code_attribute ea =
+                    (Code_attribute)testMethod.attributes.get(Attribute.Code);
             if (testMethod == null) {
                 throw new Error("Code attribute for test() method not found");
             }
@@ -270,10 +287,12 @@
             for (Instruction i : ea.getInstructions()) {
                 if (i.getMnemonic().equals("invokedynamic")) {
                     CONSTANT_InvokeDynamic_info indyInfo =
-                            (CONSTANT_InvokeDynamic_info)cf.constant_pool.get(i.getShort(1));
+                         (CONSTANT_InvokeDynamic_info)cf
+                            .constant_pool.get(i.getShort(1));
                     bsmIdx = indyInfo.bootstrap_method_attr_index;
                     if (!indyInfo.getNameAndTypeInfo().getType().equals("()V")) {
-                        throw new AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
+                        throw new
+                            AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
                     }
                 }
             }
@@ -281,34 +300,41 @@
                 throw new Error("Missing invokedynamic in generated code");
             }
 
-            BootstrapMethods_attribute bsm_attr = (BootstrapMethods_attribute)cf.getAttribute(Attribute.BootstrapMethods);
+            BootstrapMethods_attribute bsm_attr =
+                    (BootstrapMethods_attribute)cf
+                    .getAttribute(Attribute.BootstrapMethods);
             if (bsm_attr.bootstrap_method_specifiers.length != 1) {
-                throw new Error("Bad number of method specifiers in BootstrapMethods attribute");
+                throw new Error("Bad number of method specifiers " +
+                        "in BootstrapMethods attribute");
             }
             BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec =
                     bsm_attr.bootstrap_method_specifiers[0];
 
             if (bsm_spec.bootstrap_arguments.length != arity.arity) {
-                throw new Error("Bad number of static invokedynamic args in BootstrapMethod attribute");
+                throw new Error("Bad number of static invokedynamic args " +
+                        "in BootstrapMethod attribute");
             }
 
             int count = 0;
             for (StaticArgumentKind sak : saks) {
-                if (!sak.check(cf.constant_pool.get(bsm_spec.bootstrap_arguments[count]))) {
+                if (!sak.check(cf.constant_pool
+                        .get(bsm_spec.bootstrap_arguments[count]))) {
                     throw new Error("Bad static argument value " + sak);
                 }
                 count++;
             }
 
             CONSTANT_MethodHandle_info bsm_handle =
-                    (CONSTANT_MethodHandle_info)cf.constant_pool.get(bsm_spec.bootstrap_method_ref);
+                    (CONSTANT_MethodHandle_info)cf.constant_pool
+                    .get(bsm_spec.bootstrap_method_ref);
 
             if (bsm_handle.reference_kind != RefKind.REF_invokeStatic) {
                 throw new Error("Bad kind on boostrap method handle");
             }
 
             CONSTANT_Methodref_info bsm_ref =
-                    (CONSTANT_Methodref_info)cf.constant_pool.get(bsm_handle.reference_index);
+                    (CONSTANT_Methodref_info)cf.constant_pool
+                    .get(bsm_handle.reference_index);
 
             if (!bsm_ref.getClassInfo().getName().equals("Bootstrap")) {
                 throw new Error("Bad owner of boostrap method");
@@ -318,8 +344,11 @@
                 throw new Error("Bad boostrap method name");
             }
 
-            if (!bsm_ref.getNameAndTypeInfo().getType().equals(asBSMSignatureString())) {
-                throw new Error("Bad boostrap method type" + bsm_ref.getNameAndTypeInfo().getType() + " " + asBSMSignatureString());
+            if (!bsm_ref.getNameAndTypeInfo()
+                    .getType().equals(asBSMSignatureString())) {
+                throw new Error("Bad boostrap method type" +
+                        bsm_ref.getNameAndTypeInfo().getType() + " " +
+                        asBSMSignatureString());
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -341,20 +370,22 @@
 
         static final String source_template = "import java.lang.invoke.*;\n" +
                 "class Bootstrap {\n" +
-                "   public static CallSite bsm(MethodHandles.Lookup lookup, String name, MethodType methodType #SARGS) {\n" +
+                "   public static CallSite bsm(MethodHandles.Lookup lookup, " +
+                "String name, MethodType methodType #SARGS) {\n" +
                 "       return null;\n" +
                 "   }\n" +
                 "}\n" +
-                "class Test {\n" +
+                "class Test#ID {\n" +
                 "   void m() { }\n" +
                 "   void test() { m(); }\n" +
                 "}";
 
         String source;
 
-        JavaSource() {
+        JavaSource(int id) {
             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
-            source = source_template.replace("#SARGS", asSignatureString());
+            source = source_template.replace("#SARGS", asSignatureString())
+                    .replace("#ID", String.valueOf(id));
         }
 
         @Override
@@ -411,7 +442,8 @@
                 for (int i = 0; i < arity.arity ; i++) {
                     staticArgs[i] = saks[i].getValue(syms, names, types);
                 }
-                ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
+                ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
+                        oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
             }
             return null;
         }
@@ -426,7 +458,8 @@
         }
     }
 
-    static class DiagChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean diagFound;
         ArrayList<String> diags = new ArrayList<>();
@@ -445,4 +478,5 @@
             return buf.toString();
         }
     }
+
 }
--- a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java	Wed Jul 05 18:36:11 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
@@ -26,24 +26,23 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  Automatic test for checking correctness of structural most specific test routine
- * @run main/timeout=360 StructuralMostSpecificTest
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main/timeout=600 StructuralMostSpecificTest
  */
 
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.api.ClientCodeWrapper;
-import com.sun.tools.javac.util.JCDiagnostic;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.ClientCodeWrapper;
+import com.sun.tools.javac.util.JCDiagnostic;
 
-public class StructuralMostSpecificTest {
-
-    static int checkCount = 0;
+public class StructuralMostSpecificTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum RetTypeKind {
         SHORT("short"),
@@ -105,7 +104,7 @@
         VOID("return;"),
         SHORT("return (short)0;"),
         INT("return 0;"),
-        INTEGER("return (Integer)null"),
+        INTEGER("return (Integer)null;"),
         NULL("return null;");
 
         String retStr;
@@ -142,11 +141,6 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (LambdaReturnKind lrk : LambdaReturnKind.values()) {
             for (RetTypeKind rk1 : RetTypeKind.values()) {
                 for (RetTypeKind rk2 : RetTypeKind.values()) {
@@ -154,7 +148,9 @@
                         for (ExceptionKind ek2 : ExceptionKind.values()) {
                             for (ArgTypeKind ak11 : ArgTypeKind.values()) {
                                 for (ArgTypeKind ak12 : ArgTypeKind.values()) {
-                                    new StructuralMostSpecificTest(lrk, rk1, rk2, ek1, ek2, ak11, ak12).run(comp, fm);
+                                    pool.execute(
+                                        new StructuralMostSpecificTest(lrk, rk1,
+                                            rk2, ek1, ek2, ak11, ak12));
                                 }
                             }
                         }
@@ -162,7 +158,8 @@
                 }
             }
         }
-        System.out.println("Total check executed: " + checkCount);
+
+        checkAfterExec();
     }
 
     LambdaReturnKind lrk;
@@ -218,20 +215,22 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"),
                 null, Arrays.asList(source));
         try {
             ct.analyze();
         } catch (Throwable ex) {
-            throw new AssertionError("Error thron when analyzing the following source:\n" + source.getCharContent(true));
+            throw new
+                AssertionError("Error thron when analyzing the following source:\n" +
+                    source.getCharContent(true));
         }
         check();
     }
 
     void check() {
-        checkCount++;
+        checkCount.incrementAndGet();
 
         if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
             return;
@@ -265,8 +264,8 @@
         }
     }
 
-    boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, ExceptionKind ek2,
-            ArgTypeKind ak1, ArgTypeKind ak2) {
+    boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1,
+            ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
         if (!rk1.moreSpecificThan(rk2))
             return false;
 
@@ -276,7 +275,8 @@
         return true;
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean ambiguityFound;
         String mostSpecificSig;
@@ -287,12 +287,16 @@
                         diagnostic.getCode().equals("compiler.err.ref.ambiguous")) {
                     ambiguityFound = true;
                 } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE &&
-                        diagnostic.getCode().equals("compiler.note.verbose.resolve.multi")) {
+                        diagnostic.getCode()
+                        .equals("compiler.note.verbose.resolve.multi")) {
                     ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
-                            (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
-                    JCDiagnostic.MultilineDiagnostic mdiag = (JCDiagnostic.MultilineDiagnostic)dsu.d;
+                        (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
+                    JCDiagnostic.MultilineDiagnostic mdiag =
+                        (JCDiagnostic.MultilineDiagnostic)dsu.d;
                     int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
-                    mostSpecificSig = ((JCDiagnostic)mdiag.getSubdiagnostics().get(mostSpecificIndex)).getArgs()[1].toString();
+                    mostSpecificSig =
+                        ((JCDiagnostic)mdiag.getSubdiagnostics()
+                            .get(mostSpecificIndex)).getArgs()[1].toString();
                 }
             } catch (RuntimeException t) {
                 t.printStackTrace();
@@ -300,4 +304,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java	Wed Jul 05 18:36:11 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
@@ -25,22 +25,24 @@
  * @test
  * @bug 8003280
  * @summary Add lambda tests
- *  perform automated checks in type inference in lambda expressions in different contexts
+ *  perform automated checks in type inference in lambda expressions
+ *  in different contexts
+ * @library ../../../lib
+ * @build JavacTestingAbstractThreadedTest
  * @compile  TypeInferenceComboTest.java
  * @run main/timeout=360 TypeInferenceComboTest
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-import javax.tools.StandardJavaFileManager;
+import com.sun.source.util.JavacTask;
 
-public class TypeInferenceComboTest {
+public class TypeInferenceComboTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
     enum Context {
         ASSIGNMENT("SAM#Type s = #LBody;"),
         METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
@@ -59,27 +61,35 @@
             this.context = context;
         }
 
-        String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
+        String getContext(SamKind sk, TypeKind samTargetT, Keyword kw,
+                TypeKind parameterT, TypeKind returnT, LambdaKind lk,
+                ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
             String result = context;
             if (sk == SamKind.GENERIC) {
                 if(this == Context.METHOD_CALL) {
-                    result = result.replaceAll("#GenericDeclKind", gdk.getGenericDeclKind(samTargetT));
+                    result = result.replaceAll("#GenericDeclKind",
+                            gdk.getGenericDeclKind(samTargetT));
                     if(gdk == GenericDeclKind.NON_GENERIC)
-                        result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
+                        result = result.replaceAll("#Type", "<" +
+                                samTargetT.typeStr + ">");
                     else //#GenericDeclKind is <T> or <T extends xxx>
                         result = result.replaceAll("#Type", "<T>");
                 }
                 else {
                     if(kw == Keyword.VOID)
-                        result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
+                        result = result.replaceAll("#Type", "<" +
+                                samTargetT.typeStr + ">");
                     else
-                        result = result.replaceAll("#Type", "<? " + kw.keyStr + " " + samTargetT.typeStr + ">");
+                        result = result.replaceAll("#Type", "<? " + kw.keyStr +
+                                " " + samTargetT.typeStr + ">");
                 }
             }
             else
-                result = result.replaceAll("#Type", "").replaceAll("#GenericDeclKind", "");
+                result = result.replaceAll("#Type", "").
+                        replaceAll("#GenericDeclKind", "");
 
-            return result.replaceAll("#LBody", lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
+            return result.replaceAll("#LBody",
+                    lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
         }
     }
 
@@ -94,8 +104,10 @@
         }
 
         String getSam(TypeKind parameterT, TypeKind returnT) {
-            return sam_str.replaceAll("#ARG", parameterT == TypeKind.VOID ? "" : parameterT.typeStr + " arg")
-                          .replaceAll("#R", returnT.typeStr);
+            return sam_str.replaceAll("#ARG",
+                    parameterT == TypeKind.VOID ?
+                        "" : parameterT.typeStr + " arg")
+                    .replaceAll("#R", returnT.typeStr);
         }
     }
 
@@ -104,7 +116,8 @@
         STRING("String", "\"hello\""),
         INTEGER("Integer", "1"),
         INT("int", "0"),
-        COMPARATOR("java.util.Comparator<String>", "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
+        COMPARATOR("java.util.Comparator<String>",
+                "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
         SAM("SAM2", "null"),
         GENERIC("T", null);
 
@@ -152,8 +165,10 @@
     }
 
     enum LambdaBody {
-        RETURN_VOID("() -> #RET"),//no parameters, return type is one of the TypeKind
-        RETURN_ARG("(#PK arg) -> #RET");//has parameters, return type is one of the TypeKind
+        //no parameters, return type is one of the TypeKind
+        RETURN_VOID("() -> #RET"),
+        //has parameters, return type is one of the TypeKind
+        RETURN_ARG("(#PK arg) -> #RET");
 
         String bodyStr;
 
@@ -161,12 +176,14 @@
             this.bodyStr = bodyStr;
         }
 
-        String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk) {
+        String getLambdaBody(TypeKind samTargetT, TypeKind parameterT,
+                TypeKind returnT, LambdaKind lk, ParameterKind pk) {
             String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
 
             if(result.contains("#TYPE")) {
                 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
-                    result = result.replaceAll("#TYPE", samTargetT == null? "": samTargetT.typeStr);
+                    result = result.replaceAll("#TYPE",
+                            samTargetT == null? "": samTargetT.typeStr);
                 else
                     result = result.replaceAll("#TYPE", parameterT.typeStr);
             }
@@ -174,9 +191,12 @@
                 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
             else {
                 if(returnT != TypeKind.GENERIC)
-                    return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", (returnT==TypeKind.VOID && lk==LambdaKind.EXPRESSION)? "{}" : returnT.valStr));
+                    return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL",
+                            (returnT==TypeKind.VOID &&
+                            lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr));
                 else
-                    return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", samTargetT.valStr));
+                    return result.replaceAll("#RET",
+                            lk.stmt.replaceAll("#VAL", samTargetT.valStr));
             }
         }
     }
@@ -203,8 +223,10 @@
         }
         else if (lambdaBodyType != LambdaBody.RETURN_ARG)
             return false;
-        if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
-            if ( parameterType == TypeKind.GENERIC && parameterKind == ParameterKind.IMPLICIT) //cyclic inference
+        if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
+                genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
+            if ( parameterType == TypeKind.GENERIC &&
+                    parameterKind == ParameterKind.IMPLICIT) //cyclic inference
                 return false;
         }
         return true;
@@ -216,7 +238,8 @@
                          "}\n";
     SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
         public String toString() {
-            return template.replaceAll("#C", samKind.getSam(parameterType, returnType));
+            return template.replaceAll("#C",
+                    samKind.getSam(parameterType, returnType));
         }
     };
 
@@ -225,22 +248,35 @@
                                                  "    #Context\n" +
                                                  "}") {
         public String toString() {
-            return template.replaceAll("#Context", context.getContext(samKind, samTargetType, keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType));
+            return template.replaceAll("#Context",
+                    context.getContext(samKind, samTargetType, keyword,
+                    parameterType, returnType, lambdaKind, parameterKind,
+                    genericDeclKind, lambdaBodyType));
         }
     };
 
-    void test() throws Exception {
-        System.out.println("kk:");
+    public void run() {
+        outWriter.println("kk:");
         StringBuilder sb = new StringBuilder("SamKind:");
-        sb.append(samKind).append(" SamTargetType:").append(samTargetType).append(" ParameterType:").append(parameterType)
-            .append(" ReturnType:").append(returnType).append(" Context:").append(context).append(" LambdaKind:").append(lambdaKind)
-            .append(" LambdaBodyType:").append(lambdaBodyType).append(" ParameterKind:").append(parameterKind).append(" Keyword:").append(keyword);
-        System.out.println(sb);
+        sb.append(samKind).append(" SamTargetType:")
+            .append(samTargetType).append(" ParameterType:").append(parameterType)
+            .append(" ReturnType:").append(returnType).append(" Context:")
+            .append(context).append(" LambdaKind:").append(lambdaKind)
+            .append(" LambdaBodyType:").append(lambdaBodyType)
+            .append(" ParameterKind:").append(parameterKind).append(" Keyword:")
+            .append(keyword);
+        outWriter.println(sb);
         DiagnosticChecker dc = new DiagnosticChecker();
-        JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
-        ct.analyze();
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc,
+                null, null, Arrays.asList(samSourceFile, clientSourceFile));
+        try {
+            ct.analyze();
+        } catch (Throwable t) {
+            processException(t);
+        }
         if (dc.errorFound == checkTypeInference()) {
-            throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile + "\n" + parameterType + " " + returnType);
+            throw new AssertionError(samSourceFile + "\n\n" +
+                    clientSourceFile + "\n" + parameterType + " " + returnType);
         }
     }
 
@@ -261,7 +297,8 @@
         public abstract String toString();
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound = false;
 
@@ -283,10 +320,9 @@
     Keyword keyword;
     GenericDeclKind genericDeclKind;
 
-    static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-    static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
-    TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
+    TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT,
+            TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk,
+            ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
         samKind = sk;
         samTargetType = samTargetT;
         parameterType = parameterT;
@@ -308,24 +344,14 @@
                             for(LambdaKind lambdaK : LambdaKind.values()) {
                                 for (SamKind sk : SamKind.values()) {
                                     if (sk == SamKind.NON_GENERIC) {
-                                        if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC )
-                                            new TypeInferenceComboTest(sk, null, parameterT, returnT, lb, ct, lambdaK, parameterK, null, null).test();
+                                        generateNonGenericSAM(ct, returnT,
+                                                parameterT, lb, parameterK,
+                                                lambdaK, sk);
                                     }
                                     else if (sk == SamKind.GENERIC) {
-                                        for (Keyword kw : Keyword.values()) {
-                                            for (TypeKind samTargetT : TypeKind.values()) {
-                                                if(samTargetT != TypeKind.VOID && samTargetT != TypeKind.INT && samTargetT != TypeKind.GENERIC
-                                                   && (parameterT == TypeKind.GENERIC || returnT == TypeKind.GENERIC)) {
-                                                    if(ct != Context.METHOD_CALL) {
-                                                        new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, null).test();
-                                                    }
-                                                    else {//Context.METHOD_CALL
-                                                        for (GenericDeclKind gdk : GenericDeclKind.values())
-                                                            new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, gdk).test();
-                                                    }
-                                                }
-                                            }
-                                        }
+                                        generateGenericSAM(ct, returnT,
+                                                parameterT, lb, parameterK,
+                                                lambdaK, sk);
                                     }
                                 }
                             }
@@ -334,5 +360,44 @@
                 }
             }
         }
+
+        checkAfterExec(false);
     }
+
+    static void generateNonGenericSAM(Context ct, TypeKind returnT,
+            TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
+            LambdaKind lambdaK, SamKind sk) {
+        if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) {
+            pool.execute(new TypeInferenceComboTest(sk, null, parameterT,
+                    returnT, lb, ct, lambdaK, parameterK, null, null));
+        }
+    }
+
+    static void generateGenericSAM(Context ct, TypeKind returnT,
+            TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
+            LambdaKind lambdaK, SamKind sk) {
+        for (Keyword kw : Keyword.values()) {
+            for (TypeKind samTargetT : TypeKind.values()) {
+                if(samTargetT != TypeKind.VOID &&
+                   samTargetT != TypeKind.INT &&
+                   samTargetT != TypeKind.GENERIC &&
+                   (parameterT == TypeKind.GENERIC ||
+                   returnT == TypeKind.GENERIC)) {
+                    if(ct != Context.METHOD_CALL) {
+                        pool.execute(
+                            new TypeInferenceComboTest(sk, samTargetT, parameterT,
+                                returnT, lb, ct, lambdaK, parameterK, kw, null));
+                    } else {//Context.METHOD_CALL
+                        for (GenericDeclKind gdk :
+                                GenericDeclKind.values())
+                            pool.execute(
+                                    new TypeInferenceComboTest(sk, samTargetT,
+                                    parameterT, returnT, lb, ct, lambdaK,
+                                    parameterK, kw, gdk));
+                    }
+                }
+            }
+         }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * An abstract superclass for threaded tests.
+ *
+ * This class will try to read a property named test.concurrency.
+ * The property can be provided by passing this option to jtreg:
+ * -javaoption:-Dtest.concurrency=#
+ *
+ * If the property is not set the class will use a heuristic to determine the
+ * maximum number of threads that can be fired to execute a given test.
+ */
+public abstract class JavacTestingAbstractThreadedTest {
+
+    protected static int getThreadPoolSize() {
+        Integer testConc = Integer.getInteger("test.concurrency");
+        if (testConc != null) return testConc;
+        int cores = Runtime.getRuntime().availableProcessors();
+        return Math.max(2, Math.min(8, cores / 2));
+    }
+
+    protected static void checkAfterExec() throws InterruptedException {
+        checkAfterExec(true);
+    };
+
+    protected static boolean throwAssertionOnError = true;
+
+    protected static boolean printAll = false;
+
+    protected static StringWriter errSWriter = new StringWriter();
+    protected static PrintWriter errWriter = new PrintWriter(errSWriter);
+
+    protected static StringWriter outSWriter = new StringWriter();
+    protected static PrintWriter outWriter = new PrintWriter(outSWriter);
+
+    protected static void checkAfterExec(boolean printCheckCount)
+            throws InterruptedException {
+        pool.shutdown();
+        while (!pool.isTerminated()) {
+            Thread.sleep(10);
+        }
+        if (errCount.get() > 0) {
+            if (throwAssertionOnError) {
+                closePrinters();
+                System.err.println(errSWriter.toString());
+                throw new AssertionError(
+                    String.format("%d errors found", errCount.get()));
+            } else {
+                System.err.println(
+                        String.format("%d errors found", errCount.get()));
+            }
+        } else if (printCheckCount) {
+            outWriter.println("Total check executed: " + checkCount.get());
+        }
+        closePrinters();
+        if (printAll) {
+            System.out.println(errSWriter.toString());
+            System.out.println(outSWriter.toString());
+        }
+    }
+
+    protected static void closePrinters() {
+        errWriter.close();
+        outWriter.close();
+    }
+
+    protected static void processException(Throwable t) {
+        errCount.incrementAndGet();
+        t.printStackTrace(errWriter);
+        pool.shutdown();
+    }
+
+    //number of checks executed
+    protected static AtomicInteger checkCount = new AtomicInteger();
+
+    //number of errors found while running combo tests
+    protected static AtomicInteger errCount = new AtomicInteger();
+
+    //create default shared JavaCompiler - reused across multiple compilations
+    protected static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+
+    protected static ExecutorService pool = Executors.newFixedThreadPool(
+            getThreadPoolSize(), new ThreadFactory() {
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(r);
+            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread t, Throwable e) {
+                    pool.shutdown();
+                    errCount.incrementAndGet();
+                    e.printStackTrace(System.err);
+                }
+            });
+            return t;
+        }
+    });
+
+    /*
+     * File manager is not thread-safe so it cannot be re-used across multiple
+     * threads. However we cache per-thread FileManager to avoid excessive
+     * object creation
+     */
+    protected static final ThreadLocal<StandardJavaFileManager> fm =
+        new ThreadLocal<StandardJavaFileManager>() {
+            @Override protected StandardJavaFileManager initialValue() {
+                return comp.getStandardFileManager(null, null, null);
+            }
+        };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/main/Option_J_At_Test.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,70 @@
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/*
+ * 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 8006037
+ * @summary extra space in javac -help for -J and @ options
+ */
+
+public class Option_J_At_Test {
+    public static void main(String... args) throws Exception {
+        new Option_J_At_Test().run();
+    }
+
+    void run() throws Exception {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        String[] help = { "-help" };
+        int rc = com.sun.tools.javac.Main.compile(help, pw);
+        pw.flush();
+        String out = sw.toString();
+        System.out.println(out);
+        check(out, "-J<flag>",     true);
+        check(out, "-J <flag>",    false);
+        check(out, "@<filename>",  true);
+        check(out, "@ <filename>", false);
+        if (errors > 0)
+            throw new Exception(errors + " errors found");
+    }
+
+    void check(String out, String text, boolean expect) {
+        if (out.contains(text) != expect) {
+            if (expect)
+                error("expected string not found: " + text);
+            else
+                error("unexpected string found: " + text);
+        }
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
--- a/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java	Wed Jul 05 18:36:11 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
@@ -25,19 +25,21 @@
  * @test
  * @bug 7030606
  * @summary Project-coin: multi-catch types should be pairwise disjoint
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main DisjunctiveTypeWellFormednessTest
  */
 
-import com.sun.source.util.JavacTask;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class DisjunctiveTypeWellFormednessTest {
+public class DisjunctiveTypeWellFormednessTest
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum Alternative {
         EXCEPTION("Exception"),
@@ -92,40 +94,37 @@
     }
 
     public static void main(String... args) throws Exception {
-
-        //create default shared JavaCompiler - reused across multiple compilations
-        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-
         for (Arity arity : Arity.values()) {
             for (Alternative a1 : Alternative.values()) {
                 if (arity == Arity.ONE) {
-                    new DisjunctiveTypeWellFormednessTest(a1).run(comp, fm);
+                    pool.execute(new DisjunctiveTypeWellFormednessTest(a1));
                     continue;
                 }
                 for (Alternative a2 : Alternative.values()) {
                     if (arity == Arity.TWO) {
-                        new DisjunctiveTypeWellFormednessTest(a1, a2).run(comp, fm);
+                        pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2));
                         continue;
                     }
                     for (Alternative a3 : Alternative.values()) {
                         if (arity == Arity.THREE) {
-                            new DisjunctiveTypeWellFormednessTest(a1, a2, a3).run(comp, fm);
+                            pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3));
                             continue;
                         }
                         for (Alternative a4 : Alternative.values()) {
                             if (arity == Arity.FOUR) {
-                                new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4).run(comp, fm);
+                                pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4));
                                 continue;
                             }
                             for (Alternative a5 : Alternative.values()) {
-                                new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5).run(comp, fm);
+                                pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5));
                             }
                         }
                     }
                 }
             }
         }
+
+        checkAfterExec(false);
     }
 
     Alternative[] alternatives;
@@ -159,10 +158,16 @@
         }
     }
 
-    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+    @Override
+    public void run() {
+        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
                 null, null, Arrays.asList(source));
-        ct.analyze();
+        try {
+            ct.analyze();
+        } catch (Throwable t) {
+            processException(t);
+            return;
+        }
         check();
     }
 
@@ -202,4 +207,5 @@
             }
         }
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/PrettySimpleStringTest.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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 8006033
+ * @summary bug in Pretty.toSimpleString
+ */
+
+import java.io.File;
+
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.Pretty;
+
+public class PrettySimpleStringTest {
+    public static void main(String... args) throws Exception {
+        new PrettySimpleStringTest().run();
+    }
+
+    void run() throws Exception {
+        File testSrc = new File(System.getProperty("test.src"));
+        File thisFile = new File(testSrc, getClass().getName() + ".java");
+        JavacTool tool = JavacTool.create();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        JavacTask task = tool.getTask(null, fm, null, null, null,
+                fm.getJavaFileObjects(thisFile));
+        Iterable<? extends CompilationUnitTree> trees = task.parse();
+        CompilationUnitTree thisTree = trees.iterator().next();
+
+        {   // test default
+            String thisSrc = Pretty.toSimpleString((JCTree) thisTree);
+            System.err.println(thisSrc);
+            String expect = "import jav[...]} } }";
+            if (!thisSrc.equals(expect)) {
+                throw new Exception("unexpected result");
+            }
+        }
+
+        {   // test explicit length
+            String thisSrc = Pretty.toSimpleString((JCTree) thisTree, 32);
+            System.err.println(thisSrc);
+            String expect = "import java.io.Fil[...]; } } } }";
+            if (!thisSrc.equals(expect)) {
+                throw new Exception("unexpected result");
+            }
+        }
+    }
+}
--- a/langtools/test/tools/javac/varargs/7042566/T7042566.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/varargs/7042566/T7042566.java	Wed Jul 05 18:36:11 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
@@ -25,8 +25,22 @@
  * @test
  * @bug 7042566
  * @summary Unambiguous varargs method calls flagged as ambiguous
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
+ * @run main T7042566
  */
 
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
 import com.sun.source.util.JavacTask;
 import com.sun.tools.classfile.Instruction;
 import com.sun.tools.classfile.Attribute;
@@ -34,44 +48,36 @@
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.ConstantPool.*;
 import com.sun.tools.classfile.Method;
-import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.util.List;
 
-import java.io.File;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Locale;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-public class T7042566 {
+public class T7042566
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     VarargsMethod m1;
     VarargsMethod m2;
     TypeConfiguration actuals;
 
-    T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf, TypeConfiguration actuals) {
+    T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf,
+            TypeConfiguration actuals) {
         this.m1 = new VarargsMethod(m1_conf);
         this.m2 = new VarargsMethod(m2_conf);
         this.actuals = actuals;
     }
 
-    void compileAndCheck() throws Exception {
+    @Override
+    public void run() {
+        int id = checkCount.incrementAndGet();
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavaSource source = new JavaSource();
+        JavaSource source = new JavaSource(id);
         ErrorChecker ec = new ErrorChecker();
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, ec,
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), ec,
                 null, null, Arrays.asList(source));
         ct.call();
-        check(source, ec);
+        check(source, ec, id);
     }
 
-    void check(JavaSource source, ErrorChecker ec) {
-        checkCount++;
+    void check(JavaSource source, ErrorChecker ec, int id) {
         boolean resolutionError = false;
         VarargsMethod selectedMethod = null;
 
@@ -99,13 +105,13 @@
                     "\nFound error: " + ec.errorFound +
                     "\nCompiler diagnostics:\n" + ec.printDiags());
         } else if (!resolutionError) {
-            verifyBytecode(selectedMethod, source);
+            verifyBytecode(selectedMethod, source, id);
         }
     }
 
-    void verifyBytecode(VarargsMethod selected, JavaSource source) {
-        bytecodeCheckCount++;
-        File compiledTest = new File("Test.class");
+    void verifyBytecode(VarargsMethod selected, JavaSource source, int id) {
+        bytecodeCheckCount.incrementAndGet();
+        File compiledTest = new File(String.format("Test%d.class", id));
         try {
             ClassFile cf = ClassFile.read(compiledTest);
             Method testMethod = null;
@@ -118,7 +124,8 @@
             if (testMethod == null) {
                 throw new Error("Test method not found");
             }
-            Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
+            Code_attribute ea =
+                (Code_attribute)testMethod.attributes.get(Attribute.Code);
             if (testMethod == null) {
                 throw new Error("Code attribute for test() method not found");
             }
@@ -127,11 +134,12 @@
                 if (i.getMnemonic().equals("invokevirtual")) {
                     int cp_entry = i.getUnsignedShort(1);
                     CONSTANT_Methodref_info methRef =
-                            (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
+                        (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
                     String type = methRef.getNameAndTypeInfo().getType();
                     String sig = selected.parameterTypes.bytecodeSigStr;
                     if (!type.contains(sig)) {
-                        throw new Error("Unexpected type method call: " + type + "" +
+                        throw new Error("Unexpected type method call: " +
+                                        type + "" +
                                         "\nfound: " + sig +
                                         "\n" + source.getCharContent(true));
                     }
@@ -146,7 +154,7 @@
 
     class JavaSource extends SimpleJavaFileObject {
 
-        static final String source_template = "class Test {\n" +
+        static final String source_template = "class Test#ID {\n" +
                 "   #V1\n" +
                 "   #V2\n" +
                 "   void test() { m(#E); }\n" +
@@ -154,11 +162,13 @@
 
         String source;
 
-        public JavaSource() {
-            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
-            source = source_template.replaceAll("#V1", m1.toString()).
-                    replaceAll("#V2", m2.toString()).
-                    replaceAll("#E", actuals.expressionListStr);
+        public JavaSource(int id) {
+            super(URI.create(String.format("myfo:/Test%d.java", id)),
+                    JavaFileObject.Kind.SOURCE);
+            source = source_template.replaceAll("#V1", m1.toString())
+                    .replaceAll("#V2", m2.toString())
+                    .replaceAll("#E", actuals.expressionListStr)
+                    .replaceAll("#ID", String.valueOf(id));
         }
 
         @Override
@@ -167,26 +177,17 @@
         }
     }
 
-    /** global decls ***/
-
-    // Create a single file manager and reuse it for each compile to save time.
-    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-
-    //statistics
-    static int checkCount = 0;
-    static int bytecodeCheckCount = 0;
-
     public static void main(String... args) throws Exception {
         for (TypeConfiguration tconf1 : TypeConfiguration.values()) {
             for (TypeConfiguration tconf2 : TypeConfiguration.values()) {
                 for (TypeConfiguration tconf3 : TypeConfiguration.values()) {
-                    new T7042566(tconf1, tconf2, tconf3).compileAndCheck();
+                    pool.execute(new T7042566(tconf1, tconf2, tconf3));
                 }
             }
         }
 
-        System.out.println("Total checks made: " + checkCount);
-        System.out.println("Bytecode checks made: " + bytecodeCheckCount);
+        outWriter.println("Bytecode checks made: " + bytecodeCheckCount.get());
+        checkAfterExec();
     }
 
     enum TypeKind {
@@ -326,14 +327,16 @@
         }
     }
 
-    static class ErrorChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class ErrorChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         boolean errorFound;
         List<String> errDiags = List.nil();
 
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
-                errDiags = errDiags.append(diagnostic.getMessage(Locale.getDefault()));
+                errDiags = errDiags
+                        .append(diagnostic.getMessage(Locale.getDefault()));
                 errorFound = true;
             }
         }
@@ -347,4 +350,8 @@
             return buf.toString();
         }
     }
+
+    //number of bytecode checks made while running combo tests
+    static AtomicInteger bytecodeCheckCount = new AtomicInteger();
+
 }
--- a/langtools/test/tools/javac/varargs/warning/Warn4.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/varargs/warning/Warn4.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,10 +26,11 @@
  * @bug     6945418 6993978
  * @summary Project Coin: Simplified Varargs Method Invocation
  * @author  mcimadamore
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
  * @run main Warn4
  */
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.api.JavacTool;
+
 import java.net.URI;
 import java.util.Arrays;
 import java.util.Set;
@@ -38,16 +39,19 @@
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
 import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class Warn4 {
+public class Warn4
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     final static Warning[] error = null;
     final static Warning[] none = new Warning[] {};
     final static Warning[] vararg = new Warning[] { Warning.VARARGS };
     final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED };
-    final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
+    final static Warning[] both =
+            new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
 
     enum Warning {
         UNCHECKED("generic.array.creation"),
@@ -59,8 +63,10 @@
             this.key = key;
         }
 
-        boolean isSuppressed(TrustMe trustMe, SourceLevel source, SuppressLevel suppressLevelClient,
-                SuppressLevel suppressLevelDecl, ModifierKind modKind) {
+        boolean isSuppressed(TrustMe trustMe, SourceLevel source,
+                SuppressLevel suppressLevelClient,
+                SuppressLevel suppressLevelDecl,
+                ModifierKind modKind) {
             switch(this) {
                 case VARARGS:
                     return source == SourceLevel.JDK_6 ||
@@ -68,7 +74,8 @@
                             trustMe == TrustMe.TRUST;
                 case UNCHECKED:
                     return suppressLevelClient == SuppressLevel.UNCHECKED ||
-                        (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE && source == SourceLevel.JDK_7);
+                        (trustMe == TrustMe.TRUST && modKind !=
+                            ModifierKind.NONE && source == SourceLevel.JDK_7);
             }
 
             SuppressLevel supLev = this == VARARGS ?
@@ -172,13 +179,13 @@
                             for (Signature vararg_meth : Signature.values()) {
                                 for (Signature client_meth : Signature.values()) {
                                     if (vararg_meth.isApplicableTo(client_meth)) {
-                                        test(sourceLevel,
+                                        pool.execute(new Warn4(sourceLevel,
                                                 trustMe,
                                                 suppressLevelClient,
                                                 suppressLevelDecl,
                                                 modKind,
                                                 vararg_meth,
-                                                client_meth);
+                                                client_meth));
                                     }
                                 }
                             }
@@ -187,63 +194,82 @@
                 }
             }
         }
+
+        checkAfterExec();
     }
 
-    // Create a single file manager and reuse it for each compile to save time.
-    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+    SourceLevel sourceLevel;
+    TrustMe trustMe;
+    SuppressLevel suppressLevelClient;
+    SuppressLevel suppressLevelDecl;
+    ModifierKind modKind;
+    Signature vararg_meth;
+    Signature client_meth;
+    DiagnosticChecker diagChecker;
 
-    static void test(SourceLevel sourceLevel, TrustMe trustMe, SuppressLevel suppressLevelClient,
-            SuppressLevel suppressLevelDecl, ModifierKind modKind, Signature vararg_meth, Signature client_meth) throws Exception {
+    public Warn4(SourceLevel sourceLevel, TrustMe trustMe,
+            SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
+            ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
+        this.sourceLevel = sourceLevel;
+        this.trustMe = trustMe;
+        this.suppressLevelClient = suppressLevelClient;
+        this.suppressLevelDecl = suppressLevelDecl;
+        this.modKind = modKind;
+        this.vararg_meth = vararg_meth;
+        this.client_meth = client_meth;
+        this.diagChecker = new DiagnosticChecker();
+    }
+
+    @Override
+    public void run() {
+        int id = checkCount.incrementAndGet();
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavaSource source = new JavaSource(trustMe, suppressLevelClient, suppressLevelDecl, modKind, vararg_meth, client_meth);
-        DiagnosticChecker dc = new DiagnosticChecker();
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
+        JavaSource source = new JavaSource(id);
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
                 Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey),
                 null, Arrays.asList(source));
-        ct.generate(); //to get mandatory notes
-        check(dc.warnings, sourceLevel,
-                new boolean[] {vararg_meth.giveUnchecked(client_meth),
-                               vararg_meth.giveVarargs(client_meth)},
-                source, trustMe, suppressLevelClient, suppressLevelDecl, modKind);
+        ct.call(); //to get mandatory notes
+        check(source, new boolean[] {vararg_meth.giveUnchecked(client_meth),
+                               vararg_meth.giveVarargs(client_meth)});
     }
 
-    static void check(Set<Warning> warnings, SourceLevel sourceLevel, boolean[] warnArr, JavaSource source,
-            TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl, ModifierKind modKind) {
+    void check(JavaSource source, boolean[] warnArr) {
         boolean badOutput = false;
         for (Warning wkind : Warning.values()) {
             boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
                     suppressLevelClient, suppressLevelDecl, modKind);
             System.out.println("SUPPRESSED = " + isSuppressed);
-            badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != warnings.contains(wkind);
+            badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) !=
+                    diagChecker.warnings.contains(wkind);
         }
         if (badOutput) {
             throw new Error("invalid diagnostics for source:\n" +
                     source.getCharContent(true) +
                     "\nExpected unchecked warning: " + warnArr[0] +
                     "\nExpected unsafe vararg warning: " + warnArr[1] +
-                    "\nWarnings: " + warnings +
+                    "\nWarnings: " + diagChecker.warnings +
                     "\nSource level: " + sourceLevel);
         }
     }
 
-    static class JavaSource extends SimpleJavaFileObject {
+    class JavaSource extends SimpleJavaFileObject {
 
         String source;
 
-        public JavaSource(TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
-                ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
-            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+        public JavaSource(int id) {
+            super(URI.create(String.format("myfo:/Test%d.java", id)),
+                    JavaFileObject.Kind.SOURCE);
             String meth1 = vararg_meth.template.replace("#arity", "...");
             meth1 = meth1.replace("#name", "m");
             meth1 = meth1.replace("#body", "");
-            meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() + modKind.mod + meth1;
+            meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() +
+                    modKind.mod + meth1;
             String meth2 = client_meth.template.replace("#arity", "");
             meth2 = meth2.replace("#name", "test");
             meth2 = meth2.replace("#body", "m(arg);");
             meth2 = suppressLevelClient.getSuppressAnno() + meth2;
-            source = "import java.util.List;\n" +
-                     "class Test {\n" + meth1 +
-                     "\n" + meth2 + "\n}\n";
+            source = String.format("import java.util.List;\n" +
+                     "class Test%s {\n %s \n %s \n } \n", id, meth1, meth2);
         }
 
         @Override
@@ -252,7 +278,8 @@
         }
     }
 
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    static class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         Set<Warning> warnings = new HashSet<>();
 
@@ -267,4 +294,5 @@
             }
         }
     }
+
 }
--- a/langtools/test/tools/javac/varargs/warning/Warn5.java	Wed Jul 05 18:35:27 2017 +0200
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java	Wed Jul 05 18:36:11 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,10 +26,10 @@
  * @bug     6993978 7097436
  * @summary Project Coin: Annotation to reduce varargs warnings
  * @author  mcimadamore
+ * @library ../../lib
+ * @build JavacTestingAbstractThreadedTest
  * @run main Warn5
  */
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.api.JavacTool;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.EnumSet;
@@ -37,10 +37,12 @@
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
 import javax.tools.ToolProvider;
+import com.sun.source.util.JavacTask;
 
-public class Warn5 {
+public class Warn5
+    extends JavacTestingAbstractThreadedTest
+    implements Runnable {
 
     enum XlintOption {
         NONE("none"),
@@ -161,9 +163,6 @@
         REDUNDANT_SAFEVARARGS;
     }
 
-    // Create a single file manager and reuse it for each compile to save time.
-    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-
     public static void main(String... args) throws Exception {
         for (SourceLevel sourceLevel : SourceLevel.values()) {
             for (XlintOption xlint : XlintOption.values()) {
@@ -173,14 +172,9 @@
                             for (MethodKind methKind : MethodKind.values()) {
                                 for (SignatureKind sig : SignatureKind.values()) {
                                     for (BodyKind body : BodyKind.values()) {
-                                        new Warn5(sourceLevel,
-                                                xlint,
-                                                trustMe,
-                                                suppressLevel,
-                                                modKind,
-                                                methKind,
-                                                sig,
-                                                body).test();
+                                        pool.execute(new Warn5(sourceLevel,
+                                                xlint, trustMe, suppressLevel,
+                                                modKind, methKind, sig, body));
                                     }
                                 }
                             }
@@ -189,6 +183,8 @@
                 }
             }
         }
+
+        checkAfterExec(false);
     }
 
     final SourceLevel sourceLevel;
@@ -202,7 +198,9 @@
     final JavaSource source;
     final DiagnosticChecker dc;
 
-    public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) {
+    public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe,
+            SuppressLevel suppressLevel, ModifierKind modKind,
+            MethodKind methKind, SignatureKind sig, BodyKind body) {
         this.sourceLevel = sourceLevel;
         this.xlint = xlint;
         this.trustMe = trustMe;
@@ -215,24 +213,36 @@
         this.dc = new DiagnosticChecker();
     }
 
-    void test() throws Exception {
+    @Override
+    public void run() {
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
-                Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
-        ct.analyze();
+        JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc,
+                Arrays.asList(xlint.getXlintOption(),
+                    "-source", sourceLevel.sourceKey),
+                null, Arrays.asList(source));
+        try {
+            ct.analyze();
+        } catch (Throwable t) {
+            processException(t);
+        }
         check();
     }
 
     void check() {
 
-        EnumSet<WarningKind> expectedWarnings = EnumSet.noneOf(WarningKind.class);
+        EnumSet<WarningKind> expectedWarnings =
+                EnumSet.noneOf(WarningKind.class);
 
         if (sourceLevel == SourceLevel.JDK_7 &&
                 trustMe == TrustMe.TRUST &&
                 suppressLevel != SuppressLevel.VARARGS &&
                 xlint != XlintOption.NONE &&
-                sig.isVarargs && !sig.isReifiableArg && body.hasAliasing &&
-                (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE))) {
+                sig.isVarargs &&
+                !sig.isReifiableArg &&
+                body.hasAliasing &&
+                (methKind == MethodKind.CONSTRUCTOR ||
+                (methKind == MethodKind.METHOD &&
+                modKind != ModifierKind.NONE))) {
             expectedWarnings.add(WarningKind.UNSAFE_BODY);
         }
 
@@ -247,7 +257,8 @@
         if (sourceLevel == SourceLevel.JDK_7 &&
                 trustMe == TrustMe.TRUST &&
                 (!sig.isVarargs ||
-                (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD))) {
+                (modKind == ModifierKind.NONE &&
+                methKind == MethodKind.METHOD))) {
             expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
         }
 
@@ -255,7 +266,8 @@
                 trustMe == TrustMe.TRUST &&
                 xlint != XlintOption.NONE &&
                 suppressLevel != SuppressLevel.VARARGS &&
-                (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
+                (modKind != ModifierKind.NONE ||
+                methKind == MethodKind.CONSTRUCTOR) &&
                 sig.isVarargs &&
                 sig.isReifiableArg) {
             expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
@@ -297,19 +309,23 @@
         }
     }
 
-    class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+    class DiagnosticChecker
+        implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
 
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
-                    if (diagnostic.getCode().contains("unsafe.use.varargs.param")) {
+                    if (diagnostic.getCode().
+                            contains("unsafe.use.varargs.param")) {
                         setWarning(WarningKind.UNSAFE_BODY);
-                    } else if (diagnostic.getCode().contains("redundant.trustme")) {
+                    } else if (diagnostic.getCode().
+                            contains("redundant.trustme")) {
                         setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
                     }
             } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
-                    diagnostic.getCode().contains("varargs.non.reifiable.type")) {
+                    diagnostic.getCode().
+                        contains("varargs.non.reifiable.type")) {
                 setWarning(WarningKind.UNSAFE_DECL);
             } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
                     diagnostic.getCode().contains("invalid.trustme")) {
@@ -319,7 +335,8 @@
 
         void setWarning(WarningKind wk) {
             if (!warnings.add(wk)) {
-                throw new AssertionError("Duplicate warning of kind " + wk + " in source:\n" + source);
+                throw new AssertionError("Duplicate warning of kind " +
+                        wk + " in source:\n" + source);
             }
         }
 
@@ -327,4 +344,5 @@
             return warnings.contains(wk);
         }
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/MaxWarns.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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 8005644
+ * @summary set default max errs and max warns
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class MaxWarns {
+    public static void main(String... args) throws Exception {
+        new MaxWarns().run();
+    }
+
+    void run() throws Exception {
+        final int defaultMaxWarns = 100;
+        final int genWarns = 150;
+        File f = genSrc(genWarns);
+        String out = javadoc(f);
+        check(out, defaultMaxWarns);
+
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    File genSrc(int count) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        sb.append("package p;\n")
+            .append("public class C {\n")
+            .append("    /**\n");
+        for (int i = 0; i < count; i++)
+            sb.append("     * @param i").append(i).append(" does not exist!\n");
+        sb.append("     */\n")
+            .append("    public void m() { }\n")
+            .append("}\n");
+        File srcDir = new File("src");
+        srcDir.mkdirs();
+        File f = new File(srcDir, "C.java");
+        try (FileWriter fw = new FileWriter(f)) {
+            fw.write(sb.toString());
+        }
+        return f;
+    }
+
+    String javadoc(File f) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        String[] args = { "-d", "api", f.getPath() };
+        int rc = com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw,
+                com.sun.tools.doclets.standard.Standard.class.getName(), args);
+        pw.flush();
+        return sw.toString();
+    }
+
+    void check(String out, int count) {
+        System.err.println(out);
+        Pattern warn = Pattern.compile("warning - @param argument \"i[0-9]+\" is not a parameter name");
+        Matcher m = warn.matcher(out);
+        int n = 0;
+        for (int start = 0; m.find(start); start = m.start() + 1) {
+            n++;
+        }
+        if (n != count)
+            error("unexpected number of warnings reported: " + n + "; expected: " + count);
+
+        Pattern warnCount = Pattern.compile("(?ms).*^([0-9]+) warnings$.*");
+        m = warnCount.matcher(out);
+        if (m.matches()) {
+            n = Integer.parseInt(m.group(1));
+            if (n != count)
+                error("unexpected number of warnings reported: " + n + "; expected: " + count);
+        } else
+            error("total count not found");
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/MethodParameters.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2010, 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 8004727 8005647
+ * @summary javac should generate method parameters correctly.
+ */
+
+import java.io.*;
+import java.util.*;
+
+public class MethodParameters {
+
+    static final String Foo_name = "Foo";
+    static final String Foo_contents =
+        ("public class Foo {\n" +
+         "  Foo() {}\n" +
+         "  Foo(int i) {}\n" +
+         "  void foo0() {}\n" +
+         "  void foo2(int j, int k) {}\n" +
+         "}").replaceAll(" +", " ");
+    static final String Init0_expected =
+        ("  Foo();\n" +
+         "    flags: \n" +
+         "    Code:\n" +
+         "      stack=1, locals=1, args_size=1\n" +
+         "         0: aload_0       \n" +
+         "         1: invokespecial #1                  // Method java/lang/Object.\"<init>\":()V\n" +
+         "         4: return        \n" +
+         "      LineNumberTable:\n" +
+         "        line 2: 0").replaceAll(" +", " ");
+    static final String Init1_expected =
+        ("  Foo(int);\n" +
+         "    flags: \n" +
+         "    Code:\n" +
+         "      stack=1, locals=2, args_size=2\n" +
+         "         0: aload_0       \n" +
+         "         1: invokespecial #1                  // Method java/lang/Object.\"<init>\":()V\n" +
+         "         4: return        \n" +
+         "      LineNumberTable:\n" +
+         "        line 3: 0\n" +
+         "    MethodParameters:\n" +
+         "      Name                                Flags\n" +
+         "      i").replaceAll(" +", " ");
+    static final String foo0_expected =
+        ("  void foo0();\n" +
+         "    flags: \n" +
+         "    Code:\n" +
+         "      stack=0, locals=1, args_size=1\n" +
+         "         0: return        \n" +
+         "      LineNumberTable:\n" +
+         "        line 4: 0").replaceAll(" +", " ");
+    static final String foo2_expected =
+        ("  void foo2(int, int);\n" +
+         "    flags: \n" +
+         "    Code:\n" +
+         "      stack=0, locals=3, args_size=3\n" +
+         "         0: return        \n" +
+         "      LineNumberTable:\n" +
+         "        line 5: 0\n" +
+         "    MethodParameters:\n" +
+         "      Name                                Flags\n" +
+         "      j                              \n" +
+         "      k").replaceAll(" +", " ");
+
+    static final File classesdir = new File("methodparameters");
+    static final String separator = System.getProperty("line.separator");
+
+    public static void main(String... args) throws Exception {
+        new MethodParameters().run();
+    }
+
+    void run() throws Exception {
+        classesdir.mkdir();
+        final File Foo_java =
+            writeFile(classesdir, Foo_name + ".java", Foo_contents);
+        compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath());
+        System.out.println("Run javap");
+        String output =
+            javap("-c", "-verbose", "-classpath",
+                  classesdir.getPath(), Foo_name);
+        String normalized =
+            output.replaceAll(separator, "\n").replaceAll(" +", " ");
+
+        if (!normalized.contains(Init0_expected))
+            error("Bad output for zero-parameter constructor.  Expected\n" +
+                  Init0_expected + "\n" + "but got\n" + normalized);
+        if (!normalized.contains(Init1_expected))
+           error("Bad output for one-parameter constructor.  Expected\n" +
+                 Init1_expected + "\n" + "but got\n" + normalized);
+        if (!normalized.contains(foo0_expected))
+           error("Bad output for zero-parameter method.  Expected\n" +
+                 foo0_expected + "\n" + "but got\n" + normalized);
+        if (!normalized.contains(foo2_expected))
+           error("Bad output for two-parameter method  Expected\n" +
+                 foo2_expected + "\n" + "but got\n" + normalized);
+
+        if (0 != errors)
+            throw new Exception("MethodParameters test failed with " +
+                                errors + " errors");
+    }
+
+    String javap(String... args) {
+        StringWriter sw = new StringWriter();
+        PrintWriter out = new PrintWriter(sw);
+        //sun.tools.javap.Main.entry(args);
+        int rc = com.sun.tools.javap.Main.run(args, out);
+        if (rc != 0)
+            throw new Error("javap failed. rc=" + rc);
+        out.close();
+        System.out.println(sw);
+        return sw.toString();
+    }
+
+    String compile(String... args) throws Exception {
+        System.err.println("compile: " + Arrays.asList(args));
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        int rc = com.sun.tools.javac.Main.compile(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (out.length() > 0)
+            System.err.println(out);
+        if (rc != 0)
+            error("compilation failed, rc=" + rc);
+        return out;
+    }
+
+    File writeFile(File dir, String path, String body) throws IOException {
+        File f = new File(dir, path);
+        f.getParentFile().mkdirs();
+        FileWriter out = new FileWriter(f);
+        out.write(body);
+        out.close();
+        return f;
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/Basic.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,149 @@
+/*
+ * 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 8003562
+ * @summary Basic tests for jdeps tool
+ * @build Test p.Foo
+ * @run main Basic
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.*;
+import java.util.regex.*;
+
+public class Basic {
+    public static void main(String... args) throws Exception {
+        int errors = 0;
+
+        errors += new Basic().run();
+        if (errors > 0)
+            throw new Exception(errors + " errors found");
+    }
+
+    int run() throws IOException {
+        File testDir = new File(System.getProperty("test.classes", "."));
+        // test a .class file
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang", "p"});
+        // test a directory
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util"});
+        // test class-level dependency output
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang.Object", "p.Foo"},
+             new String[] {"-V", "class"});
+        // test -p option
+        test(new File(testDir, "Test.class"),
+             new String[] {"p.Foo"},
+             new String[] {"--verbose-level=class", "-p", "p"});
+        // test -e option
+        test(new File(testDir, "Test.class"),
+             new String[] {"p.Foo"},
+             new String[] {"-V", "class", "-e", "p\\..*"});
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang"},
+             new String[] {"-V", "package", "-e", "java\\.lang\\..*"});
+        // test -classpath and -all options
+        test(null,
+             new String[] {"com.sun.tools.jdeps", "java.lang", "java.util",
+                           "java.util.regex", "java.io", "p"},
+             new String[] {"--classpath", testDir.getPath(), "*"});
+        return errors;
+    }
+
+    void test(File file, String[] expect) {
+        test(file, expect, new String[0]);
+    }
+
+    void test(File file, String[] expect, String[] options) {
+        String[] args;
+        if (file != null) {
+            args = Arrays.copyOf(options, options.length+1);
+            args[options.length] = file.getPath();
+        } else {
+            args = options;
+        }
+        String[] deps = jdeps(args);
+        checkEqual("dependencies", expect, deps);
+    }
+
+    String[] jdeps(String... args) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        System.err.println("jdeps " + Arrays.toString(args));
+        int rc = com.sun.tools.jdeps.Main.run(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+        if (rc != 0)
+            throw new Error("jdeps failed: rc=" + rc);
+        return findDeps(out);
+    }
+
+    // Pattern used to parse lines
+    private static Pattern linePattern = Pattern.compile(".*\r?\n");
+    private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +.*");
+
+    // Use the linePattern to break the given String into lines, applying
+    // the pattern to each line to see if we have a match
+    private static String[] findDeps(String out) {
+        List<String> result = new ArrayList<>();
+        Matcher lm = linePattern.matcher(out);  // Line matcher
+        Matcher pm = null;                      // Pattern matcher
+        int lines = 0;
+        while (lm.find()) {
+            lines++;
+            CharSequence cs = lm.group();       // The current line
+            if (pm == null)
+                pm = pattern.matcher(cs);
+            else
+                pm.reset(cs);
+            if (pm.find())
+                result.add(pm.group(1));
+            if (lm.end() == out.length())
+                break;
+        }
+        return result.toArray(new String[0]);
+    }
+
+    void checkEqual(String label, String[] expect, String[] found) {
+        Set<String> s1 = new HashSet<>(Arrays.asList(expect));
+        Set<String> s2 = new HashSet<>(Arrays.asList(found));
+
+        if (!s1.equals(s2))
+            error("Unexpected " + label + " found: '" + s2 + "', expected: '" + s1 + "'");
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/Test.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+public class Test {
+    public void test() {
+        p.Foo f = new p.Foo();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/p/Foo.java	Wed Jul 05 18:36:11 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package p;
+
+import java.util.List;
+import java.util.Collections;
+public class Foo {
+    public static List foo() {
+        return Collections.emptyList();
+    }
+
+    public Foo() {
+    }
+}