Merge
authorvinnie
Tue, 16 Apr 2013 01:44:58 -0700
changeset 16917 fa58bdc075f8
parent 16916 5ecc1594af4d (current diff)
parent 16863 f51406efb328 (diff)
child 16918 a51c2ab502ff
Merge
jdk/test/java/util/ComparatorsTest.java
--- a/jdk/make/java/java/mapfile-vers	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/make/java/java/mapfile-vers	Tue Apr 16 01:44:58 2013 -0700
@@ -217,7 +217,7 @@
 		Java_java_lang_Throwable_fillInStackTrace;
                 Java_java_lang_Throwable_getStackTraceDepth;
                 Java_java_lang_Throwable_getStackTraceElement;
-		Java_java_lang_UNIXProcess_initIDs;
+		Java_java_lang_UNIXProcess_init;
 		Java_java_lang_UNIXProcess_waitForProcessExit;
 		Java_java_lang_UNIXProcess_forkAndExec;
 		Java_java_lang_UNIXProcess_destroyProcess;
--- a/jdk/makefiles/mapfiles/libjava/mapfile-vers	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/makefiles/mapfiles/libjava/mapfile-vers	Tue Apr 16 01:44:58 2013 -0700
@@ -217,7 +217,7 @@
 		Java_java_lang_Throwable_fillInStackTrace;
                 Java_java_lang_Throwable_getStackTraceDepth;
                 Java_java_lang_Throwable_getStackTraceElement;
-		Java_java_lang_UNIXProcess_initIDs;
+		Java_java_lang_UNIXProcess_init;
 		Java_java_lang_UNIXProcess_waitForProcessExit;
 		Java_java_lang_UNIXProcess_forkAndExec;
 		Java_java_lang_UNIXProcess_destroyProcess;
--- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Tue Apr 16 01:44:58 2013 -0700
@@ -184,7 +184,7 @@
         for (int i=0; i<markerInterfaces.length; i++) {
             interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
         }
-        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL,
+        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
                  lambdaClassName, null,
                  NAME_MAGIC_ACCESSOR_IMPL, interfaces);
 
