Merge JDK-8145252-TLS13-branch
authorxuelei
Fri, 08 Jun 2018 19:14:58 +0000
branchJDK-8145252-TLS13-branch
changeset 56709 789118dc46c6
parent 56708 25178bb3e8f5 (current diff)
parent 50477 cb0efe0cc20e (diff)
child 56710 f4c7a97a1275
Merge
--- a/src/java.base/share/classes/java/lang/Object.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Object.java	Fri Jun 08 19:14:58 2018 +0000
@@ -333,12 +333,12 @@
      * by being <em>notified</em> or <em>interrupted</em>, or until a
      * certain amount of real time has elapsed.
      * <p>
-     * In all respects, this method behaves as if {@code wait(timeout, 0)}
+     * In all respects, this method behaves as if {@code wait(timeoutMillis, 0)}
      * had been called. See the specification of the {@link #wait(long, int)} method
      * for details.
      *
-     * @param  timeout the maximum time to wait, in milliseconds
-     * @throws IllegalArgumentException if the value of {@code timeout} is negative
+     * @param  timeoutMillis the maximum time to wait, in milliseconds
+     * @throws IllegalArgumentException if {@code timeoutMillis} is negative
      * @throws IllegalMonitorStateException if the current thread is not
      *         the owner of the object's monitor
      * @throws InterruptedException if any thread interrupted the current thread before or
@@ -349,7 +349,7 @@
      * @see    #wait()
      * @see    #wait(long, int)
      */
-    public final native void wait(long timeout) throws InterruptedException;
+    public final native void wait(long timeoutMillis) throws InterruptedException;
 
     /**
      * Causes the current thread to wait until it is awakened, typically
@@ -378,7 +378,7 @@
      * thread <var>T</var>.
      * <li>The specified amount of real time has elapsed, more or less.
      * The amount of real time, in nanoseconds, is given by the expression
-     * {@code 1000000 * timeout + nanos}. If {@code timeout} and {@code nanos}
+     * {@code 1000000 * timeoutMillis + nanos}. If {@code timeoutMillis} and {@code nanos}
      * are both zero, then real time is not taken into consideration and the
      * thread waits until awakened by one of the other causes.
      * <li>Thread <var>T</var> is awakened spuriously. (See below.)
@@ -423,17 +423,17 @@
      * <pre>{@code
      *     synchronized (obj) {
      *         while (<condition does not hold> and <timeout not exceeded>) {
-     *             long timeout = ... ; // recompute timeout values
+     *             long timeoutMillis = ... ; // recompute timeout values
      *             int nanos = ... ;
-     *             obj.wait(timeout, nanos);
+     *             obj.wait(timeoutMillis, nanos);
      *         }
      *         ... // Perform action appropriate to condition or timeout
      *     }
      * }</pre>
      *
-     * @param  timeout the maximum time to wait, in milliseconds
+     * @param  timeoutMillis the maximum time to wait, in milliseconds
      * @param  nanos   additional time, in nanoseconds, in the range range 0-999999 inclusive
-     * @throws IllegalArgumentException if the value of {@code timeout} is negative,
+     * @throws IllegalArgumentException if {@code timeoutMillis} is negative,
      *         or if the value of {@code nanos} is out of range
      * @throws IllegalMonitorStateException if the current thread is not
      *         the owner of the object's monitor
@@ -445,9 +445,9 @@
      * @see    #wait()
      * @see    #wait(long)
      */
-    public final void wait(long timeout, int nanos) throws InterruptedException {
-        if (timeout < 0) {
-            throw new IllegalArgumentException("timeout value is negative");
+    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
+        if (timeoutMillis < 0) {
+            throw new IllegalArgumentException("timeoutMillis value is negative");
         }
 
         if (nanos < 0 || nanos > 999999) {
@@ -456,10 +456,10 @@
         }
 
         if (nanos > 0) {
-            timeout++;
+            timeoutMillis++;
         }
 
-        wait(timeout);
+        wait(timeoutMillis);
     }
 
     /**
--- a/src/java.base/share/classes/java/time/Clock.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/Clock.java	Fri Jun 08 19:14:58 2018 +0000
@@ -586,7 +586,7 @@
      * This is typically used for testing.
      */
     static final class FixedClock extends Clock implements Serializable {
-       private static final long serialVersionUID = 7430389292664866958L;
+        private static final long serialVersionUID = 7430389292664866958L;
         private final Instant instant;
         private final ZoneId zone;
 
@@ -636,7 +636,7 @@
      * Implementation of a clock that adds an offset to an underlying clock.
      */
     static final class OffsetClock extends Clock implements Serializable {
-       private static final long serialVersionUID = 2007484719125426256L;
+        private static final long serialVersionUID = 2007484719125426256L;
         private final Clock baseClock;
         private final Duration offset;
 
--- a/src/java.base/share/classes/java/time/Duration.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/Duration.java	Fri Jun 08 19:14:58 2018 +0000
@@ -231,7 +231,7 @@
      * This method allows an arbitrary number of nanoseconds to be passed in.
      * The factory will alter the values of the second and nanosecond in order
      * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
-     * For example, the following will result in the exactly the same duration:
+     * For example, the following will result in exactly the same duration:
      * <pre>
      *  Duration.ofSeconds(3, 1);
      *  Duration.ofSeconds(4, -999_999_999);
@@ -1357,12 +1357,14 @@
      * Truncating the duration returns a copy of the original with conceptual fields
      * smaller than the specified unit set to zero.
      * For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will
-     * round down to the nearest minute, setting the seconds and nanoseconds to zero.
+     * round down towards zero to the nearest minute, setting the seconds and
+     * nanoseconds to zero.
      * <p>
      * The unit must have a {@linkplain TemporalUnit#getDuration() duration}
      * that divides into the length of a standard day without remainder.
-     * This includes all supplied time units on {@link ChronoUnit} and
-     * {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception.
+     * This includes all
+     * {@linkplain ChronoUnit#isTimeBased() time-based units on {@code ChronoUnit}}
+     * and {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
@@ -1388,7 +1390,7 @@
             throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
-        long result = (nod / dur) * dur ;
+        long result = (nod / dur) * dur;
         return plusNanos(result - nod);
     }
 
--- a/src/java.base/share/classes/java/time/Instant.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/Instant.java	Fri Jun 08 19:14:58 2018 +0000
@@ -311,7 +311,7 @@
      * This method allows an arbitrary number of nanoseconds to be passed in.
      * The factory will alter the values of the second and nanosecond in order
      * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
-     * For example, the following will result in the exactly the same instant:
+     * For example, the following will result in exactly the same instant:
      * <pre>
      *  Instant.ofEpochSecond(3, 1);
      *  Instant.ofEpochSecond(4, -999_999_999);
@@ -757,7 +757,7 @@
             throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
-        long result = Math.floorDiv(nod, dur) * dur ;
+        long result = Math.floorDiv(nod, dur) * dur;
         return plusNanos(result - nod);
     }
 
--- a/src/java.base/share/classes/java/time/LocalTime.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/LocalTime.java	Fri Jun 08 19:14:58 2018 +0000
@@ -356,14 +356,14 @@
      * @return the local time, not null
      * @since 9
      */
-     public static LocalTime ofInstant(Instant instant, ZoneId zone) {
-         Objects.requireNonNull(instant, "instant");
-         Objects.requireNonNull(zone, "zone");
-         ZoneOffset offset = zone.getRules().getOffset(instant);
-         long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
-         int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
-         return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
-     }
+    public static LocalTime ofInstant(Instant instant, ZoneId zone) {
+        Objects.requireNonNull(instant, "instant");
+        Objects.requireNonNull(zone, "zone");
+        ZoneOffset offset = zone.getRules().getOffset(instant);
+        long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
+        int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
+        return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
+    }
 
     //-----------------------------------------------------------------------
     /**
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java	Fri Jun 08 19:14:58 2018 +0000
@@ -110,7 +110,7 @@
  *        int year = date.get(ChronoField.YEAR);
  *        System.out.printf("  Today is %s %s %d-%s-%d%n", date.getChronology().getID(),
  *                dow, day, month, year);
-
+ *
  *        // Print today's date and the last day of the year
  *        ChronoLocalDate now1 = Chronology.of("Hijrah").dateNow();
  *        ChronoLocalDate first = now1.with(ChronoField.DAY_OF_MONTH, 1)
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java	Fri Jun 08 19:14:58 2018 +0000
@@ -201,7 +201,7 @@
      *
      * @return the date part of this date-time, not null
      */
-    D toLocalDate() ;
+    D toLocalDate();
 
     /**
      * Gets the local time part of this date-time.
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java	Fri Jun 08 19:14:58 2018 +0000
@@ -736,8 +736,8 @@
      * @throws DateTimeException if any of the values are out of range
      * @since 9
      */
-     public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
-                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+    public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
         Objects.requireNonNull(zoneOffset, "zoneOffset");
         HOUR_OF_DAY.checkValidValue(hour);
         MINUTE_OF_HOUR.checkValidValue(minute);
@@ -765,8 +765,8 @@
      * @throws DateTimeException if any of the values are out of range
      * @since 9
      */
-     public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
-                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+    public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
         Objects.requireNonNull(era, "era");
         return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
     }
--- a/src/java.base/share/classes/java/time/chrono/IsoChronology.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/chrono/IsoChronology.java	Fri Jun 08 19:14:58 2018 +0000
@@ -287,9 +287,9 @@
      *         or if the day-of-month is invalid for the month-of-year
      * @since 9
      */
-     @Override
-     public long epochSecond(int prolepticYear, int month, int dayOfMonth,
-                             int hour, int minute, int second, ZoneOffset zoneOffset) {
+    @Override
+    public long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                            int hour, int minute, int second, ZoneOffset zoneOffset) {
         YEAR.checkValidValue(prolepticYear);
         MONTH_OF_YEAR.checkValidValue(month);
         DAY_OF_MONTH.checkValidValue(dayOfMonth);
--- a/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java	Fri Jun 08 19:14:58 2018 +0000
@@ -459,38 +459,38 @@
         return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
     }
 
-     private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
-         fieldValues.remove(ERA);
-         fieldValues.remove(YEAR_OF_ERA);
-         if (resolverStyle == ResolverStyle.LENIENT) {
-             int y = prolepticYearLenient(era, yoe);
-             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
-             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
-             return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
-         }
-         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
-         int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
-         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
-             if (yoe < 1) {
-                 throw new DateTimeException("Invalid YearOfEra: " + yoe);
-             }
-             int y = prolepticYearLenient(era, yoe);
-             JapaneseDate result;
-             try {
-                 result = date(y, moy, dom);
-             } catch (DateTimeException ex) {
-                 result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
-             }
-             // handle the era being changed
-             // only allow if the new date is in the same Jan-Dec as the era change
-             // determine by ensuring either original yoe or result yoe is 1
-             if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
-                 throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
-             }
-             return result;
-         }
-         return date(era, yoe, moy, dom);
-     }
+    private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
+        fieldValues.remove(ERA);
+        fieldValues.remove(YEAR_OF_ERA);
+        if (resolverStyle == ResolverStyle.LENIENT) {
+            int y = prolepticYearLenient(era, yoe);
+            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
+            long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
+            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
+        }
+        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+        int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
+        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
+            if (yoe < 1) {
+                throw new DateTimeException("Invalid YearOfEra: " + yoe);
+            }
+            int y = prolepticYearLenient(era, yoe);
+            JapaneseDate result;
+            try {
+                result = date(y, moy, dom);
+            } catch (DateTimeException ex) {
+                result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
+            }
+            // handle the era being changed
+            // only allow if the new date is in the same Jan-Dec as the era change
+            // determine by ensuring either original yoe or result yoe is 1
+            if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
+                throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
+            }
+            return result;
+        }
+        return date(era, yoe, moy, dom);
+    }
 
     private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map <TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
         fieldValues.remove(ERA);
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Fri Jun 08 19:14:58 2018 +0000
@@ -3049,7 +3049,7 @@
      * Prints and parses a numeric date-time field with optional padding.
      */
     static final class FractionPrinterParser extends NumberPrinterParser {
-       private final boolean decimalPoint;
+        private final boolean decimalPoint;
 
         /**
          * Constructor.
--- a/src/java.base/share/classes/java/time/format/DecimalStyle.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java	Fri Jun 08 19:14:58 2018 +0000
@@ -216,7 +216,6 @@
      *
      * @param zeroDigit  the character for zero
      * @return  a copy with a new character that represents zero, not null
-
      */
     public DecimalStyle withZeroDigit(char zeroDigit) {
         if (zeroDigit == this.zeroDigit) {
--- a/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java	Fri Jun 08 19:14:58 2018 +0000
@@ -119,7 +119,7 @@
  * Providers must ensure that once a rule has been seen by the application, the
  * rule must continue to be available.
  * <p>
-*  Providers are encouraged to implement a meaningful {@code toString} method.
+ * Providers are encouraged to implement a meaningful {@code toString} method.
  * <p>
  * Many systems would like to update time-zone rules dynamically without stopping the JVM.
  * When examined in detail, this is a complex problem.
--- a/src/java.base/share/classes/java/util/Formatter.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/util/Formatter.java	Fri Jun 08 19:14:58 2018 +0000
@@ -2914,7 +2914,7 @@
                 a.append(System.lineSeparator());
                 break;
             case Conversion.PERCENT_SIGN:
-                a.append('%');
+                print("%", l);
                 break;
             default:
                 assert false;
--- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Fri Jun 08 19:14:58 2018 +0000
@@ -35,6 +35,7 @@
 
 package java.util.concurrent;
 
+import java.time.Duration;
 import java.time.temporal.ChronoUnit;
 import java.util.Objects;
 
@@ -192,6 +193,50 @@
     }
 
     /**
+     * Converts the given time duration to this unit.
+     *
+     * <p>For any TimeUnit {@code unit},
+     * {@code unit.convert(Duration.ofNanos(n))}
+     * is equivalent to
+     * {@code unit.convert(n, NANOSECONDS)}, and
+     * {@code unit.convert(Duration.of(n, unit.toChronoUnit()))}
+     * is equivalent to {@code n} (in the absence of overflow).
+     *
+     * @param duration the time duration
+     * @return the converted duration in this unit,
+     * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+     * or {@code Long.MAX_VALUE} if it would positively overflow.
+     * @throws NullPointerException if {@code duration} is null
+     * @see Duration#of(long,TemporalUnit)
+     * @since 11
+     */
+    public long convert(Duration duration) {
+        long secs = duration.getSeconds();
+        int nano = duration.getNano();
+        if (secs < 0 && nano > 0) {
+            // use representation compatible with integer division
+            secs++;
+            nano -= SECOND_SCALE;
+        }
+        final long s, nanoVal;
+        // Optimize for the common case - NANOSECONDS without overflow
+        if (this == NANOSECONDS)
+            nanoVal = nano;
+        else if ((s = scale) < SECOND_SCALE)
+            nanoVal = nano / s;
+        else if (this == SECONDS)
+            return secs;
+        else
+            return secs / secRatio;
+        long val = secs * secRatio + nanoVal;
+        return ((secs < maxSecs && secs > -maxSecs) ||
+                (secs == maxSecs && val > 0) ||
+                (secs == -maxSecs && val < 0))
+            ? val
+            : (secs > 0) ? Long.MAX_VALUE : Long.MIN_VALUE;
+    }
+
+    /**
      * Equivalent to
      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
      * @param duration the duration
@@ -221,10 +266,8 @@
      */
     public long toMicros(long duration) {
         long s, m;
-        if ((s = scale) == MICRO_SCALE)
-            return duration;
-        else if (s < MICRO_SCALE)
-            return duration / microRatio;
+        if ((s = scale) <= MICRO_SCALE)
+            return (s == MICRO_SCALE) ? duration : duration / microRatio;
         else if (duration > (m = maxMicros))
             return Long.MAX_VALUE;
         else if (duration < -m)
@@ -243,10 +286,8 @@
      */
     public long toMillis(long duration) {
         long s, m;
-        if ((s = scale) == MILLI_SCALE)
-            return duration;
-        else if (s < MILLI_SCALE)
-            return duration / milliRatio;
+        if ((s = scale) <= MILLI_SCALE)
+            return (s == MILLI_SCALE) ? duration : duration / milliRatio;
         else if (duration > (m = maxMillis))
             return Long.MAX_VALUE;
         else if (duration < -m)
@@ -265,10 +306,8 @@
      */
     public long toSeconds(long duration) {
         long s, m;
-        if ((s = scale) == SECOND_SCALE)
-            return duration;
-        else if (s < SECOND_SCALE)
-            return duration / secRatio;
+        if ((s = scale) <= SECOND_SCALE)
+            return (s == SECOND_SCALE) ? duration : duration / secRatio;
         else if (duration > (m = maxSecs))
             return Long.MAX_VALUE;
         else if (duration < -m)
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Fri Jun 08 19:14:58 2018 +0000
@@ -49,6 +49,7 @@
 import sun.jvm.hotspot.debugger.Address;
 import sun.jvm.hotspot.debugger.OopHandle;
 import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
+import sun.jvm.hotspot.memory.FileMapInfo;
 import sun.jvm.hotspot.memory.SymbolTable;
 import sun.jvm.hotspot.memory.SystemDictionary;
 import sun.jvm.hotspot.memory.Universe;
@@ -89,6 +90,7 @@
 import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
 import sun.jvm.hotspot.utilities.AddressOps;
 import sun.jvm.hotspot.utilities.Assert;
+import sun.jvm.hotspot.utilities.CompactHashTable;
 import sun.jvm.hotspot.utilities.HeapProgressThunk;
 import sun.jvm.hotspot.utilities.LivenessPathElement;
 import sun.jvm.hotspot.utilities.MethodArray;
@@ -637,12 +639,22 @@
         },
         new Command("symboldump", "symboldump", false) {
             public void doit(Tokens t) {
-                SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() {
+                SymbolTable theTable = SymbolTable.getTheTable();
+                theTable.symbolsDo(new SymbolTable.SymbolVisitor() {
                         public void visit(Symbol sym) {
                             sym.printValueOn(out);
                             out.println();
                         }
                     });
+                CompactHashTable sharedTable = theTable.getSharedTable();
+                if (sharedTable != null) {
+                    sharedTable.symbolsDo(new CompactHashTable.SymbolVisitor() {
+                            public void visit(Symbol sym) {
+                                sym.printValueOn(out);
+                                out.println();
+                            }
+                        });
+                }
             }
         },
         new Command("flags", "flags [ flag | -nd ]", false) {
@@ -1048,6 +1060,15 @@
                     }
                     if (node == null) {
                         Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
+                        if (type == null && VM.getVM().isSharingEnabled()) {
+                            // Check if the value falls in the _md_region
+                            Address loc1 = a.getAddressAt(0);
+                            FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
+                            if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
+                               type = cdsFileMapInfo.getTypeForVptrAddress(loc1);
+                            }
+
+                        }
                         if (type != null) {
                             out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")");
                             node = new CTypeTreeNodeAdapter(a, type, null);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * 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,6 +65,10 @@
     return table;
   }
 
+  public CompactHashTable getSharedTable() {
+      return sharedTable;
+  }
+
   public static long getSeed() {
       return (long) seedField.getValue();
   }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,4 +119,39 @@
     }
     return null;
   }
+
+  public interface SymbolVisitor {
+    public void visit(Symbol sym);
+  }
+
+  public void symbolsDo(SymbolVisitor visitor) {
+    long    symOffset;
+    Symbol  sym;
+    Address baseAddress = baseAddressField.getValue(addr);
+    Address bucket = bucketsField.getValue(addr);
+    for (long index = 0; index < bucketCount(); index++) {
+      int bucketInfo = (int)bucket.getCIntegerAt(index * uintSize, uintSize, true);
+      int bucketOffset = bucketOffset(bucketInfo);
+      int nextBucketInfo = (int)bucket.getCIntegerAt((index+1) * uintSize, uintSize, true);
+      int nextBucketOffset = bucketOffset(nextBucketInfo);
+
+      Address entry = entriesField.getValue(addr).addOffsetTo(bucketOffset * uintSize);
+
+      if (isValueOnlyBucket(bucketInfo)) {
+        symOffset = entry.getCIntegerAt(0, uintSize, true);
+        sym = Symbol.create(baseAddress.addOffsetTo(symOffset));
+        visitor.visit(sym);
+      } else {
+        Address entryMax = entriesField.getValue(addr).addOffsetTo(nextBucketOffset * uintSize);
+        while (entry.lessThan(entryMax)) {
+          symOffset = entry.getCIntegerAt(uintSize, uintSize, true);
+          Address symAddr = baseAddress.addOffsetTo(symOffset);
+          sym = Symbol.create(symAddr);
+          visitor.visit(sym);
+          entry = entry.addOffsetTo(2 * uintSize);
+        }
+      }
+    }
+  }
 }
+
--- a/test/jdk/java/util/Formatter/Basic-X.java.template	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/Basic-X.java.template	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/Basic.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/Basic.java	Fri Jun 08 19:14:58 2018 +0000
@@ -26,7 +26,7 @@
  * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937
  *      5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122
  *      6344623 6369500 6534606 6282094 6286592 6476425 5063507 6469160 6476168
- *      8059175
+ *      8059175 8204229
  *
  * @modules java.base
  * @run shell/timeout=240 Basic.sh
--- a/test/jdk/java/util/Formatter/BasicBigDecimal.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicBigDecimal.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicBigInteger.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicBigInteger.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicBoolean.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicBoolean.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicBooleanObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicBooleanObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicByte.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicByte.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicByteObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicByteObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicChar.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicChar.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicCharObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicCharObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicDateTime.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicDateTime.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicDouble.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicDouble.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicDoubleObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicDoubleObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicFloat.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicFloat.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicFloatObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicFloatObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicInt.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicInt.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicIntObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicIntObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicLong.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicLong.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicLongObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicLongObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicShort.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicShort.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/BasicShortObject.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/BasicShortObject.java	Fri Jun 08 19:14:58 2018 +0000
@@ -1792,6 +1792,15 @@
         //---------------------------------------------------------------------
         test("%%", "%", (Object)null);
         test("%%", "%", "");
+
+        test("%5%", "    %", (Object)null);
+        test("%5%", "    %", "");
+        test("%-5%", "%    ", (Object)null);
+        test("%-5%", "%    ", "");
+
+        tryCatch("%.5%", IllegalFormatPrecisionException.class);
+        tryCatch("%5.5%", IllegalFormatPrecisionException.class);
+
         tryCatch("%%%", UnknownFormatConversionException.class);
         // perhaps an IllegalFormatArgumentIndexException should be defined?
         tryCatch("%<%", IllegalFormatFlagsException.class);
--- a/test/jdk/java/util/Formatter/genBasic.sh	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/Formatter/genBasic.sh	Fri Jun 08 19:14:58 2018 +0000
@@ -23,7 +23,7 @@
 # questions.
 #
 
-javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java
+javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java
 
 gen() {
 #  if [ $3 = "true" ]
--- a/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java	Fri Jun 08 11:59:34 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java	Fri Jun 08 19:14:58 2018 +0000
@@ -40,8 +40,12 @@
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import java.time.Duration;
 import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.LongStream;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -100,4 +104,85 @@
         }
     }
 