--- a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java	Tue Apr 16 01:44:58 2013 -0700
@@ -25,12 +25,10 @@
 
 package java.nio.file.attribute;
 
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Date;
-import java.util.Formatter;
-import java.util.Locale;
-import java.util.TimeZone;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -51,14 +49,22 @@
     implements Comparable<FileTime>
 {
     /**
+     * The unit of granularity to interpret the value. Null if
+     * this {@code FileTime} is converted from an {@code Instant},
+     * the {@code value} and {@code unit} pair will not be used
+     * in this scenario.
+     */
+    private final TimeUnit unit;
+
+    /**
      * The value since the epoch; can be negative.
      */
     private final long value;
 
     /**
-     * The unit of granularity to interpret the value.
+     * The value as Instant (created lazily, if not from an instant)
      */
-    private final TimeUnit unit;
+    private Instant instant;
 
     /**
      * The value return by toString (created lazily)
@@ -66,27 +72,12 @@
     private String valueAsString;
 
     /**
-     * The value in days and excess nanos (created lazily)
-     */
-    private DaysAndNanos daysAndNanos;
-
-    /**
-     * Returns a DaysAndNanos object representing the value.
-     */
-    private DaysAndNanos asDaysAndNanos() {
-        if (daysAndNanos == null)
-            daysAndNanos = new DaysAndNanos(value, unit);
-        return daysAndNanos;
-    }
-
-    /**
      * Initializes a new instance of this class.
      */
-    private FileTime(long value, TimeUnit unit) {
-        if (unit == null)
-            throw new NullPointerException();
+    private FileTime(long value, TimeUnit unit, Instant instant) {
         this.value = value;
         this.unit = unit;
+        this.instant = instant;
     }
 
     /**
@@ -102,7 +93,8 @@
      * @return  a {@code FileTime} representing the given value
      */
     public static FileTime from(long value, TimeUnit unit) {
-        return new FileTime(value, unit);
+        Objects.requireNonNull(unit, "unit");
+        return new FileTime(value, unit, null);
     }
 
     /**
@@ -115,7 +107,22 @@
      * @return  a {@code FileTime} representing the given value
      */
     public static FileTime fromMillis(long value) {
-        return new FileTime(value, TimeUnit.MILLISECONDS);
+        return new FileTime(value, TimeUnit.MILLISECONDS, null);
+    }
+
+    /**
+     * Returns a {@code FileTime} representing the same point of time value
+     * on the time-line as the provided {@code Instant} object.
+     *
+     * @param   instant
+     *          the instant to convert
+     * @return  a {@code FileTime} representing the same point on the time-line
+     *          as the provided instant
+     * @since 1.8
+     */
+    public static FileTime from(Instant instant) {
+        Objects.requireNonNull(instant, "instant");
+        return new FileTime(0, null, instant);
     }
 
     /**
@@ -132,7 +139,22 @@
      *          since the epoch (1970-01-01T00:00:00Z); can be negative
      */
     public long to(TimeUnit unit) {
-        return unit.convert(this.value, this.unit);
+        Objects.requireNonNull(unit, "unit");
+        if (this.unit != null) {
+            return unit.convert(this.value, this.unit);
+        } else {
+            long secs = unit.convert(instant.getEpochSecond(), TimeUnit.SECONDS);
+            if (secs == Long.MIN_VALUE || secs == Long.MAX_VALUE) {
+                return secs;
+            }
+            long nanos = unit.convert(instant.getNano(), TimeUnit.NANOSECONDS);
+            long r = secs + nanos;
+            // Math.addExact() variant
+            if (((secs ^ r) & (nanos ^ r)) < 0) {
+                return (secs < 0) ? Long.MIN_VALUE : Long.MAX_VALUE;
+            }
+            return r;
+        }
     }
 
     /**
@@ -145,7 +167,110 @@
      * @return  the value in milliseconds, since the epoch (1970-01-01T00:00:00Z)
      */
     public long toMillis() {
-        return unit.toMillis(value);
+        if (unit != null) {
+            return unit.toMillis(value);
+        } else {
+            long secs = instant.getEpochSecond();
+            int  nanos = instant.getNano();
+            // Math.multiplyExact() variant
+            long r = secs * 1000;
+            long ax = Math.abs(secs);
+            if (((ax | 1000) >>> 31 != 0)) {
+                if ((r / 1000) != secs) {
+                    return (secs < 0) ? Long.MIN_VALUE : Long.MAX_VALUE;
+                }
+            }
+            return r + nanos / 1000_000;
+        }
+    }
+
+    /**
+     * Time unit constants for conversion.
+     */
+    private static final long HOURS_PER_DAY      = 24L;
+    private static final long MINUTES_PER_HOUR   = 60L;
+    private static final long SECONDS_PER_MINUTE = 60L;
+    private static final long SECONDS_PER_HOUR   = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
+    private static final long SECONDS_PER_DAY    = SECONDS_PER_HOUR * HOURS_PER_DAY;
+    private static final long MILLIS_PER_SECOND  = 1000L;
+    private static final long MICROS_PER_SECOND  = 1000_000L;
+    private static final long NANOS_PER_SECOND   = 1000_000_000L;
+    private static final int  NANOS_PER_MILLI    = 1000_000;
+    private static final int  NANOS_PER_MICRO    = 1000;
+    // The epoch second of Instant.MIN.
+    private static final long MIN_SECOND = -31557014167219200L;
+    // The epoch second of Instant.MAX.
+    private static final long MAX_SECOND = 31556889864403199L;
+
+    /*
+     * Scale d by m, checking for overflow.
+     */
+    private static long scale(long d, long m, long over) {
+        if (d >  over) return Long.MAX_VALUE;
+        if (d < -over) return Long.MIN_VALUE;
+        return d * m;
+    }
+
+    /**
+     * Converts this {@code FileTime} object to an {@code Instant}.
+     *
+     * <p> The conversion creates an {@code Instant} that represents the
+     * same point on the time-line as this {@code FileTime}.
+     *
+     * <p> {@code FileTime} can store points on the time-line further in the
+     * future and further in the past than {@code Instant}. Conversion
+     * from such further time points saturates to {@link Instant.MIN} if
+     * earlier than {@code Instant.MIN} or {@link Instant.MAX} if later
+     * than {@code Instant.MAX}.
+     *
+     * @return  an instant representing the same point on the time-line as
+     *          this {@code FileTime} object
+     * @since 1.8
+     */
+    public Instant toInstant() {
+        if (instant == null) {
+            long secs = 0L;
+            int nanos = 0;
+            switch (unit) {
+                case DAYS:
+                    secs = scale(value, SECONDS_PER_DAY,
+                                 Long.MAX_VALUE/SECONDS_PER_DAY);
+                    break;
+                case HOURS:
+                    secs = scale(value, SECONDS_PER_HOUR,
+                                 Long.MAX_VALUE/SECONDS_PER_HOUR);
+                    break;
+                case MINUTES:
+                    secs = scale(value, SECONDS_PER_MINUTE,
+                                 Long.MAX_VALUE/SECONDS_PER_MINUTE);
+                    break;
+                case SECONDS:
+                    secs = value;
+                    break;
+                case MILLISECONDS:
+                    secs = Math.floorDiv(value, MILLIS_PER_SECOND);
+                    nanos = (int)Math.floorMod(value, MILLIS_PER_SECOND)
+                            * NANOS_PER_MILLI;
+                    break;
+                case MICROSECONDS:
+                    secs = Math.floorDiv(value, MICROS_PER_SECOND);
+                    nanos = (int)Math.floorMod(value, MICROS_PER_SECOND)
+                            * NANOS_PER_MICRO;
+                    break;
+                case NANOSECONDS:
+                    secs = Math.floorDiv(value, NANOS_PER_SECOND);
+                    nanos = (int)Math.floorMod(value, NANOS_PER_SECOND);
+                    break;
+                default : throw new AssertionError("Unit not handled");
+            }
+            if (secs <= MIN_SECOND)
+                instant = Instant.MIN;
+            else if (secs >= MAX_SECOND)
+                instant = Instant.MAX;
+            else
+                instant = Instant.ofEpochSecond(secs, nanos);
+        }
+        return instant;
     }
 
     /**
@@ -176,8 +301,25 @@
      */
     @Override
     public int hashCode() {
-        // hashcode of days/nanos representation to satisfy contract with equals
-        return asDaysAndNanos().hashCode();
+        // hashcode of instant representation to satisfy contract with equals
+        return toInstant().hashCode();
+    }
+
+    private long toDays() {
+        if (unit != null) {
+            return unit.toDays(value);
+        } else {
+            return TimeUnit.SECONDS.toDays(toInstant().getEpochSecond());
+        }
+    }
+
+    private long toExcessNanos(long days) {
+        if (unit != null) {
+            return unit.toNanos(value - unit.convert(days, TimeUnit.DAYS));
+        } else {
+            return TimeUnit.SECONDS.toNanos(toInstant().getEpochSecond()
+                                            - TimeUnit.DAYS.toSeconds(days));
+        }
     }
 
     /**
@@ -194,14 +336,52 @@
     @Override
     public int compareTo(FileTime other) {
         // same granularity
-        if (unit == other.unit) {
-            return (value < other.value) ? -1 : (value == other.value ? 0 : 1);
+        if (unit != null && unit == other.unit) {
+            return Long.compare(value, other.value);
         } else {
-            // compare using days/nanos representation when unit differs
-            return asDaysAndNanos().compareTo(other.asDaysAndNanos());
+            // compare using instant representation when unit differs
+            long secs = toInstant().getEpochSecond();
+            long secsOther = other.toInstant().getEpochSecond();
+            int cmp = Long.compare(secs, secsOther);
+            if (cmp != 0) {
+                return cmp;
+            }
+            cmp = Long.compare(toInstant().getNano(), other.toInstant().getNano());
+            if (cmp != 0) {
+                return cmp;
+            }
+            if (secs != MAX_SECOND && secs != MIN_SECOND) {
+                return 0;
+            }
+            // if both this and other's Instant reps are MIN/MAX,
+            // use daysSinceEpoch and nanosOfDays, which will not
+            // saturate during calculation.
+            long days = toDays();
+            long daysOther = other.toDays();
+            if (days == daysOther) {
+                return Long.compare(toExcessNanos(days), other.toExcessNanos(daysOther));
+            }
+            return Long.compare(days, daysOther);
         }
     }
 
+    // days in a 400 year cycle = 146097
+    // days in a 10,000 year cycle = 146097 * 25
+    // seconds per day = 86400
+    private static final long DAYS_PER_10000_YEARS = 146097L * 25L;
+    private static final long SECONDS_PER_10000_YEARS = 146097L * 25L * 86400L;
+    private static final long SECONDS_0000_TO_1970 = ((146097L * 5L) - (30L * 365L + 7L)) * 86400L;
+
+    // append year/month/day/hour/minute/second/nano with width and 0 padding
+    private StringBuilder append(StringBuilder sb, int w, int d) {
+        while (w > 0) {
+            sb.append((char)(d/w + '0'));
+            d = d % w;
+            w /= 10;
+        }
+        return sb;
+    }
+
     /**
      * Returns the string representation of this {@code FileTime}. The string
      * is returned in the <a
@@ -229,135 +409,67 @@
      */
     @Override
     public String toString() {
-        String v = valueAsString;
-        if (v == null) {
-            // overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this
-            // limits the range:
-            // [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z]
-            long ms = toMillis();
-
-            // nothing to do when seconds/minutes/hours/days
-            String fractionAsString = "";
-            if (unit.compareTo(TimeUnit.SECONDS) < 0) {
-                long fraction = asDaysAndNanos().fractionOfSecondInNanos();
-                if (fraction != 0L) {
-                    // fraction must be positive
-                    if (fraction < 0L) {
-                        final long MAX_FRACTION_PLUS_1 = 1000L * 1000L * 1000L;
-                        fraction += MAX_FRACTION_PLUS_1;
-                        if (ms != Long.MIN_VALUE) ms--;
-                    }
-
-                    // convert to String, adding leading zeros as required and
-                    // stripping any trailing zeros
-                    String s = Long.toString(fraction);
-                    int len = s.length();
-                    int width = 9 - len;
-                    StringBuilder sb = new StringBuilder(".");
-                    while (width-- > 0) {
-                        sb.append('0');
-                    }
-                    if (s.charAt(len-1) == '0') {
-                        // drop trailing zeros
-                        len--;
-                        while (s.charAt(len-1) == '0')
-                            len--;
-                        sb.append(s.substring(0, len));
-                    } else {
-                        sb.append(s);
-                    }
-                    fractionAsString = sb.toString();
+        if (valueAsString == null) {
+            long secs = 0L;
+            int  nanos = 0;
+            if (instant == null && unit.compareTo(TimeUnit.SECONDS) >= 0) {
+                secs = unit.toSeconds(value);
+            } else {
+                secs = toInstant().getEpochSecond();
+                nanos = toInstant().getNano();
+            }
+            LocalDateTime ldt;
+            int year = 0;
+            if (secs >= -SECONDS_0000_TO_1970) {
+                // current era
+                long zeroSecs = secs - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
+                long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
+                long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
+                ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, nanos, ZoneOffset.UTC);
+                year = ldt.getYear() +  (int)hi * 10000;
+            } else {
+                // before current era
+                long zeroSecs = secs + SECONDS_0000_TO_1970;
+                long hi = zeroSecs / SECONDS_PER_10000_YEARS;
+                long lo = zeroSecs % SECONDS_PER_10000_YEARS;
+                ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, nanos, ZoneOffset.UTC);
+                year = ldt.getYear() + (int)hi * 10000;
+            }
+            if (year <= 0) {
+                year = year - 1;
+            }
+            int fraction = ldt.getNano();
+            StringBuilder sb = new StringBuilder(64);
+            sb.append(year < 0 ? "-" : "");
+            year = Math.abs(year);
+            if (year < 10000) {
+                append(sb, 1000, Math.abs(year));
+            } else {
+                sb.append(String.valueOf(year));
+            }
+            sb.append('-');
+            append(sb, 10, ldt.getMonthValue());
+            sb.append('-');
+            append(sb, 10, ldt.getDayOfMonth());
+            sb.append('T');
+            append(sb, 10, ldt.getHour());
+            sb.append(':');
+            append(sb, 10, ldt.getMinute());
+            sb.append(':');
+            append(sb, 10, ldt.getSecond());
+            if (fraction != 0) {
+                sb.append('.');
+                // adding leading zeros and stripping any trailing zeros
+                int w = 100_000_000;
+                while (fraction % 10 == 0) {
+                    fraction /= 10;
+                    w /= 10;
                 }
+                append(sb, w, fraction);
             }
-
-            // create calendar to use with formatter.
-            GregorianCalendar cal =
-                new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
-            if (value < 0L)
-                cal.setGregorianChange(new Date(Long.MIN_VALUE));
-            cal.setTimeInMillis(ms);
-
-            // years are negative before common era
-            String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : "";
-
-            // [-]YYYY-MM-DDThh:mm:ss[.s]Z
-            v = new Formatter(Locale.ROOT)
-                .format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString)
-                .toString();
-            valueAsString = v;
+            sb.append('Z');
+            valueAsString = sb.toString();
         }
-        return v;
-    }
-
-    /**
-     * Represents a FileTime's value as two longs: the number of days since
-     * the epoch, and the excess (in nanoseconds). This is used for comparing
-     * values with different units of granularity.
-     */
-    private static class DaysAndNanos implements Comparable<DaysAndNanos> {
-        // constants for conversion
-        private static final long C0 = 1L;
-        private static final long C1 = C0 * 24L;
-        private static final long C2 = C1 * 60L;
-        private static final long C3 = C2 * 60L;
-        private static final long C4 = C3 * 1000L;
-        private static final long C5 = C4 * 1000L;
-        private static final long C6 = C5 * 1000L;
-
-        /**
-         * The value (in days) since the epoch; can be negative.
-         */
-        private final long days;
-
-        /**
-         * The excess (in nanoseconds); can be negative if days &lt;= 0.
-         */
-        private final long excessNanos;
-
-        /**
-         * Initializes a new instance of this class.
-         */
-        DaysAndNanos(long value, TimeUnit unit) {
-            long scale;
-            switch (unit) {
-                case DAYS         : scale = C0; break;
-                case HOURS        : scale = C1; break;
-                case MINUTES      : scale = C2; break;
-                case SECONDS      : scale = C3; break;
-                case MILLISECONDS : scale = C4; break;
-                case MICROSECONDS : scale = C5; break;
-                case NANOSECONDS  : scale = C6; break;
-                default : throw new AssertionError("Unit not handled");
-            }
-            this.days = unit.toDays(value);
-            this.excessNanos = unit.toNanos(value - (this.days * scale));
-        }
-
-        /**
-         * Returns the fraction of a second, in nanoseconds.
-         */
-        long fractionOfSecondInNanos() {
-            return excessNanos % (1000L * 1000L * 1000L);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return (obj instanceof DaysAndNanos) ?
-                compareTo((DaysAndNanos)obj) == 0 : false;
-        }
-
-        @Override
-        public int hashCode() {
-            return (int)(days ^ (days >>> 32) ^
-                         excessNanos ^ (excessNanos >>> 32));
-        }
-
-        @Override
-        public int compareTo(DaysAndNanos other) {
-            if (this.days != other.days)
-                return (this.days < other.days) ? -1 : 1;
-            return (this.excessNanos < other.excessNanos) ? -1 :
-                   (this.excessNanos == other.excessNanos) ? 0 : 1;
-        }
+        return valueAsString;
     }
 }
--- a/jdk/src/share/classes/java/util/ArrayList.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/util/ArrayList.java	Tue Apr 16 01:44:58 2013 -0700
@@ -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
@@ -105,8 +105,20 @@
     private static final long serialVersionUID = 8683452581122892189L;
 
     /**
+     * Default initial capacity.
+     */
+    private static final int DEFAULT_CAPACITY = 10;
+
+    /**
+     * Shared empty array instance used for empty instances.
+     */
+    private static final Object[] EMPTY_ELEMENTDATA = {};
+
+    /**
      * The array buffer into which the elements of the ArrayList are stored.
-     * The capacity of the ArrayList is the length of this array buffer.
+     * The capacity of the ArrayList is the length of this array buffer. Any
+     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
+     * DEFAULT_CAPACITY when the first element is added.
      */
     private transient Object[] elementData;
 
@@ -136,7 +148,8 @@
      * Constructs an empty list with an initial capacity of ten.
      */
     public ArrayList() {
-        this(10);
+        super();
+        this.elementData = EMPTY_ELEMENTDATA;
     }
 
     /**
@@ -162,8 +175,7 @@
      */
     public void trimToSize() {
         modCount++;
-        int oldCapacity = elementData.length;
-        if (size < oldCapacity) {
+        if (size < elementData.length) {
             elementData = Arrays.copyOf(elementData, size);
         }
     }
@@ -176,12 +188,29 @@
      * @param   minCapacity   the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
-        if (minCapacity > 0)
-            ensureCapacityInternal(minCapacity);
+        int minExpand = (elementData != EMPTY_ELEMENTDATA)
+            // any size if real element table
+            ? 0
+            // larger than default for empty table. It's already supposed to be
+            // at default size.
+            : DEFAULT_CAPACITY;
+
+        if (minCapacity > minExpand) {
+            ensureExplicitCapacity(minCapacity);
+        }
     }
 
     private void ensureCapacityInternal(int minCapacity) {
+        if (elementData == EMPTY_ELEMENTDATA) {
+            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
+        }
+
+        ensureExplicitCapacity(minCapacity);
+    }
+
+    private void ensureExplicitCapacity(int minCapacity) {
         modCount++;
+
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
             grow(minCapacity);
@@ -450,7 +479,7 @@
         if (numMoved > 0)
             System.arraycopy(elementData, index+1, elementData, index,
                              numMoved);
-        elementData[--size] = null; // Let gc do its work
+        elementData[--size] = null; // clear to let GC do its work
 
         return oldValue;
     }
@@ -495,7 +524,7 @@
         if (numMoved > 0)
             System.arraycopy(elementData, index+1, elementData, index,
                              numMoved);
-        elementData[--size] = null; // Let gc do its work
+        elementData[--size] = null; // clear to let GC do its work
     }
 
     /**
@@ -505,7 +534,7 @@
     public void clear() {
         modCount++;
 
-        // Let gc do its work
+        // clear to let GC do its work
         for (int i = 0; i < size; i++)
             elementData[i] = null;
 
@@ -586,10 +615,12 @@
         System.arraycopy(elementData, toIndex, elementData, fromIndex,
                          numMoved);
 
-        // Let gc do its work
+        // clear to let GC do its work
         int newSize = size - (toIndex-fromIndex);
-        while (size != newSize)
-            elementData[--size] = null;
+        for (int i = newSize; i < size; i++) {
+            elementData[i] = null;
+        }
+        size = newSize;
     }
 
     /**
@@ -677,6 +708,7 @@
                 w += size - r;
             }
             if (w != size) {
+                // clear to let GC do its work
                 for (int i = w; i < size; i++)
                     elementData[i] = null;
                 modCount += size - w;
@@ -701,17 +733,17 @@
         int expectedModCount = modCount;
         s.defaultWriteObject();
 
-        // Write out array length
-        s.writeInt(elementData.length);
+        // Write out size as capacity for behavioural compatibility with clone()
+        s.writeInt(size);
 
         // Write out all elements in the proper order.
-        for (int i=0; i<size; i++)
+        for (int i=0; i<size; i++) {
             s.writeObject(elementData[i]);
+        }
 
         if (modCount != expectedModCount) {
             throw new ConcurrentModificationException();
         }
-
     }
 
     /**
@@ -720,16 +752,24 @@
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
+        elementData = EMPTY_ELEMENTDATA;
+
         // Read in size, and any hidden stuff
         s.defaultReadObject();
 
-        // Read in array length and allocate array
-        int arrayLength = s.readInt();
-        Object[] a = elementData = new Object[arrayLength];
+        // Read in capacity
+        s.readInt(); // ignored
+
+        if (size > 0) {
+            // be like clone(), allocate array based upon size not capacity
+            ensureCapacityInternal(size);
 
-        // Read in all elements in the proper order.
-        for (int i=0; i<size; i++)
-            a[i] = s.readObject();
+            Object[] a = elementData;
+            // Read in all elements in the proper order.
+            for (int i=0; i<size; i++) {
+                a[i] = s.readObject();
+            }
+        }
     }
 
     /**
--- a/jdk/src/share/classes/java/util/Comparators.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/util/Comparators.java	Tue Apr 16 01:44:58 2013 -0700
@@ -261,6 +261,7 @@
      * according to the supplied {@code Comparator}
      */
     public static<T> BinaryOperator<T> lesserOf(Comparator<? super T> comparator) {
+        Objects.requireNonNull(comparator);
         return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
     }
 
@@ -274,6 +275,7 @@
      * according to the supplied {@code Comparator}
      */
     public static<T> BinaryOperator<T> greaterOf(Comparator<? super T> comparator) {
+        Objects.requireNonNull(comparator);
         return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
     }
 }
--- a/jdk/src/share/classes/java/util/HashMap.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/util/HashMap.java	Tue Apr 16 01:44:58 2013 -0700
@@ -129,7 +129,7 @@
     /**
      * The default initial capacity - MUST be a power of two.
      */
-    static final int DEFAULT_INITIAL_CAPACITY = 16;
+    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
 
     /**
      * The maximum capacity, used if a higher value is implicitly specified
@@ -144,9 +144,14 @@
     static final float DEFAULT_LOAD_FACTOR = 0.75f;
 
     /**
+     * An empty table instance to share when the table is not inflated.
+     */
+    static final Entry<?,?>[] EMPTY_TABLE = {};
+
+    /**
      * The table, resized as necessary. Length MUST Always be a power of two.
      */
-    transient Entry<?,?>[] table;
+    transient Entry<?,?>[] table = EMPTY_TABLE;
 
     /**
      * The number of key-value mappings contained in this map.
@@ -157,6 +162,8 @@
      * The next size value at which to resize (capacity * load factor).
      * @serial
      */
+    // If table == EMPTY_TABLE then this is the initial capacity at which the
+    // table will be created when inflated.
     int threshold;
 
     /**
@@ -223,14 +230,8 @@
             throw new IllegalArgumentException("Illegal load factor: " +
                                                loadFactor);
 
-        // Find a power of 2 >= initialCapacity
-        int capacity = 1;
-        while (capacity < initialCapacity)
-            capacity <<= 1;
-
         this.loadFactor = loadFactor;
-        threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
-        table = new Entry<?,?>[capacity];
+        threshold = initialCapacity;
         init();
     }
 
@@ -265,9 +266,33 @@
     public HashMap(Map<? extends K, ? extends V> m) {
         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
                       DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
+        inflateTable(threshold);
+
         putAllForCreate(m);
     }
 
+    private static int roundUpToPowerOf2(int number) {
+        // assert number >= 0 : "number must be non-negative";
+        int rounded = number >= MAXIMUM_CAPACITY
+                ? MAXIMUM_CAPACITY
+                : (rounded = Integer.highestOneBit(number)) != 0
+                    ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded
+                    : 1;
+
+        return rounded;
+    }
+
+    /**
+     * Inflates the table.
+     */
+    private void inflateTable(int toSize) {
+        // Find a power of 2 >= toSize
+        int capacity = roundUpToPowerOf2(toSize);
+
+        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
+        table = new Entry[capacity];
+    }
+
     // internal utilities
 
     /**
@@ -305,6 +330,7 @@
      * Returns index for hash code h.
      */
     static int indexFor(int h, int length) {
+        // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
         return h & (length-1);
     }
 