+    /**
+     * convert(Duration) roundtrips with Duration.ofXXXX and Duration.of(long, ChronoUnit)
+     */
+    public void testConvertDuration_roundtripDurationOf() {
+        long n = ThreadLocalRandom.current().nextLong();
+
+        assertEquals(n, NANOSECONDS.convert(Duration.ofNanos(n)));
+        assertEquals(n, NANOSECONDS.convert(Duration.of(n, ChronoUnit.NANOS)));
+        assertEquals(n, MILLISECONDS.convert(Duration.ofMillis(n)));
+        assertEquals(n, MILLISECONDS.convert(Duration.of(n, ChronoUnit.MILLIS)));
+        assertEquals(n, SECONDS.convert(Duration.ofSeconds(n)));
+        assertEquals(n, SECONDS.convert(Duration.of(n, ChronoUnit.SECONDS)));
+        n /= 60;
+        assertEquals(n, MINUTES.convert(Duration.ofMinutes(n)));
+        assertEquals(n, MINUTES.convert(Duration.of(n, ChronoUnit.MINUTES)));
+        n /= 60;
+        assertEquals(n, HOURS.convert(Duration.ofHours(n)));
+        assertEquals(n, HOURS.convert(Duration.of(n, ChronoUnit.HOURS)));
+        n /= 24;
+        assertEquals(n, DAYS.convert(Duration.ofDays(n)));
+        assertEquals(n, DAYS.convert(Duration.of(n, ChronoUnit.DAYS)));
+    }
+
+    /**
+     * convert(Duration.ofNanos(n)) agrees with convert(n, NANOSECONDS)
+     */
+    public void testConvertDuration_roundtripDurationOfNanos() {
+        // Test values near unit transitions and near overflow.
+        LongStream.concat(
+                Arrays.stream(TimeUnit.values()).mapToLong(u -> u.toNanos(1)),
+                LongStream.of(Long.MAX_VALUE, Long.MIN_VALUE))
+            .flatMap(n -> LongStream.of(n, n + 1, n - 1))
+            .flatMap(n -> LongStream.of(n, n + 1_000_000_000, n - 1_000_000_000))
+            .flatMap(n -> LongStream.of(n, -n))
+            // .peek(System.err::println)
+            .forEach(n -> Arrays.stream(TimeUnit.values()).forEach(
+                u -> assertEquals(u.convert(n, NANOSECONDS),
+                                  u.convert(Duration.ofNanos(n)))));
+    }
+
+    /**
+     * convert(Duration) doesn't misbehave near Long.MAX_VALUE and Long.MIN_VALUE.
+     */
+    public void testConvertDuration_nearOverflow() {
+        ChronoUnit NANOS = ChronoUnit.NANOS;
+        Duration maxDuration = Duration.ofSeconds(Long.MAX_VALUE, 999_999_999);
+        Duration minDuration = Duration.ofSeconds(Long.MIN_VALUE, 0);
+
+        for (TimeUnit u : TimeUnit.values()) {
+            ChronoUnit cu = u.toChronoUnit();
+            long r;
+            if (u.toNanos(1) > SECONDS.toNanos(1)) {
+                r = u.toNanos(1) / SECONDS.toNanos(1);
+
+                assertThrows(ArithmeticException.class,
+                             () -> Duration.of(Long.MAX_VALUE, cu),
+                             () -> Duration.of(Long.MIN_VALUE, cu));
+            } else {
+                r = 1;
+
+                Duration max = Duration.of(Long.MAX_VALUE, cu);
+                Duration min = Duration.of(Long.MIN_VALUE, cu);
+                assertEquals(Long.MAX_VALUE, u.convert(max));
+                assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, NANOS)));
+                assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, cu)));
+                assertEquals(Long.MIN_VALUE, u.convert(min));
+                assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, NANOS)));
+                assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, cu)));
+                assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, NANOS)));
+                if (u != SECONDS) {
+                    assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, cu)));
+                    assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, NANOS)));
+                    assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, cu)));
+                }
+            }
+
+            assertEquals(Long.MAX_VALUE / r, u.convert(maxDuration));
+            assertEquals(Long.MIN_VALUE / r, u.convert(minDuration));
+        }
+    }
+
 }