@@ -369,6 +395,10 @@
      */
     @SuppressWarnings("unchecked")
     final Entry<K,V> getEntry(Object key) {
+        if (isEmpty()) {
+            return null;
+        }
+
         int hash = (key == null) ? 0 : hash(key);
         for (Entry<?,?> e = table[indexFor(hash, table.length)];
              e != null;
@@ -381,7 +411,6 @@
         return null;
     }
 
-
     /**
      * Associates the specified value with the specified key in this map.
      * If the map previously contained a mapping for the key, the old
@@ -395,6 +424,9 @@
      *         previously associated <tt>null</tt> with <tt>key</tt>.)
      */
     public V put(K key, V value) {
+        if (table == EMPTY_TABLE) {
+            inflateTable(threshold);
+        }
         if (key == null)
             return putForNullKey(value);
         int hash = hash(key);
@@ -529,6 +561,10 @@
         if (numKeysToBeAdded == 0)
             return;
 
+        if (table == EMPTY_TABLE) {
+            inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
+        }
+
         /*
          * Expand the map if the map if the number of mappings to be added
          * is greater than or equal to threshold.  This is conservative; the
@@ -573,6 +609,9 @@
      * for this key.
      */
     final Entry<K,V> removeEntryForKey(Object key) {
+        if (isEmpty()) {
+            return null;
+        }
         int hash = (key == null) ? 0 : hash(key);
         int i = indexFor(hash, table.length);
         @SuppressWarnings("unchecked")
@@ -605,7 +644,7 @@
      * for matching.
      */
     final Entry<K,V> removeMapping(Object o) {
-        if (!(o instanceof Map.Entry))
+        if (isEmpty() || !(o instanceof Map.Entry))
             return null;
 
         Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
@@ -641,9 +680,7 @@
      */
     public void clear() {
         modCount++;
-        Entry<?,?>[] tab = table;
-        for (int i = 0; i < tab.length; i++)
-            tab[i] = null;
+        Arrays.fill(table, null);
         size = 0;
     }
 
@@ -693,7 +730,14 @@
         } catch (CloneNotSupportedException e) {
             // assert false;
         }
-        result.table = new Entry<?,?>[table.length];
+        if (result.table != EMPTY_TABLE) {
+            result.inflateTable(Math.min(
+                (int) Math.min(
+                    size * Math.min(1 / loadFactor, 4.0f),
+                    // we have limits...
+                    HashMap.MAXIMUM_CAPACITY),
+                table.length));
+        }
         result.entrySet = null;
         result.modCount = 0;
         result.size = 0;
@@ -749,8 +793,7 @@
         }
 
         public final int hashCode() {
-            return (key==null   ? 0 : key.hashCode()) ^
-                   (value==null ? 0 : value.hashCode());
+            return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
         }
 
         public final String toString() {
@@ -1017,14 +1060,15 @@
     private void writeObject(java.io.ObjectOutputStream s)
         throws IOException
     {
-        Iterator<Map.Entry<K,V>> i =
-            (size > 0) ? entrySet0().iterator() : null;
-
         // Write out the threshold, loadfactor, and any hidden stuff
         s.defaultWriteObject();
 
         // Write out number of buckets
-        s.writeInt(table.length);
+        if (table==EMPTY_TABLE) {
+            s.writeInt(roundUpToPowerOf2(threshold));
+        } else {
+           s.writeInt(table.length);
+        }
 
         // Write out size (number of Mappings)
         s.writeInt(size);
@@ -1049,16 +1093,18 @@
     {
         // Read in the threshold (ignored), loadfactor, and any hidden stuff
         s.defaultReadObject();
-        if (loadFactor <= 0 || Float.isNaN(loadFactor))
+        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
             throw new InvalidObjectException("Illegal load factor: " +
                                                loadFactor);
+        }
 
-        // set hashMask
+        // set other fields that need values
         Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
                 sun.misc.Hashing.randomHashSeed(this));
+        table = EMPTY_TABLE;
 
-        // Read in number of buckets and allocate the bucket array;
-        s.readInt(); // ignored
+        // Read in number of buckets
+        s.readInt(); // ignored.
 
         // Read number of mappings
         int mappings = s.readInt();
@@ -1066,23 +1112,21 @@
             throw new InvalidObjectException("Illegal mappings count: " +
                                                mappings);
 
-        int initialCapacity = (int) Math.min(
-                // capacity chosen by number of mappings
-                // and desired load (if >= 0.25)
-                mappings * Math.min(1 / loadFactor, 4.0f),
-                // we have limits...
-                HashMap.MAXIMUM_CAPACITY);
-        int capacity = 1;
-        // find smallest power of two which holds all mappings
-        while (capacity < initialCapacity) {
-            capacity <<= 1;
+        // capacity chosen by number of mappings and desired load (if >= 0.25)
+        int capacity = (int) Math.min(
+                    mappings * Math.min(1 / loadFactor, 4.0f),
+                    // we have limits...
+                    HashMap.MAXIMUM_CAPACITY);
+
+        // allocate the bucket array;
+        if (mappings > 0) {
+            inflateTable(capacity);
+        } else {
+            threshold = capacity;
         }
 
-        table = new Entry<?,?>[capacity];
-        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
         init();  // Give subclass a chance to do its thing.
 
-
         // Read the keys and values, and put the mappings in the HashMap
         for (int i=0; i<mappings; i++) {
             @SuppressWarnings("unchecked")
--- a/jdk/src/share/classes/java/util/Objects.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/classes/java/util/Objects.java	Tue Apr 16 01:44:58 2013 -0700
@@ -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
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import java.util.function.Supplier;
+
 /**
  * This class consists of {@code static} utility methods for operating
  * on objects.  These utilities include {@code null}-safe or {@code
@@ -226,4 +228,30 @@
             throw new NullPointerException(message);
         return obj;
     }
+
+    /**
+     * Checks that the specified object reference is not {@code null} and
+     * throws a customized {@link NullPointerException} if it is.
+     *
+     * <p>Unlike the method {@link requireNonNull(Object, String},
+     * this method allows creation of the message to be deferred until
+     * after the null check is made. While this may confer a
+     * performance advantage in the non-null case, when deciding to
+     * call this method care should be taken that the costs of
+     * creating the message supplier are less than the cost of just
+     * creating the string message directly.
+     *
+     * @param obj     the object reference to check for nullity
+     * @param messageSupplier supplier of the detail message to be
+     * used in the event that a {@code NullPointerException} is thrown
+     * @param <T> the type of the reference
+     * @return {@code obj} if not {@code null}
+     * @throws NullPointerException if {@code obj} is {@code null}
+     * @since 1.8
+     */
+    public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
+        if (obj == null)
+            throw new NullPointerException(messageSupplier.get());
+        return obj;
+    }
 }
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Tue Apr 16 01:44:58 2013 -0700
@@ -466,7 +466,10 @@
             if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
             {
                 u.type = eSrc.type;    // make it the same type
-                if (!deletesrc) {      // if it's not "rename", just take the data
+                if (deletesrc) {       // if it's a "rename", take the data
+                    u.bytes = eSrc.bytes;
+                    u.file = eSrc.file;
+                } else {               // if it's not "rename", copy the data
                     if (eSrc.bytes != null)
                         u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
                     else if (eSrc.file != null) {
@@ -1118,7 +1121,7 @@
             if (old != null) {
                 removeFromTree(old);
             }
-            if (e.type == Entry.NEW || e.type == Entry.FILECH) {
+            if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
                 IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
                 e.sibling = parent.child;
                 parent.child = e;
@@ -2326,12 +2329,12 @@
     private void removeFromTree(IndexNode inode) {
         IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
         IndexNode child = parent.child;
-        if (child == inode) {
+        if (child.equals(inode)) {
             parent.child = child.sibling;
         } else {
             IndexNode last = child;
             while ((child = child.sibling) != null) {
-                if (child == inode) {
+                if (child.equals(inode)) {
                     last.sibling = child.sibling;
                     break;
                 } else {
--- a/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h	Tue Apr 16 01:44:58 2013 -0700
@@ -143,9 +143,9 @@
  * structure from the information present in a given Java Composite
  * object.
  */
-typedef JNIEXPORT void (JNICALL CompInfoFunc)(JNIEnv *env,
-                                              CompositeInfo *pCompInfo,
-                                              jobject Composite);
+typedef void (JNICALL CompInfoFunc)(JNIEnv *env,
+                                    CompositeInfo *pCompInfo,
+                                    jobject Composite);
 
 /*
  * The additional information needed to implement a primitive that
--- a/jdk/src/share/npt/npt.h	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/share/npt/npt.h	Tue Apr 16 01:44:58 2013 -0700
@@ -94,13 +94,13 @@
 
 JNIEXPORT void JNICALL nptInitialize
                        (NptEnv **pnpt, char *nptVersion, char *options);
-typedef JNIEXPORT void (JNICALL *NptInitialize)
-                       (NptEnv **pnpt, char *nptVersion, char *options);
+typedef void (JNICALL *NptInitialize)
+             (NptEnv **pnpt, char *nptVersion, char *options);
 
 JNIEXPORT void JNICALL nptTerminate
                        (NptEnv* npt, char *options);
-typedef JNIEXPORT void (JNICALL *NptTerminate)
-                       (NptEnv* npt, char *options);
+typedef void (JNICALL *NptTerminate)
+             (NptEnv* npt, char *options);
 
 #ifdef __cplusplus
 } /* extern "C" */
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd	Tue Apr 16 01:44:58 2013 -0700
@@ -270,11 +270,10 @@
         return !hasExited;
     }
 
-    /* This routine initializes JNI field offsets for the class */
-    private static native void initIDs();
+    private static native void init();
 
     static {
-        initIDs();
+        init();
     }
 
     /**
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux	Tue Apr 16 01:44:58 2013 -0700
@@ -270,11 +270,10 @@
         return !hasExited;
     }
 
-    /* This routine initializes JNI field offsets for the class */
-    private static native void initIDs();
+    private static native void init();
 
     static {
-        initIDs();
+        init();
     }
 
     /**
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris	Tue Apr 16 01:44:58 2013 -0700
@@ -328,10 +328,9 @@
 
     }
 
-    /* This routine initializes JNI field offsets for the class */
-    private static native void initIDs();
+    private static native void init();
 
     static {
-        initIDs();
+        init();
     }
 }
--- a/jdk/src/solaris/javavm/export/jni_md.h	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/javavm/export/jni_md.h	Tue Apr 16 01:44:58 2013 -0700
@@ -26,8 +26,17 @@
 #ifndef _JAVASOFT_JNI_MD_H_
 #define _JAVASOFT_JNI_MD_H_
 
-#define JNIEXPORT
-#define JNIIMPORT
+#ifndef __has_attribute
+  #define __has_attribute(x) 0
+#endif
+#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+  #define JNIEXPORT     __attribute__((visibility("default")))
+  #define JNIIMPORT     __attribute__((visibility("default")))
+#else
+  #define JNIEXPORT
+  #define JNIIMPORT
+#endif
+
 #define JNICALL
 
 typedef int jint;
--- a/jdk/src/solaris/native/java/lang/ProcessEnvironment_md.c	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/native/java/lang/ProcessEnvironment_md.c	Tue Apr 16 01:44:58 2013 -0700
@@ -31,21 +31,24 @@
 #ifdef __APPLE__
 #include <crt_externs.h>
 #define environ (*_NSGetEnviron())
+#else
+/* This is one of the rare times it's more portable to declare an
+ * external symbol explicitly, rather than via a system header.
+ * The declaration is standardized as part of UNIX98, but there is
+ * no standard (not even de-facto) header file where the
+ * declaration is to be found.  See:
+ * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
+ *
+ * "All identifiers in this volume of IEEE Std 1003.1-2001, except
+ * environ, are defined in at least one of the headers" (!)
+ */
+extern char **environ;
 #endif
 
 JNIEXPORT jobjectArray JNICALL
 Java_java_lang_ProcessEnvironment_environ(JNIEnv *env, jclass ign)
 {
-    /* This is one of the rare times it's more portable to declare an
-     * external symbol explicitly, rather than via a system header.
-     * The declaration is standardized as part of UNIX98, but there is
-     * no standard (not even de-facto) header file where the
-     * declaration is to be found.  See:
-     * http://www.opengroup.org/onlinepubs/007908799/xbd/envvar.html */
-#ifndef __APPLE__
-    extern char ** environ; /* environ[i] looks like: VAR=VALUE\0 */
-#endif
-
     jsize count = 0;
     jsize i, j;
     jobjectArray result;
--- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c	Tue Apr 16 01:44:58 2013 -0700
@@ -52,6 +52,19 @@
 #ifdef __APPLE__
 #include <crt_externs.h>
 #define environ (*_NSGetEnviron())
+#else
+/* This is one of the rare times it's more portable to declare an
+ * external symbol explicitly, rather than via a system header.
+ * The declaration is standardized as part of UNIX98, but there is
+ * no standard (not even de-facto) header file where the
+ * declaration is to be found.  See:
+ * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
+ *
+ * "All identifiers in this volume of IEEE Std 1003.1-2001, except
+ * environ, are defined in at least one of the headers" (!)
+ */
+extern char **environ;
 #endif
 
 /*
@@ -152,19 +165,6 @@
   } while((_result == -1) && (errno == EINTR)); \
 } while(0)
 
-/* This is one of the rare times it's more portable to declare an
- * external symbol explicitly, rather than via a system header.
- * The declaration is standardized as part of UNIX98, but there is
- * no standard (not even de-facto) header file where the
- * declaration is to be found.  See:
- * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
- *
- * "All identifiers in this volume of IEEE Std 1003.1-2001, except
- * environ, are defined in at least one of the headers" (!)
- */
-extern char **environ;
-
 
 static void
 setSIGCHLDHandler(JNIEnv *env)
@@ -241,52 +241,41 @@
 }
 
 static const char * const *
-splitPath(JNIEnv *env, const char *path)
+effectivePathv(JNIEnv *env)
 {
-    const char *p, *q;
-    char **pathv;
+    char *p;
     int i;
+    const char *path = effectivePath();
     int count = countOccurrences(path, ':') + 1;
+    size_t pathvsize = sizeof(const char *) * (count+1);
+    size_t pathsize = strlen(path) + 1;
+    const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
 
-    pathv = NEW(char*, count+1);
+    if (pathv == NULL)
+        return NULL;
+    p = (char *) pathv + pathvsize;
+    memcpy(p, path, pathsize);
+    /* split PATH by replacing ':' with NULs; empty components => "." */
+    for (i = 0; i < count; i++) {
+        char *q = p + strcspn(p, ":");
+        pathv[i] = (p == q) ? "." : p;
+        *q = '\0';
+        p = q + 1;
+    }
     pathv[count] = NULL;
-    for (p = path, i = 0; i < count; i++, p = q + 1) {
-        for (q = p; (*q != ':') && (*q != '\0'); q++)
-            ;
-        if (q == p)             /* empty PATH component => "." */
-            pathv[i] = "./";
-        else {
-            int addSlash = ((*(q - 1)) != '/');
-            pathv[i] = NEW(char, q - p + addSlash + 1);
-            memcpy(pathv[i], p, q - p);
-            if (addSlash)
-                pathv[i][q - p] = '/';
-            pathv[i][q - p + addSlash] = '\0';
-        }
-    }
-    return (const char * const *) pathv;
+    return pathv;
 }
 
 /**
- * Cached value of JVM's effective PATH.
+ * The cached and split version of the JDK's effective PATH.
  * (We don't support putenv("PATH=...") in native code)
  */
-static const char *parentPath;
-
-/**
- * Split, canonicalized version of parentPath
- */
 static const char * const *parentPathv;
 
-static jfieldID field_exitcode;
-
 JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz)
+Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
 {
-    field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I");
-
-    parentPath  = effectivePath();
-    parentPathv = splitPath(env, parentPath);
+    parentPathv = effectivePathv(env);
 
     setSIGCHLDHandler(env);
 }
@@ -486,6 +475,9 @@
     }
     /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
     errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
+    if (errmsg == NULL)
+        return;
+
     sprintf(errmsg, format, errnum, detail);
     s = JNU_NewStringPlatform(env, errmsg);
     if (s != NULL) {
@@ -590,11 +582,13 @@
         for (dirs = parentPathv; *dirs; dirs++) {
             const char * dir = *dirs;
             int dirlen = strlen(dir);
-            if (filelen + dirlen + 1 >= PATH_MAX) {
+            if (filelen + dirlen + 2 >= PATH_MAX) {
                 errno = ENAMETOOLONG;
                 continue;
             }
             memcpy(expanded_file, dir, dirlen);
+            if (expanded_file[dirlen - 1] != '/')
+                expanded_file[dirlen++] = '/';
             memcpy(expanded_file + dirlen, file, filelen);
             expanded_file[dirlen + filelen] = '\0';
             execve_with_shell_fallback(expanded_file, argv, envp);
--- a/jdk/src/solaris/native/sun/awt/awt_LoadLibrary.c	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_LoadLibrary.c	Tue Apr 16 01:44:58 2013 -0700
@@ -43,7 +43,7 @@
 
 static void *awtHandle = NULL;
 
-typedef JNIEXPORT jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved);
+typedef jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved);
 
 /* Initialize the Java VM instance variable when the library is
    first loaded */
@@ -206,7 +206,7 @@
                                      jobject frame, jstring jcommand)
 {
     /* type of the old backdoor function */
-    typedef JNIEXPORT void JNICALL
+    typedef void JNICALL
         XsessionWMcommand_type(JNIEnv *env, jobject this,
                                jobject frame, jstring jcommand);
 
@@ -234,7 +234,7 @@
 JNIEXPORT void JNICALL
 Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv)
 {
-    typedef JNIEXPORT void JNICALL
+    typedef void JNICALL
         XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv);
 
     static XsessionWMcommand_New_type *XsessionWMcommand = NULL;
--- a/jdk/test/demo/zipfs/ZipFSTester.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/test/demo/zipfs/ZipFSTester.java	Tue Apr 16 01:44:58 2013 -0700
@@ -138,14 +138,31 @@
             Path dst3 = Paths.get(tmpName + "_Tmp");
             Files.move(dst2, dst3);
             checkEqual(src, dst3);
+            if (Files.exists(dst2))
+                throw new RuntimeException("Failed!");
+
+            // copyback + move
+            Files.copy(dst3, dst);
+            Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
+            Files.move(dst, dst4);
+            checkEqual(src, dst4);
 
             // delete
-            if (Files.exists(dst2))
+            Files.delete(dst4);
+            if (Files.exists(dst4))
                 throw new RuntimeException("Failed!");
             Files.delete(dst3);
             if (Files.exists(dst3))
                 throw new RuntimeException("Failed!");
 
+            // move (existing entry)
+            Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
+            if (Files.exists(dst5)) {
+                Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
+                Files.move(dst5, dst6);
+                walk(fs.getPath("/"));
+            }
+
             // newInputStream on dir
             Path parent = dst2.getParent();
             try {
--- a/jdk/test/demo/zipfs/basic.sh	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/test/demo/zipfs/basic.sh	Tue Apr 16 01:44:58 2013 -0700
@@ -22,7 +22,7 @@
 #
 # @test
 # @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
-# 7157656
+# 7157656 8002390
 # @summary Test ZipFileSystem demo
 # @build Basic PathOps ZipFSTester
 # @run shell basic.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/lambda/LambdaClassFinal.java	Tue Apr 16 01:44:58 2013 -0700
@@ -0,0 +1,58 @@
+/*
+ * 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 8012028
+ * @summary Generated Lambda implementing class should be final
+ */
+
+import java.lang.reflect.Modifier;
+import java.io.Serializable;
+
+public class LambdaClassFinal {
+
+    interface I {
+        void m();
+    }
+
+    interface Iser extends Serializable {
+        void m();
+    }
+
+    static void assertTrue(boolean cond) {
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new LambdaClassFinal().test();
+    }
+
+     void test() throws Exception {
+        I lam = () -> { };
+        assertTrue((lam.getClass().getModifiers() & Modifier.FINAL) != 0);
+        Iser slam = () -> { };
+        assertTrue((slam.getClass().getModifiers() & Modifier.FINAL) != 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/lambda/LambdaClassSynthetic.java	Tue Apr 16 01:44:58 2013 -0700
@@ -0,0 +1,58 @@
+/*
+ * 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 8008941
+ * @summary Generated Lambda implementing class should be synthetic
+ */
+
+import java.lang.reflect.Modifier;
+import java.io.Serializable;
+
+public class LambdaClassSynthetic {
+
+    interface I {
+        void m();
+    }
+
+    interface Iser extends Serializable {
+        void m();
+    }
+
+    static void assertTrue(boolean cond) {
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new LambdaClassFinal().test();
+    }
+
+    void test() throws Exception {
+        I lam = () -> { };
+        assertTrue(lam.getClass().isSynthetic());
+        Iser slam = () -> { };
+        assertTrue(slam.getClass().isSynthetic());
+    }
+}
--- a/jdk/test/java/nio/file/attribute/FileTime/Basic.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/test/java/nio/file/attribute/FileTime/Basic.java	Tue Apr 16 01:44:58 2013 -0700
@@ -22,14 +22,17 @@
  */
 
 /* @test
- * @bug 6844313
+ * @bug 6844313 8011647
  * @summary Unit test for java.nio.file.FileTime
  */
 
+
 import java.nio.file.attribute.FileTime;
+import java.time.Instant;
 import java.util.concurrent.TimeUnit;
 import static java.util.concurrent.TimeUnit.*;
 import java.util.Random;
+import java.util.EnumSet;
 
 public class Basic {
 
@@ -40,27 +43,59 @@
         long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1;
         long yesterdayInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) - 1;
 
+        Instant nowInstant = Instant.ofEpochMilli(now);
+
         // equals
         eq(now, MILLISECONDS, now, MILLISECONDS);
         eq(now, MILLISECONDS, now*1000L, MICROSECONDS);
         neq(now, MILLISECONDS, 0, MILLISECONDS);
         neq(now, MILLISECONDS, 0, MICROSECONDS);
 
+        eq(nowInstant, now, MILLISECONDS);
+        eq(nowInstant, now*1000L, MICROSECONDS);
+        neq(nowInstant, 0, MILLISECONDS);
+        neq(nowInstant, 0, MICROSECONDS);
+
         // compareTo
         cmp(now, MILLISECONDS, now, MILLISECONDS, 0);
         cmp(now, MILLISECONDS, now*1000L, MICROSECONDS, 0);
         cmp(now, MILLISECONDS, now-1234, MILLISECONDS, 1);
         cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1);
+
         cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1);
         cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1);
         cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1);
         cmp(now, MILLISECONDS, yesterdayInDays, DAYS, 1);
         cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1);
+
         cmp(Long.MAX_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, 1);
         cmp(Long.MAX_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, 1);
         cmp(Long.MIN_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, -1);
         cmp(Long.MIN_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, -1);
 
+        cmp(Instant.MIN, Long.MIN_VALUE, DAYS, 1);
+        cmp(Instant.MIN, Long.MIN_VALUE, HOURS, 1);
+        cmp(Instant.MIN, Long.MIN_VALUE, MINUTES, 1);
+        cmp(Instant.MIN, Long.MIN_VALUE, SECONDS, 1);
+        cmp(Instant.MIN, Instant.MIN.getEpochSecond() - 1, SECONDS, 1);
+        cmp(Instant.MIN, Instant.MIN.getEpochSecond() - 100, SECONDS, 1);
+        cmp(Instant.MIN, Instant.MIN.getEpochSecond(), SECONDS, 0);
+
+        cmp(Instant.MAX, Long.MAX_VALUE, DAYS, -1);
+        cmp(Instant.MAX, Long.MAX_VALUE, HOURS, -1);
+        cmp(Instant.MAX, Long.MAX_VALUE, MINUTES, -1);
+        cmp(Instant.MAX, Long.MAX_VALUE, SECONDS, -1);
+        cmp(Instant.MAX, Instant.MAX.getEpochSecond() + 1, SECONDS, -1);
+        cmp(Instant.MAX, Instant.MAX.getEpochSecond() + 100, SECONDS, -1);
+        cmp(Instant.MAX, Instant.MAX.getEpochSecond(), SECONDS, 0);
+
+        cmp(nowInstant, now, MILLISECONDS, 0);
+        cmp(nowInstant, now*1000L, MICROSECONDS, 0);
+        cmp(nowInstant, now-1234, MILLISECONDS, 1);
+        cmp(nowInstant, now+1234, MILLISECONDS, -1);
+        cmp(nowInstant, tomorrowInDays, DAYS, -1);
+        cmp(nowInstant, yesterdayInDays, DAYS, 1);
+
         // to(TimeUnit)
         to(MILLISECONDS.convert(1, DAYS) - 1, MILLISECONDS);
         to(MILLISECONDS.convert(1, DAYS) + 0, MILLISECONDS);
@@ -77,6 +112,64 @@
             to(Long.MAX_VALUE, unit);
         }
 
+        // toInstant()
+        int N = 1000;
+        for (TimeUnit unit : EnumSet.allOf(TimeUnit.class)) {
+            for (int i = 0; i < N; i++) {
+                long value = rand.nextLong();
+                FileTime ft = FileTime.from(value, unit);
+                Instant instant = ft.toInstant();
+                if (instant != Instant.MIN && instant != Instant.MAX) {
+                    eqTime(value, unit, instant);
+                }
+            }
+        }
+        for (TimeUnit unit : EnumSet.allOf(TimeUnit.class)) {
+            long value = Long.MIN_VALUE;
+            FileTime ft = FileTime.from(value, unit);
+            Instant instant = ft.toInstant();
+            if (unit.compareTo(TimeUnit.SECONDS) < 0) {
+                eqTime(value, unit, instant);
+            } else if (!instant.equals(Instant.MIN)) {
+                throw new RuntimeException("should overflow to MIN");
+            }
+            value = Long.MAX_VALUE;
+            ft = FileTime.from(value, unit);
+            instant = ft.toInstant();
+            if (unit.compareTo(TimeUnit.SECONDS) < 0) {
+                eqTime(value, unit, instant);
+            } else if (!instant.equals(Instant.MAX)) {
+                throw new RuntimeException("should overflow to MAX");
+            }
+        }
+
+        // from(Instant)
+        final long MAX_SECOND = 31556889864403199L;
+        for (int i = 0; i < N; i++) {
+            long v = rand.nextLong();
+            long secs = v % MAX_SECOND;
+            Instant instant = Instant.ofEpochSecond(secs, rand.nextInt(1000_000_000));
+            FileTime ft = FileTime.from(instant);
+            if (!ft.toInstant().equals(instant) || ft.to(SECONDS)  != secs) {
+                throw new RuntimeException("from(Instant) failed");
+            }
+            long millis = v;
+            instant = Instant.ofEpochMilli(millis);
+            ft = FileTime.from(instant);
+            if (!ft.toInstant().equals(instant) ||
+                ft.toMillis()  != instant.toEpochMilli()) {
+                throw new RuntimeException("from(Instant) failed");
+            }
+            long nanos = v;
+            ft = FileTime.from(nanos, NANOSECONDS);
+            secs = nanos / 1000_000_000;
+            nanos = nanos % 1000_000_000;
+            instant = Instant.ofEpochSecond(secs, nanos);
+            if (!ft.equals(FileTime.from(instant))) {
+                throw new RuntimeException("from(Instant) failed");
+            }
+        }
+
         // toString
         ts(1L, DAYS, "1970-01-02T00:00:00Z");
         ts(1L, HOURS, "1970-01-01T01:00:00Z");
@@ -108,11 +201,18 @@
         // NTFS epoch in usec.
         ts(-11644473600000000L, MICROSECONDS, "1601-01-01T00:00:00Z");
 
-        // nulls
+        ts(Instant.MIN, "-1000000001-01-01T00:00:00Z");
+        ts(Instant.MAX, "1000000000-12-31T23:59:59.999999999Z");
+
         try {
             FileTime.from(0L, null);
             throw new RuntimeException("NullPointerException expected");
         } catch (NullPointerException npe) { }
+        try {
+            FileTime.from(null);
+            throw new RuntimeException("NullPointerException expected");
+        } catch (NullPointerException npe) { }
+
         FileTime time = FileTime.fromMillis(now);
         if (time.equals(null))
             throw new RuntimeException("should not be equal to null");
@@ -120,6 +220,39 @@
             time.compareTo(null);
             throw new RuntimeException("NullPointerException expected");
         } catch (NullPointerException npe) { }
+
+        // Instant + toMilli() overflow
+        overflow(Long.MAX_VALUE,
+                 FileTime.from(Instant.MAX).toMillis());
+        overflow(Long.MAX_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000 + 1))
+                         .toMillis());
+        overflow(Long.MIN_VALUE,
+                 FileTime.from(Instant.MIN).toMillis());
+        overflow(Long.MIN_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000 - 1))
+                         .toMillis());
+
+        // Instant + to(TimeUnit) overflow
+        overflow(Long.MAX_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000 + 1))
+                         .to(MILLISECONDS));
+        overflow(Long.MAX_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000,
+                                                     MILLISECONDS.toNanos(1000)))
+                    .to(MILLISECONDS));
+        overflow(Long.MIN_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000 - 1))
+                         .to(MILLISECONDS));
+        overflow(Long.MIN_VALUE,
+                 FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000,
+                                                     -MILLISECONDS.toNanos(1)))
+                         .to(MILLISECONDS));
+    }
+
+    static void overflow(long minmax, long v) {
+        if (v != minmax)
+            throw new RuntimeException("saturates to Long.MIN/MAX_VALUE expected");
     }
 
     static void cmp(long v1, TimeUnit u1, long v2, TimeUnit u2, int expected) {
@@ -128,6 +261,12 @@
             throw new RuntimeException("unexpected order");
     }
 
+    static void cmp(Instant ins, long v2, TimeUnit u2, int expected) {
+        int result = FileTime.from(ins).compareTo(FileTime.from(v2, u2));
+        if (result != expected)
+            throw new RuntimeException("unexpected order");
+    }
+
     static void eq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
         FileTime t1 = FileTime.from(v1, u1);
         FileTime t2 = FileTime.from(v2, u2);
@@ -137,6 +276,28 @@
             throw new RuntimeException("hashCodes should be equal");
     }
 
+    static void eq(Instant ins, long v2, TimeUnit u2) {
+        FileTime t1 = FileTime.from(ins);
+        FileTime t2 = FileTime.from(v2, u2);
+        if (!t1.equals(t2))
+            throw new RuntimeException("not equal");
+        if (t1.hashCode() != t2.hashCode())
+            throw new RuntimeException("hashCodes should be equal");
+    }
+
+    static void eqTime(long value, TimeUnit unit, Instant instant) {
+        long secs = SECONDS.convert(value, unit);
+        long nanos = NANOSECONDS.convert(value - unit.convert(secs, SECONDS), unit);
+        if (nanos < 0) {    // normalize nanoOfSecond to positive
+            secs -= 1;
+            nanos += 1000_000_000;
+        }
+        if (secs != instant.getEpochSecond() || (int)nanos != instant.getNano()) {
+            System.err.println(" ins=" + instant);
+            throw new RuntimeException("ft and instant are not the same time point");
+        }
+    }
+
     static void neq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
         FileTime t1 = FileTime.from(v1, u1);
         FileTime t2 = FileTime.from(v2, u2);
@@ -144,6 +305,13 @@
             throw new RuntimeException("should not be equal");
     }
 
+    static void neq(Instant ins, long v2, TimeUnit u2) {
+        FileTime t1 = FileTime.from(ins);
+        FileTime t2 = FileTime.from(v2, u2);
+        if (t1.equals(t2))
+            throw new RuntimeException("should not be equal");
+    }
+
     static void to(long v, TimeUnit unit) {
         FileTime t = FileTime.from(v, unit);
         for (TimeUnit u: TimeUnit.values()) {
@@ -164,4 +332,14 @@
             throw new RuntimeException();
         }
     }
+
+    static void ts(Instant instant, String expected) {
+        String result = FileTime.from(instant).toString();
+        if (!result.equals(expected)) {
+            System.err.format("FileTime.from(%s).toString() failed\n", instant);
+            System.err.format("Expected: %s\n", expected);
+            System.err.format("     Got: %s\n", result);
+            throw new RuntimeException();
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Comparators/BasicTest.java	Tue Apr 16 01:44:58 2013 -0700
@@ -0,0 +1,412 @@
+/*
+ * 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 8001667 8010279
+ * @run testng BasicTest
+ */
+
+import java.util.Comparator;
+import java.util.Comparators;
+import java.util.AbstractMap;
+import java.util.Map;
+import org.testng.annotations.Test;
+
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+import java.util.function.ToDoubleFunction;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.fail;
+
+/**
+ * Unit tests for helper methods in Comparators
+ */
+@Test(groups = "unit")
+public class BasicTest {
+    private static class Thing {
+        public final int intField;
+        public final long longField;
+        public final double doubleField;
+        public final String stringField;
+
+        private Thing(int intField, long longField, double doubleField, String stringField) {
+            this.intField = intField;
+            this.longField = longField;
+            this.doubleField = doubleField;
+            this.stringField = stringField;
+        }
+
+        public int getIntField() {
+            return intField;
+        }
+
+        public long getLongField() {
+            return longField;
+        }
+
+        public double getDoubleField() {
+            return doubleField;
+        }
+
+        public String getStringField() {
+            return stringField;
+        }
+    }
+
+    private final int[] intValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
+    private final long[] longValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
+    private final double[] doubleValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
+    private final String[] stringValues = { "a", "a", "b", "b", "c", "c", "d", "d", "e", "e" };
+    private final int[] comparisons = { 0, -1, 0, -1, 0, -1, 0, -1, 0 };
+
+    private<T> void assertComparisons(T[] things, Comparator<T> comp, int[] comparisons) {
+        for (int i=0; i<comparisons.length; i++) {
+            assertEquals(comparisons.length + 1, things.length);
+            assertEquals(comparisons[i], comp.compare(things[i], things[i+1]));
+            assertEquals(-comparisons[i], comp.compare(things[i+1], things[i]));
+        }
+    }
+
+    public void testIntComparator() {
+        Thing[] things = new Thing[intValues.length];
+        for (int i=0; i<intValues.length; i++)
+            things[i] = new Thing(intValues[i], 0L, 0.0, null);
+        Comparator<Thing> comp = Comparators.comparing(new ToIntFunction<BasicTest.Thing>() {
+            @Override
+            public int applyAsInt(Thing thing) {
+                return thing.getIntField();
+            }
+        });
+
+        assertComparisons(things, comp, comparisons);
+    }
+
+    public void testLongComparator() {
+        Thing[] things = new Thing[longValues.length];
+        for (int i=0; i<longValues.length; i++)
+            things[i] = new Thing(0, longValues[i], 0.0, null);
+        Comparator<Thing> comp = Comparators.comparing(new ToLongFunction<BasicTest.Thing>() {
+            @Override
+            public long applyAsLong(Thing thing) {
+                return thing.getLongField();
+            }
+        });
+
+        assertComparisons(things, comp, comparisons);
+    }
+
+    public void testDoubleComparator() {
+        Thing[] things = new Thing[doubleValues.length];
+        for (int i=0; i<doubleValues.length; i++)
+            things[i] = new Thing(0, 0L, doubleValues[i], null);
+        Comparator<Thing> comp = Comparators.comparing(new ToDoubleFunction<BasicTest.Thing>() {
+            @Override
+            public double applyAsDouble(Thing thing) {
+                return thing.getDoubleField();
+            }
+        });
+
+        assertComparisons(things, comp, comparisons);
+    }
+
+    public void testComparing() {
+        Thing[] things = new Thing[doubleValues.length];
+        for (int i=0; i<doubleValues.length; i++)
+            things[i] = new Thing(0, 0L, 0.0, stringValues[i]);
+        Comparator<Thing> comp = Comparators.comparing(new Function<Thing, String>() {
+            @Override
+            public String apply(Thing thing) {
+                return thing.getStringField();
+            }
+        });
+
+        assertComparisons(things, comp, comparisons);
+    }
+
+    public void testNaturalOrderComparator() {
+        Comparator<String> comp = Comparators.naturalOrder();
+
+        assertComparisons(stringValues, comp, comparisons);
+    }
+
+    public void testReverseComparator() {
+        Comparator<String> cmpr = Comparators.reverseOrder();
+        Comparator<String> cmp = cmpr.reverseOrder();
+
+        assertEquals(cmp.reverseOrder(), cmpr);
+        assertEquals(0, cmp.compare("a", "a"));
+        assertEquals(0, cmpr.compare("a", "a"));
+        assertTrue(cmp.compare("a", "b") < 0);
+        assertTrue(cmpr.compare("a", "b") > 0);
+        assertTrue(cmp.compare("b", "a") > 0);
+        assertTrue(cmpr.compare("b", "a") < 0);
+    }
+
+    public void testReverseComparator2() {
+        Comparator<String> cmp = (s1, s2) -> s1.length() - s2.length();
+        Comparator<String> cmpr = cmp.reverseOrder();
+
+        assertEquals(cmpr.reverseOrder(), cmp);
+        assertEquals(0, cmp.compare("abc", "def"));
+        assertEquals(0, cmpr.compare("abc", "def"));
+        assertTrue(cmp.compare("abcd", "def") > 0);
+        assertTrue(cmpr.compare("abcd", "def") < 0);
+        assertTrue(cmp.compare("abc", "defg") < 0);
+        assertTrue(cmpr.compare("abc", "defg") > 0);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void testReverseComparatorNPE() {
+        Comparator<String> cmp = Comparators.reverseOrder(null);
+    }
+
+    public void testComposeComparator() {
+        // Longer string in front
+        Comparator<String> first = (s1, s2) -> s2.length() - s1.length();
+        Comparator<String> second = Comparators.naturalOrder();
+        Comparator<String> composed = Comparators.compose(first, second);
+
+        assertTrue(composed.compare("abcdefg", "abcdef") < 0);
+        assertTrue(composed.compare("abcdef", "abcdefg") > 0);
+        assertTrue(composed.compare("abcdef", "abcdef") == 0);
+        assertTrue(composed.compare("abcdef", "ghijkl") < 0);
+        assertTrue(composed.compare("ghijkl", "abcdefg") > 0);
+    }
+
+    private <K, V> void assertPairComparison(K k1, V v1, K k2, V v2,
+                                        Comparator<Map.Entry<K, V>> ck,
+                                        Comparator<Map.Entry<K, V>> cv) {
+        final Map.Entry<K, V> p11 = new AbstractMap.SimpleImmutableEntry<>(k1, v1);
+        final Map.Entry<K, V> p12 = new AbstractMap.SimpleImmutableEntry<>(k1, v2);
+        final Map.Entry<K, V> p21 = new AbstractMap.SimpleImmutableEntry<>(k2, v1);
+        final Map.Entry<K, V> p22 = new AbstractMap.SimpleImmutableEntry<>(k2, v2);
+
+        assertTrue(ck.compare(p11, p11) == 0);
+        assertTrue(ck.compare(p12, p11) == 0);
+        assertTrue(ck.compare(p11, p12) == 0);
+        assertTrue(ck.compare(p12, p22) < 0);
+        assertTrue(ck.compare(p12, p21) < 0);
+        assertTrue(ck.compare(p21, p11) > 0);
+        assertTrue(ck.compare(p21, p12) > 0);
+
+        assertTrue(cv.compare(p11, p11) == 0);
+        assertTrue(cv.compare(p12, p11) > 0);
+        assertTrue(cv.compare(p11, p12) < 0);
+        assertTrue(cv.compare(p12, p22) == 0);
+        assertTrue(cv.compare(p12, p21) > 0);
+        assertTrue(cv.compare(p21, p11) == 0);
+        assertTrue(cv.compare(p21, p12) < 0);
+
+        Comparator<Map.Entry<K, V>> cmp = Comparators.compose(ck, cv);
+        assertTrue(cmp.compare(p11, p11) == 0);
+        assertTrue(cmp.compare(p12, p11) > 0);
+        assertTrue(cmp.compare(p11, p12) < 0);
+        assertTrue(cmp.compare(p12, p22) < 0);
+        assertTrue(cmp.compare(p12, p21) < 0);
+        assertTrue(cmp.compare(p21, p11) > 0);
+        assertTrue(cmp.compare(p21, p12) > 0);
+
+        cmp = Comparators.compose(cv, ck);
+        assertTrue(cmp.compare(p11, p11) == 0);
+        assertTrue(cmp.compare(p12, p11) > 0);
+        assertTrue(cmp.compare(p11, p12) < 0);
+        assertTrue(cmp.compare(p12, p22) < 0);
+        assertTrue(cmp.compare(p12, p21) > 0);
+        assertTrue(cmp.compare(p21, p11) > 0);
+        assertTrue(cmp.compare(p21, p12) < 0);
+    }
+
+    public void testKVComparatorable() {
+        assertPairComparison(1, "ABC", 2, "XYZ",
+                         Comparators.<Integer, String>naturalOrderKeys(),
+                         Comparators.<Integer, String>naturalOrderValues());
+    }
+
+    private static class People {
+        final String firstName;
+        final String lastName;
+        final int age;
+
+        People(String first, String last, int age) {
+            firstName = first;
+            lastName = last;
+            this.age = age;
+        }
+
+        String getFirstName() { return firstName; }
+        String getLastName() { return lastName; }
+        int getAge() { return age; }
+        long getAgeAsLong() { return (long) age; };
+        double getAgeAsDouble() { return (double) age; };
+    }
+
+    private final People people[] = {
+        new People("John", "Doe", 34),
+        new People("Mary", "Doe", 30),
+        new People("Maria", "Doe", 14),
+        new People("Jonah", "Doe", 10),
+        new People("John", "Cook", 54),
+        new People("Mary", "Cook", 50),
+    };
+
+    public void testKVComparators() {
+        // Comparator<People> cmp = Comparators.naturalOrder(); // Should fail to compiler as People is not comparable
+        // We can use simple comparator, but those have been tested above.
+        // Thus choose to do compose for some level of interation.
+        Comparator<People> cmp1 = Comparators.comparing((Function<People, String>) People::getFirstName);
+        Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
+        Comparator<People> cmp = Comparators.compose(cmp1, cmp2);
+
+        assertPairComparison(people[0], people[0], people[1], people[1],
+                         Comparators.<People, People>byKey(cmp),
+                         Comparators.<People, People>byValue(cmp));
+
+    }
+
+    private <T> void assertComparison(Comparator<T> cmp, T less, T greater) {
+        assertTrue(cmp.compare(less, greater) < 0, "less");
+        assertTrue(cmp.compare(less, less) == 0, "equal");
+        assertTrue(cmp.compare(greater, less) > 0, "greater");
+    }
+
+    public void testComparatorDefaultMethods() {
+        Comparator<People> cmp = Comparators.comparing((Function<People, String>) People::getFirstName);
+        Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
+        // reverseOrder
+        assertComparison(cmp.reverseOrder(), people[1], people[0]);
+        // thenComparing(Comparator)
+        assertComparison(cmp.thenComparing(cmp2), people[0], people[1]);
+        assertComparison(cmp.thenComparing(cmp2), people[4], people[0]);
+        // thenComparing(Function)
+        assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]);
+        assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]);
+        // thenComparing(ToIntFunction)
+        assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]);
+        assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]);
+        // thenComparing(ToLongFunction)
+        assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]);
+        assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]);
+        // thenComparing(ToDoubleFunction)
+        assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]);
+        assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]);
+    }
+
+    public void testGreaterOf() {
+        // lesser
+        assertSame(Comparators.greaterOf(Comparators.comparing(
+                                    (Function<People, String>) People::getFirstName))
+                              .apply(people[0], people[1]),
+                   people[1]);
+        // euqal
+        assertSame(Comparators.greaterOf(Comparators.comparing(
+                                    (Function<People, String>) People::getLastName))
+                              .apply(people[0], people[1]),
+                   people[0]);
+        // greater
+        assertSame(Comparators.greaterOf(Comparators.comparing(
+                                    (ToIntFunction<People>) People::getAge))
+                              .apply(people[0], people[1]),
+                   people[0]);
+    }
+
+    public void testLesserOf() {
+        // lesser
+        assertSame(Comparators.lesserOf(Comparators.comparing(
+                                    (Function<People, String>) People::getFirstName))
+                              .apply(people[0], people[1]),
+                   people[0]);
+        // euqal
+        assertSame(Comparators.lesserOf(Comparators.comparing(
+                                    (Function<People, String>) People::getLastName))
+                              .apply(people[0], people[1]),
+                   people[0]);
+        // greater
+        assertSame(Comparators.lesserOf(Comparators.comparing(
+                                    (ToIntFunction<People>) People::getAge))
+                              .apply(people[0], people[1]),
+                   people[1]);
+    }
+
+    public void testNulls() {
+        try {
+            Comparators.<String>naturalOrder().compare("abc", (String) null);
+            fail("expected NPE with naturalOrder");
+        } catch (NullPointerException npe) {}
+        try {
+            Comparators.<String>naturalOrder().compare((String) null, "abc");
+            fail("expected NPE with naturalOrder");
+        } catch (NullPointerException npe) {}
+
+        try {
+            Comparators.<String>reverseOrder().compare("abc", (String) null);
+            fail("expected NPE with naturalOrder");
+        } catch (NullPointerException npe) {}
+        try {
+            Comparators.<String>reverseOrder().compare((String) null, "abc");
+            fail("expected NPE with naturalOrder");
+        } catch (NullPointerException npe) {}
+
+        try {
+            Comparator<Map.Entry<String, String>> cmp = Comparators.byKey(null);
+            fail("byKey(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+
+        try {
+            Comparator<Map.Entry<String, String>> cmp = Comparators.byValue(null);
+            fail("byValue(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+
+        try {
+            Comparator<People> cmp = Comparators.comparing((Function<People, String>) null);
+            fail("comparing(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+        try {
+            Comparator<People> cmp = Comparators.comparing((ToIntFunction<People>) null);
+            fail("comparing(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+        try {
+            Comparator<People> cmp = Comparators.comparing((ToLongFunction<People>) null);
+            fail("comparing(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+        try {
+            Comparator<People> cmp = Comparators.comparing((ToDoubleFunction<People>) null);
+            fail("comparing(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+
+        try {
+            BinaryOperator<String> op = Comparators.lesserOf(null);
+            fail("lesserOf(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+
+        try {
+            BinaryOperator<String> op = Comparators.greaterOf(null);
+            fail("lesserOf(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+    }
+}
--- a/jdk/test/java/util/ComparatorsTest.java	Fri Apr 12 10:42:50 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,353 +0,0 @@
-/*
- * 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 8001667
- * @run testng ComparatorsTest
- */
-
-import java.util.Comparator;
-import java.util.Comparators;
-import java.util.AbstractMap;
-import java.util.Map;
-import org.testng.annotations.Test;
-
-import java.util.function.Function;
-import java.util.function.ToIntFunction;
-import java.util.function.ToLongFunction;
-import java.util.function.ToDoubleFunction;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertSame;
-
-/**
- * Unit tests for helper methods in Comparators
- */
-@Test(groups = "unit")
-public class ComparatorsTest {
-    private static class Thing {
-        public final int intField;
-        public final long longField;
-        public final double doubleField;
-        public final String stringField;
-
-        private Thing(int intField, long longField, double doubleField, String stringField) {
-            this.intField = intField;
-            this.longField = longField;
-            this.doubleField = doubleField;
-            this.stringField = stringField;
-        }
-
-        public int getIntField() {
-            return intField;
-        }
-
-        public long getLongField() {
-            return longField;
-        }
-
-        public double getDoubleField() {
-            return doubleField;
-        }
-
-        public String getStringField() {
-            return stringField;
-        }
-    }
-
-    private final int[] intValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
-    private final long[] longValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
-    private final double[] doubleValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
-    private final String[] stringValues = { "a", "a", "b", "b", "c", "c", "d", "d", "e", "e" };
-    private final int[] comparisons = { 0, -1, 0, -1, 0, -1, 0, -1, 0 };
-
-    private<T> void assertComparisons(T[] things, Comparator<T> comp, int[] comparisons) {
-        for (int i=0; i<comparisons.length; i++) {
-            assertEquals(comparisons.length + 1, things.length);
-            assertEquals(comparisons[i], comp.compare(things[i], things[i+1]));
-            assertEquals(-comparisons[i], comp.compare(things[i+1], things[i]));
-        }
-    }
-
-    public void testIntComparator() {
-        Thing[] things = new Thing[intValues.length];
-        for (int i=0; i<intValues.length; i++)
-            things[i] = new Thing(intValues[i], 0L, 0.0, null);
-        Comparator<Thing> comp = Comparators.comparing(new ToIntFunction<ComparatorsTest.Thing>() {
-            @Override
-            public int applyAsInt(Thing thing) {
-                return thing.getIntField();
-            }
-        });
-
-        assertComparisons(things, comp, comparisons);
-    }
-
-    public void testLongComparator() {
-        Thing[] things = new Thing[longValues.length];
-        for (int i=0; i<longValues.length; i++)
-            things[i] = new Thing(0, longValues[i], 0.0, null);
-        Comparator<Thing> comp = Comparators.comparing(new ToLongFunction<ComparatorsTest.Thing>() {
-            @Override
-            public long applyAsLong(Thing thing) {
-                return thing.getLongField();
-            }
-        });
-
-        assertComparisons(things, comp, comparisons);
-    }
-
-    public void testDoubleComparator() {
-        Thing[] things = new Thing[doubleValues.length];
-        for (int i=0; i<doubleValues.length; i++)
-            things[i] = new Thing(0, 0L, doubleValues[i], null);
-        Comparator<Thing> comp = Comparators.comparing(new ToDoubleFunction<ComparatorsTest.Thing>() {
-            @Override
-            public double applyAsDouble(Thing thing) {
-                return thing.getDoubleField();
-            }
-        });
-
-        assertComparisons(things, comp, comparisons);
-    }
-
-    public void testComparing() {
-        Thing[] things = new Thing[doubleValues.length];
-        for (int i=0; i<doubleValues.length; i++)
-            things[i] = new Thing(0, 0L, 0.0, stringValues[i]);
-        Comparator<Thing> comp = Comparators.comparing(new Function<Thing, String>() {
-            @Override
-            public String apply(Thing thing) {
-                return thing.getStringField();
-            }
-        });
-
-        assertComparisons(things, comp, comparisons);
-    }
-
-    public void testNaturalOrderComparator() {
-        Comparator<String> comp = Comparators.naturalOrder();
-
-        assertComparisons(stringValues, comp, comparisons);
-    }
-
-    public void testReverseComparator() {
-        Comparator<String> cmpr = Comparators.reverseOrder();
-        Comparator<String> cmp = cmpr.reverseOrder();
-
-        assertEquals(cmp.reverseOrder(), cmpr);
-        assertEquals(0, cmp.compare("a", "a"));
-        assertEquals(0, cmpr.compare("a", "a"));
-        assertTrue(cmp.compare("a", "b") < 0);
-        assertTrue(cmpr.compare("a", "b") > 0);
-        assertTrue(cmp.compare("b", "a") > 0);
-        assertTrue(cmpr.compare("b", "a") < 0);
-    }
-
-    public void testReverseComparator2() {
-        Comparator<String> cmp = (s1, s2) -> s1.length() - s2.length();
-        Comparator<String> cmpr = cmp.reverseOrder();
-
-        assertEquals(cmpr.reverseOrder(), cmp);
-        assertEquals(0, cmp.compare("abc", "def"));
-        assertEquals(0, cmpr.compare("abc", "def"));
-        assertTrue(cmp.compare("abcd", "def") > 0);
-        assertTrue(cmpr.compare("abcd", "def") < 0);
-        assertTrue(cmp.compare("abc", "defg") < 0);
-        assertTrue(cmpr.compare("abc", "defg") > 0);
-    }
-
-    @Test(expectedExceptions=NullPointerException.class)
-    public void testReverseComparatorNPE() {
-        Comparator<String> cmp = Comparators.reverseOrder(null);
-    }
-
-    public void testComposeComparator() {
-        // Longer string in front
-        Comparator<String> first = (s1, s2) -> s2.length() - s1.length();
-        Comparator<String> second = Comparators.naturalOrder();
-        Comparator<String> composed = Comparators.compose(first, second);
-
-        assertTrue(composed.compare("abcdefg", "abcdef") < 0);
-        assertTrue(composed.compare("abcdef", "abcdefg") > 0);
-        assertTrue(composed.compare("abcdef", "abcdef") == 0);
-        assertTrue(composed.compare("abcdef", "ghijkl") < 0);
-        assertTrue(composed.compare("ghijkl", "abcdefg") > 0);
-    }
-
-    private <K, V> void assertPairComparison(K k1, V v1, K k2, V v2,
-                                        Comparator<Map.Entry<K, V>> ck,
-                                        Comparator<Map.Entry<K, V>> cv) {
-        final Map.Entry<K, V> p11 = new AbstractMap.SimpleImmutableEntry<>(k1, v1);
-        final Map.Entry<K, V> p12 = new AbstractMap.SimpleImmutableEntry<>(k1, v2);
-        final Map.Entry<K, V> p21 = new AbstractMap.SimpleImmutableEntry<>(k2, v1);
-        final Map.Entry<K, V> p22 = new AbstractMap.SimpleImmutableEntry<>(k2, v2);
-
-        assertTrue(ck.compare(p11, p11) == 0);
-        assertTrue(ck.compare(p12, p11) == 0);
-        assertTrue(ck.compare(p11, p12) == 0);
-        assertTrue(ck.compare(p12, p22) < 0);
-        assertTrue(ck.compare(p12, p21) < 0);
-        assertTrue(ck.compare(p21, p11) > 0);
-        assertTrue(ck.compare(p21, p12) > 0);
-
-        assertTrue(cv.compare(p11, p11) == 0);
-        assertTrue(cv.compare(p12, p11) > 0);
-        assertTrue(cv.compare(p11, p12) < 0);
-        assertTrue(cv.compare(p12, p22) == 0);
-        assertTrue(cv.compare(p12, p21) > 0);
-        assertTrue(cv.compare(p21, p11) == 0);
-        assertTrue(cv.compare(p21, p12) < 0);
-
-        Comparator<Map.Entry<K, V>> cmp = Comparators.compose(ck, cv);
-        assertTrue(cmp.compare(p11, p11) == 0);
-        assertTrue(cmp.compare(p12, p11) > 0);
-        assertTrue(cmp.compare(p11, p12) < 0);
-        assertTrue(cmp.compare(p12, p22) < 0);
-        assertTrue(cmp.compare(p12, p21) < 0);
-        assertTrue(cmp.compare(p21, p11) > 0);
-        assertTrue(cmp.compare(p21, p12) > 0);
-
-        cmp = Comparators.compose(cv, ck);
-        assertTrue(cmp.compare(p11, p11) == 0);
-        assertTrue(cmp.compare(p12, p11) > 0);
-        assertTrue(cmp.compare(p11, p12) < 0);
-        assertTrue(cmp.compare(p12, p22) < 0);
-        assertTrue(cmp.compare(p12, p21) > 0);
-        assertTrue(cmp.compare(p21, p11) > 0);
-        assertTrue(cmp.compare(p21, p12) < 0);
-    }
-
-    public void testKVComparatorable() {
-        assertPairComparison(1, "ABC", 2, "XYZ",
-                         Comparators.<Integer, String>naturalOrderKeys(),
-                         Comparators.<Integer, String>naturalOrderValues());
-    }
-
-    private static class People {
-        final String firstName;
-        final String lastName;
-        final int age;
-
-        People(String first, String last, int age) {
-            firstName = first;
-            lastName = last;
-            this.age = age;
-        }
-
-        String getFirstName() { return firstName; }
-        String getLastName() { return lastName; }
-        int getAge() { return age; }
-        long getAgeAsLong() { return (long) age; };
-        double getAgeAsDouble() { return (double) age; };
-    }
-
-    private final People people[] = {
-        new People("John", "Doe", 34),
-        new People("Mary", "Doe", 30),
-        new People("Maria", "Doe", 14),
-        new People("Jonah", "Doe", 10),
-        new People("John", "Cook", 54),
-        new People("Mary", "Cook", 50),
-    };
-
-    public void testKVComparators() {
-        // Comparator<People> cmp = Comparators.naturalOrder(); // Should fail to compiler as People is not comparable
-        // We can use simple comparator, but those have been tested above.
-        // Thus choose to do compose for some level of interation.
-        Comparator<People> cmp1 = Comparators.comparing((Function<People, String>) People::getFirstName);
-        Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
-        Comparator<People> cmp = Comparators.compose(cmp1, cmp2);
-
-        assertPairComparison(people[0], people[0], people[1], people[1],
-                         Comparators.<People, People>byKey(cmp),
-                         Comparators.<People, People>byValue(cmp));
-
-    }
-
-    private <T> void assertComparison(Comparator<T> cmp, T less, T greater) {
-        assertTrue(cmp.compare(less, greater) < 0, "less");
-        assertTrue(cmp.compare(less, less) == 0, "equal");
-        assertTrue(cmp.compare(greater, less) > 0, "greater");
-    }
-
-    public void testComparatorDefaultMethods() {
-        Comparator<People> cmp = Comparators.comparing((Function<People, String>) People::getFirstName);
-        Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
-        // reverseOrder
-        assertComparison(cmp.reverseOrder(), people[1], people[0]);
-        // thenComparing(Comparator)
-        assertComparison(cmp.thenComparing(cmp2), people[0], people[1]);
-        assertComparison(cmp.thenComparing(cmp2), people[4], people[0]);
-        // thenComparing(Function)
-        assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]);
-        assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]);
-        // thenComparing(ToIntFunction)
-        assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]);
-        assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]);
-        // thenComparing(ToLongFunction)
-        assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]);
-        assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]);
-        // thenComparing(ToDoubleFunction)
-        assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]);
-        assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]);
-    }
-
-    public void testGreaterOf() {
-        // lesser
-        assertSame(Comparators.greaterOf(Comparators.comparing(
-                                    (Function<People, String>) People::getFirstName))
-                              .apply(people[0], people[1]),
-                   people[1]);
-        // euqal
-        assertSame(Comparators.greaterOf(Comparators.comparing(
-                                    (Function<People, String>) People::getLastName))
-                              .apply(people[0], people[1]),
-                   people[0]);
-        // greater
-        assertSame(Comparators.greaterOf(Comparators.comparing(
-                                    (ToIntFunction<People>) People::getAge))
-                              .apply(people[0], people[1]),
-                   people[0]);
-    }
-
-    public void testLesserOf() {
-        // lesser
-        assertSame(Comparators.lesserOf(Comparators.comparing(
-                                    (Function<People, String>) People::getFirstName))
-                              .apply(people[0], people[1]),
-                   people[0]);
-        // euqal
-        assertSame(Comparators.lesserOf(Comparators.comparing(
-                                    (Function<People, String>) People::getLastName))
-                              .apply(people[0], people[1]),
-                   people[0]);
-        // greater
-        assertSame(Comparators.lesserOf(Comparators.comparing(
-                                    (ToIntFunction<People>) People::getAge))
-                              .apply(people[0], people[1]),
-                   people[1]);
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Map/BasicSerialization.java	Tue Apr 16 01:44:58 2013 -0700
@@ -0,0 +1,221 @@
+/*
+ * 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 8011200
+ * @run testng BasicSerialization
+ * @summary Ensure Maps can be serialized and deserialized.
+ * @author Mike Duigou
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.fail;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+
+public class BasicSerialization {
+
+    enum IntegerEnum {
+
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
+        e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
+        e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
+        e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
+        e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
+        e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
+        e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
+        e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
+        e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
+        e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
+        EXTRA_KEY;
+        public static final int SIZE = values().length;
+    };
+    private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
+    /**
+     * Realized keys ensure that there is always a hard ref to all test objects.
+     */
+    private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
+    /**
+     * Realized values ensure that there is always a hard ref to all test
+     * objects.
+     */
+    private static final String[] VALUES = new String[TEST_SIZE];
+
+    static {
+        IntegerEnum[] keys = IntegerEnum.values();
+        for (int each = 0; each < TEST_SIZE; each++) {
+            KEYS[each] = keys[each];
+            VALUES[each] = keys[each].name();
+        }
+    }
+    private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
+    private static final String EXTRA_VALUE = IntegerEnum.EXTRA_KEY.name();
+
+    public static <K, V> Map<K, V> mapClone(Map<K, V> map) {
+        Method cloneMethod;
+
+        try {
+            cloneMethod = map.getClass().getMethod("clone", new Class[]{});
+        } catch (NoSuchMethodException | SecurityException all) {
+            cloneMethod = null;
+        }
+
+        if (null != cloneMethod) {
+            try {
+                Map<K, V> result = (Map<K, V>)cloneMethod.invoke(map, new Object[]{});
+                return result;
+            } catch (Exception all) {
+                fail("clone() failed " + map.getClass().getSimpleName(), all);
+                return null;
+            }
+        } else {
+            Constructor<? extends Map> copyConstructor;
+            try {
+                copyConstructor = (Constructor<? extends Map>)map.getClass().getConstructor(new Class[]{Map.class});
+
+                Map<K, V> result = (Map<K, V>)copyConstructor.newInstance(new Object[]{map});
+
+                return result;
+            } catch (Exception all) {
+                return serialClone(map);
+            }
+        }
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String>")
+    public void testSerialization(String description, Map<IntegerEnum, String> map) {
+        Object foo = new Object();
+
+        Map<IntegerEnum, String> clone = mapClone(map);
+        Map<IntegerEnum, String> serialClone = serialClone(map);
+
+        assertEquals(map, map, description + ":should equal self");
+        assertEquals(clone, map, description + ":should equal clone");
+        assertEquals(map, clone, description + ": should equal orginal map");
+        assertEquals(serialClone, map, description + ": should equal deserialized clone");
+        assertEquals(map, serialClone, description + ": should equal original map");
+        assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
+        assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
+
+        assertFalse(map.containsKey(EXTRA_KEY), description + ":unexpected key");
+        assertFalse(clone.containsKey(EXTRA_KEY), description + ":unexpected key");
+        assertFalse(serialClone.containsKey(EXTRA_KEY), description + ":unexpected key");
+        map.put(EXTRA_KEY, EXTRA_VALUE);
+        clone.put(EXTRA_KEY, EXTRA_VALUE);
+        serialClone.put(EXTRA_KEY, EXTRA_VALUE);
+        assertTrue(map.containsKey(EXTRA_KEY), description + ":missing key");
+        assertTrue(clone.containsKey(EXTRA_KEY), description + ":missing key");
+        assertTrue(serialClone.containsKey(EXTRA_KEY), description + ":missing key");
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+        assertSame(clone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+        assertSame(serialClone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+
+        assertEquals(map, map, description + ":should equal self");
+        assertEquals(clone, map, description + ":should equal clone");
+        assertEquals(map, clone, description + ": should equal orginal map");
+        assertEquals(serialClone, map, description + ": should equal deserialized clone");
+        assertEquals(map, serialClone, description + ": should equal original map");
+        assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
+        assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
+    }
+
+    static byte[] serializedForm(Object obj) {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            new ObjectOutputStream(baos).writeObject(obj);
+            return baos.toByteArray();
+        } catch (IOException e) {
+            fail("Unexpected Exception", e);
+            return null;
+        }
+    }
+
+    static Object readObject(byte[] bytes) throws IOException, ClassNotFoundException {
+        InputStream is = new ByteArrayInputStream(bytes);
+        return new ObjectInputStream(is).readObject();
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> T serialClone(T obj) {
+        try {
+            return (T)readObject(serializedForm(obj));
+        } catch (IOException | ClassNotFoundException e) {
+            fail("Unexpected Exception", e);
+            return null;
+        }
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
+    private static Iterator<Object[]> makeMaps() {
+        return Arrays.asList(
+            // empty
+            new Object[]{"HashMap", new HashMap()},
+            new Object[]{"LinkedHashMap", new LinkedHashMap()},
+            new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(new HashMap(), IntegerEnum.class, String.class)},
+            new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(new HashMap())},
+            // null hostile
+            new Object[]{"EnumMap", new EnumMap(IntegerEnum.class)},
+            new Object[]{"Hashtable", new Hashtable()},
+            new Object[]{"TreeMap", new TreeMap()},
+            new Object[]{"ConcurrentHashMap", new ConcurrentHashMap()},
+            new Object[]{"ConcurrentSkipListMap", new ConcurrentSkipListMap()},
+            new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(new ConcurrentHashMap(), IntegerEnum.class, String.class)},
+            new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(new EnumMap(IntegerEnum.class))},
+            // filled
+            new Object[]{"HashMap", fillMap(new HashMap())},
+            new Object[]{"LinkedHashMap", fillMap(new LinkedHashMap())},
+            new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(fillMap(new HashMap()), IntegerEnum.class, String.class)},
+            new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(fillMap(new HashMap()))},
+            // null hostile
+            new Object[]{"EnumMap", fillMap(new EnumMap(IntegerEnum.class))},
+            new Object[]{"Hashtable", fillMap(new Hashtable())},
+            new Object[]{"TreeMap", fillMap(new TreeMap())},
+            new Object[]{"ConcurrentHashMap", fillMap(new ConcurrentHashMap())},
+            new Object[]{"ConcurrentSkipListMap", fillMap(new ConcurrentSkipListMap())},
+            new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(fillMap(new ConcurrentHashMap()), IntegerEnum.class, String.class)},
+            new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(fillMap(new EnumMap(IntegerEnum.class)))}).iterator();
+    }
+
+    private static Map<IntegerEnum, String> fillMap(Map<IntegerEnum, String> result) {
+        for (int each = 0; each < TEST_SIZE; each++) {
+            result.put(KEYS[each], VALUES[each]);
+        }
+
+        return result;
+    }
+}
--- a/jdk/test/java/util/Objects/BasicObjectsTest.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/test/java/util/Objects/BasicObjectsTest.java	Tue Apr 16 01:44:58 2013 -0700
@@ -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
@@ -23,12 +23,13 @@
 
 /*
  * @test
- * @bug 6797535 6889858 6891113
+ * @bug 6797535 6889858 6891113 8011800
  * @summary Basic tests for methods in java.util.Objects
  * @author  Joseph D. Darcy
  */
 
 import java.util.*;
+import java.util.function.*;
 
 public class BasicObjectsTest {
     public static void main(String... args) {
@@ -40,7 +41,7 @@
         errors += testToString();
         errors += testToString2();
         errors += testCompare();
-        errors += testNonNull();
+        errors += testRequireNonNull();
         if (errors > 0 )
             throw new RuntimeException();
     }
@@ -158,49 +159,54 @@
         return errors;
     }
 
-    private static int testNonNull() {
+    private static int testRequireNonNull() {
         int errors = 0;
-        String s;
+
+        final String RNN_1 = "1-arg requireNonNull";
+        final String RNN_2 = "2-arg requireNonNull";
+        final String RNN_3 = "Supplier requireNonNull";
+
+        Function<String, String> rnn1 = s -> Objects.requireNonNull(s);
+        Function<String, String> rnn2 = s -> Objects.requireNonNull(s, "trousers");
+        Function<String, String> rnn3 = s -> Objects.requireNonNull(s, () -> "trousers");
 
-        // Test 1-arg variant
+        errors += testRNN_NonNull(rnn1, RNN_1);
+        errors += testRNN_NonNull(rnn2, RNN_2);
+        errors += testRNN_NonNull(rnn3, RNN_3);
+
+        errors += testRNN_Null(rnn1, RNN_1, null);
+        errors += testRNN_Null(rnn2, RNN_2, "trousers");
+        errors += testRNN_Null(rnn3, RNN_3, "trousers");
+        return errors;
+    }
+
+    private static int testRNN_NonNull(Function<String, String> testFunc,
+                                           String testFuncName) {
+        int errors = 0;
         try {
-            s = Objects.requireNonNull("pants");
+            String s = testFunc.apply("pants");
             if (s != "pants") {
-                System.err.printf("1-arg non-null failed to return its arg");
+                System.err.printf(testFuncName + " failed to return its arg");
                 errors++;
             }
         } catch (NullPointerException e) {
-            System.err.printf("1-arg nonNull threw unexpected NPE");
+            System.err.printf(testFuncName + " threw unexpected NPE");
             errors++;
         }
+        return errors;
+    }
 
+    private static int testRNN_Null(Function<String, String> testFunc,
+                                               String testFuncName,
+                                               String expectedMessage) {
+        int errors = 0;
         try {
-            s = Objects.requireNonNull(null);
-            System.err.printf("1-arg nonNull failed to throw NPE");
+            String s = testFunc.apply(null);
+            System.err.printf(testFuncName + " failed to throw NPE");
             errors++;
         } catch (NullPointerException e) {
-            // Expected
-        }
-
-        // Test 2-arg variant
-        try {
-            s = Objects.requireNonNull("pants", "trousers");
-            if (s != "pants") {
-                System.err.printf("2-arg nonNull failed to return its arg");
-                errors++;
-            }
-        } catch (NullPointerException e) {
-            System.err.printf("2-arg nonNull threw unexpected NPE");
-            errors++;
-        }
-
-        try {
-            s = Objects.requireNonNull(null, "pantaloons");
-            System.err.printf("2-arg nonNull failed to throw NPE");
-            errors++;
-        } catch (NullPointerException e) {
-            if (e.getMessage() != "pantaloons") {
-                System.err.printf("2-arg nonNull threw NPE w/ bad detail msg");
+            if (e.getMessage() != expectedMessage) {
+                System.err.printf(testFuncName + " threw NPE w/ bad detail msg");
                 errors++;
             }
         }
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Fri Apr 12 10:42:50 2013 -0700
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Tue Apr 16 01:44:58 2013 -0700
@@ -486,40 +486,40 @@
             CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
             CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
             cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 1 || x == 2); return x; });
+            checkCompletedNormally(cf3, new Object[] {1, 2});
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, new Object[] {1, 2});
 
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> 2);
             cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; });
+            checkCompletedNormally(cf3, new Object[] {1, 2});
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, new Object[] {1, 2});
 
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> 2);
             cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; }, executor);
+            checkCompletedNormally(cf3, new Object[] {1, 2});
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, new Object[] {1, 2});
 
             cf1 = supplyAsync(() -> { throw new RuntimeException(); });
             cf2 = supplyAsync(() -> 2);
             cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 2); return x; });
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
 
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> { throw new RuntimeException(); });
             cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1); return x; });
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
 
             cf1 = supplyAsync(() -> { throw new RuntimeException(); });
             cf2 = supplyAsync(() -> { throw new RuntimeException(); });
             cf3 = cf1.applyToEitherAsync(cf2, (x) -> { fail(); return x; });
+            checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedExceptionally(cf3);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
@@ -531,45 +531,45 @@
             CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
             CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
             cf3 = cf1.acceptEither(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> 2);
             cf3 = cf1.acceptEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> 2);
             cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); }, executor);
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             cf1 = supplyAsync(() -> { throw new RuntimeException(); });
             cf2 = supplyAsync(() -> 2);
             cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 2); }, executor);
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
 
             cf1 = supplyAsync(() -> 1);
             cf2 = supplyAsync(() -> { throw new RuntimeException(); });
             cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1); });
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
 
             cf1 = supplyAsync(() -> { throw new RuntimeException(); });
             cf2 = supplyAsync(() -> { throw new RuntimeException(); });
             cf3 = cf2.acceptEitherAsync(cf1, (x) -> { fail(); });
+            checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedExceptionally(cf3);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
@@ -581,50 +581,50 @@
             CompletableFuture<Void> cf1 = runAsync(() -> { });
             CompletableFuture<Void> cf2 = runAsync(() -> { });
             cf3 = cf1.runAfterEither(cf2, () -> { atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { });
             cf2 = runAsync(() -> { });
             cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { });
             cf2 = runAsync(() -> { });
             cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor);
+            checkCompletedNormally(cf3, null);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedNormally(cf3, null);
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { throw new RuntimeException(); });
             cf2 = runAsync(() -> { });
             cf3 = cf2.runAfterEither(cf1, () -> { atomicInt.incrementAndGet(); });
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { });
             cf2 = runAsync(() -> { throw new RuntimeException(); });
             cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
-            check(cf1.isDone() || cf2.isDone());
             try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
+            check(cf1.isDone() || cf2.isDone());
             check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { throw new RuntimeException(); });
             cf2 = runAsync(() -> { throw new RuntimeException(); });
             cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor);
+            checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
-            checkCompletedExceptionally(cf3);
             check(atomicInt.get() == before);
         } catch (Throwable t) { unexpected(t); }
 
@@ -670,16 +670,16 @@
         //----------------------------------------------------------------
         // anyOf tests
         //----------------------------------------------------------------
-        //try {
-        //    CompletableFuture<Object> cf3;
-        //    for (int k=0; k < 10; k++){
-        //        CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
-        //        CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
-        //        cf3 = CompletableFuture.anyOf(cf1, cf2);
-        //        check(cf1.isDone() || cf2.isDone());
-        //        checkCompletedNormally(cf3, new Object[] {1, 2});
-        //    }
-        //} catch (Throwable t) { unexpected(t); }
+        try {
+            CompletableFuture<Object> cf3;
+            for (int k=0; k < 10; k++){
+                CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
+                CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
+                cf3 = CompletableFuture.anyOf(cf1, cf2);
+                checkCompletedNormally(cf3, new Object[] {1, 2});
+                check(cf1.isDone() || cf2.isDone());
+            }
+        } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
         // allOf tests