Merge "PathClassLoaderTest: add test about loading resources with tampered certificates"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 6b9e882..18ca800 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -121,6 +121,12 @@
 LOCAL_MODULE := core-libart
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-all
+ifeq ($(EMMA_INSTRUMENT),true)
+ifneq ($(EMMA_INSTRUMENT_STATIC),true)
+    # For instrumented build, include Jacoco classes into core-libart.
+    LOCAL_STATIC_JAVA_LIBRARIES := jacocoagent
+endif # EMMA_INSTRUMENT_STATIC
+endif # EMMA_INSTRUMENT
 LOCAL_CORE_LIBRARY := true
 LOCAL_REQUIRED_MODULES := tzdata
 include $(BUILD_JAVA_LIBRARY)
@@ -182,7 +188,7 @@
 LOCAL_SRC_FILES := $(test_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs okhttp core-junit bouncycastle mockito-target
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs okhttp core-junit junit4-target bouncycastle mockito-target
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -197,7 +203,7 @@
 LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit bouncycastle
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit junit4-target bouncycastle
 LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-bcpkix bouncycastle-ocsp
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests-support
@@ -211,7 +217,7 @@
 LOCAL_SRC_FILES :=  $(call all-test-java-files-under, jsr166-tests)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs core-junit
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs core-junit junit4-target
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := jsr166-tests
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -294,7 +300,7 @@
     LOCAL_SRC_FILES := $(test_src_files)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-lambda-stubs-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex mockito-api-hostdex
+    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-lambda-stubs-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex junit4-target-hostdex core-tests-support-hostdex mockito-api-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
@@ -310,7 +316,7 @@
     LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex bouncycastle-hostdex
+    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex junit4-target-hostdex bouncycastle-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-bcpkix-hostdex bouncycastle-ocsp-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
diff --git a/NativeCode.mk b/NativeCode.mk
index 7ab8e4f..be02ff1 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -94,6 +94,7 @@
 core_test_files := \
   luni/src/test/native/dalvik_system_JniTest.cpp \
   luni/src/test/native/libcore_java_io_FileTest.cpp \
+  luni/src/test/native/libcore_java_lang_ThreadTest.cpp \
   luni/src/test/native/libcore_java_nio_BufferTest.cpp \
   luni/src/test/native/libcore_util_NativeAllocationRegistryTest.cpp \
 
diff --git a/benchmarks/src/benchmarks/XmlSerializeBenchmark.java b/benchmarks/src/benchmarks/XmlSerializeBenchmark.java
index 0ef2620..c542e87 100644
--- a/benchmarks/src/benchmarks/XmlSerializeBenchmark.java
+++ b/benchmarks/src/benchmarks/XmlSerializeBenchmark.java
@@ -88,7 +88,7 @@
         String[] splitted = datasetAsString.split(" ");
         dataset = new double[splitted.length];
         for (int i = 0; i < splitted.length; i++) {
-            dataset[i] = Double.valueOf(splitted[i]);
+            dataset[i] = Double.parseDouble(splitted[i]);
         }
     }
 
diff --git a/benchmarks/src/benchmarks/regression/IntegerBenchmark.java b/benchmarks/src/benchmarks/regression/IntegerBenchmark.java
index f7f97c7..c9614d4 100644
--- a/benchmarks/src/benchmarks/regression/IntegerBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/IntegerBenchmark.java
@@ -133,4 +133,16 @@
         }
         return t;
     }
+
+    public int timeIntegerValueOf(int reps) throws Exception {
+        String[] intStrings = new String[]{"0", "1", "12", "123", "1234", "12345",
+                                           "123456", "1234567", "12345678"};
+        int t = 0;
+        for (int i = 0; i < reps; ++i) {
+            for (int j = 0; j < intStrings.length; ++j) {
+                t += Integer.valueOf(intStrings[j]);
+            }
+        }
+        return t;
+    }
 }
diff --git a/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java b/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
index 07a2305..ef54432 100644
--- a/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
@@ -63,6 +63,16 @@
         }
     }
 
+    public void timeAppendSubCharSequence(int reps) {
+        CharSequence cs = "chars";
+        for (int i = 0; i < reps; ++i) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < length; ++j) {
+                sb.append(cs);
+            }
+        }
+    }
+
     public void timeAppendDouble(int reps) {
         double d = 1.2;
         for (int i = 0; i < reps; ++i) {
diff --git a/benchmarks/src/benchmarks/regression/StringReplaceBenchmark.java b/benchmarks/src/benchmarks/regression/StringReplaceBenchmark.java
new file mode 100644
index 0000000..a527633
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/StringReplaceBenchmark.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package benchmarks.regression;
+
+import com.google.caliper.Param;
+
+public class StringReplaceBenchmark {
+    static enum StringLengths {
+        EMPTY(""),
+        L_16(makeString(16)),
+        L_64(makeString(64)),
+        L_256(makeString(256)),
+        L_512(makeString(512));
+
+        private final String value;
+
+        private StringLengths(String s) {
+            this.value = s;
+        }
+    }
+
+    private static final String makeString(int length) {
+        final String sequence8 = "abcdefghijklmnop";
+        final int numAppends = (length / 16) - 1;
+        StringBuilder stringBuilder = new StringBuilder(length);
+
+        // (n-1) occurences of "abcdefghijklmnop"
+        for (int i = 0; i < numAppends; ++i) {
+            stringBuilder.append(sequence8);
+        }
+
+        // and one final occurence of qrstuvwx.
+        stringBuilder.append("qrstuvwx");
+
+        return stringBuilder.toString();
+    }
+
+    @Param private StringLengths s;
+
+    public void timeReplaceCharNonExistent(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace('z', '0');
+        }
+    }
+
+    public void timeReplaceCharRepeated(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace('a', '0');
+        }
+    }
+
+    public void timeReplaceSingleChar(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace('q', '0');
+        }
+    }
+
+    public void timeReplaceSequenceNonExistent(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace("fish", "0");
+        }
+    }
+
+    public void timeReplaceSequenceRepeated(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace("jklm", "0");
+        }
+    }
+
+    public void timeReplaceSingleSequence(int reps) {
+        for (int i = 0; i < reps; ++i) {
+            s.value.replace("qrst", "0");
+        }
+    }
+}
diff --git a/benchmarks/src/benchmarks/regression/StringToBytesBenchmark.java b/benchmarks/src/benchmarks/regression/StringToBytesBenchmark.java
new file mode 100644
index 0000000..8b2222472
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/StringToBytesBenchmark.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package benchmarks.regression;
+
+import com.google.caliper.Param;
+
+import java.nio.charset.StandardCharsets;
+
+public class StringToBytesBenchmark {
+    static enum StringLengths {
+        EMPTY(""),
+        L_16(makeString(16)),
+        L_64(makeString(64)),
+        L_256(makeString(256)),
+        L_512(makeString(512));
+
+        private final String value;
+
+        private StringLengths(String s) {
+            this.value = s;
+        }
+    }
+
+    private static final String makeString(int length) {
+        char[] chars = new char[length];
+        for (int i = 0; i < length; ++i) {
+            chars[i] = (char) i;
+        }
+        return new String(chars);
+    }
+
+    @Param StringLengths string;
+
+    public void timeGetBytesUtf8(int nreps) {
+        for (int i = 0; i < nreps; ++i) {
+            string.value.getBytes(StandardCharsets.UTF_8);
+        }
+    }
+
+    public void timeGetBytesIso88591(int nreps) {
+        for (int i = 0; i < nreps; ++i) {
+            string.value.getBytes(StandardCharsets.ISO_8859_1);
+        }
+    }
+
+    public void timeGetBytesAscii(int nreps) {
+        for (int i = 0; i < nreps; ++i) {
+            string.value.getBytes(StandardCharsets.US_ASCII);
+        }
+    }
+}
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index c30972b..3a12da2 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -322,13 +322,13 @@
     /*
      * Helper class.
      */
-    private class DFEnum implements Enumeration<String> {
+    private static class DFEnum implements Enumeration<String> {
         private int mIndex;
         private String[] mNameList;
 
         DFEnum(DexFile df) {
             mIndex = 0;
-            mNameList = getClassNameList(mCookie);
+            mNameList = getClassNameList(df.mCookie);
         }
 
         public boolean hasMoreElements() {
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index 7a3fa66..48cb792 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -311,8 +311,9 @@
                     // Raw dex file (not inside a zip/jar).
                     try {
                         dex = loadDexFile(file, optimizedDirectory, loader, elements);
-                    } catch (IOException ex) {
-                        System.logE("Unable to load dex file: " + file, ex);
+                    } catch (IOException suppressed) {
+                        System.logE("Unable to load dex file: " + file, suppressed);
+                        suppressedExceptions.add(suppressed);
                     }
                 } else {
                     zip = file;
diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
index 48f1fe2..b29b895 100644
--- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
+++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
@@ -28,6 +28,18 @@
     private long token;
 
     /**
+     * Called by the zygote when starting up. It marks the point when any thread
+     * start should be an error, as only internal daemon threads are allowed there.
+     */
+    public static native void startZygoteNoThreadCreation();
+
+    /**
+     * Called by the zygote when startup is finished. It marks the point when it is
+     * conceivable that threads would be started again, e.g., restarting daemons.
+     */
+    public static native void stopZygoteNoThreadCreation();
+
+    /**
      * Called by the zygote prior to every fork. Each call to {@code preFork}
      * is followed by a matching call to {@link #postForkChild(int, String)} on the child
      * process and {@link #postForkCommon()} on both the parent and the child
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
index ea9b627b..d0434d6 100644
--- a/dex/src/main/java/com/android/dex/Dex.java
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -93,7 +93,11 @@
      * Creates a new dex buffer of the dex in {@code in}, and closes {@code in}.
      */
     public Dex(InputStream in) throws IOException {
-        loadFrom(in);
+        try {
+            loadFrom(in);
+        } finally {
+            in.close();
+        }
     }
 
     /**
@@ -104,13 +108,17 @@
             ZipFile zipFile = new ZipFile(file);
             ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME);
             if (entry != null) {
-                loadFrom(zipFile.getInputStream(entry));
+                try (InputStream inputStream = zipFile.getInputStream(entry)) {
+                    loadFrom(inputStream);
+                }
                 zipFile.close();
             } else {
                 throw new DexException("Expected " + DexFormat.DEX_IN_JAR_NAME + " in " + file);
             }
         } else if (file.getName().endsWith(".dex")) {
-            loadFrom(new FileInputStream(file));
+            try (InputStream inputStream = new FileInputStream(file)) {
+                loadFrom(inputStream);
+            }
         } else {
             throw new DexException("unknown output extension: " + file);
         }
@@ -141,6 +149,9 @@
         return new Dex(data);
     }
 
+    /**
+     * It is the caller's responsibility to close {@code in}.
+     */
     private void loadFrom(InputStream in) throws IOException {
         ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
         byte[] buffer = new byte[8192];
@@ -149,7 +160,6 @@
         while ((count = in.read(buffer)) != -1) {
             bytesOut.write(buffer, 0, count);
         }
-        in.close();
 
         this.data = ByteBuffer.wrap(bytesOut.toByteArray());
         this.data.order(ByteOrder.LITTLE_ENDIAN);
@@ -174,9 +184,9 @@
     }
 
     public void writeTo(File dexOut) throws IOException {
-        OutputStream out = new FileOutputStream(dexOut);
-        writeTo(out);
-        out.close();
+        try (OutputStream out = new FileOutputStream(dexOut)) {
+            writeTo(out);
+        }
     }
 
     public TableOfContents getTableOfContents() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/BufferedReaderTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/BufferedReaderTest.java
index 1da9502..46559dc 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/BufferedReaderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/BufferedReaderTest.java
@@ -573,6 +573,16 @@
 	}
 
 	/**
+	 * @tests java.io.BufferedReader#lines()
+	 */
+	public void test_lines() {
+		// Test for method java.util.stream.Stream java.io.BufferedReader.lines()
+		br = new BufferedReader(new Support_StringReader(testString));
+		String[] r = br.lines().toArray(String[]::new);
+		assertEquals(107, r.length);
+	}
+
+	/**
 	 * Sets up the fixture, for example, open a network connection. This method
 	 * is called before a test is executed.
 	 */
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
index 3806492..1a490fa 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
@@ -25,6 +25,7 @@
 import java.io.ObjectStreamClass;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
+import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
 public class ObjectStreamClassTest extends TestCase {
@@ -216,8 +217,23 @@
 
         osc = ObjectStreamClass.lookup(NonSerialzableClass.class);
         assertNull(osc);
-
     }
 
+    // http://b/28106822
+    public void testBug28106822() throws Exception {
+        Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
+                "getConstructorId", Class.class);
+        getConstructorId.setAccessible(true);
 
+        assertEquals(1189998819991197253L, getConstructorId.invoke(null, Object.class));
+        assertEquals(1189998819991197253L, getConstructorId.invoke(null, String.class));
+
+        Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance",
+                Class.class, Long.TYPE);
+        newInstance.setAccessible(true);
+
+        Object obj = newInstance.invoke(null, String.class, 0 /* ignored */);
+        assertNotNull(obj);
+        assertTrue(obj instanceof String);
+    }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
index f5bb134..37f5c0a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
@@ -1057,6 +1057,68 @@
     }
 
     /**
+     * {@link java.lang.Math#nextDown(double)}
+     * @since 1.8
+     */
+    @SuppressWarnings("boxing")
+    public void test_nextDown_D() {
+        // This method is semantically equivalent to nextAfter(d,
+        // Double.NEGATIVE_INFINITY),
+        // so we use the data of test_nextAfter_DD
+        for (int i = 0; i < NEXTAFTER_DD_START_CASES.length; i++) {
+            final double start = NEXTAFTER_DD_START_CASES[i][0];
+            final long nextDownBits = Double
+                    .doubleToLongBits(NEXTAFTER_DD_START_CASES[i][2]);
+            final long resultBits = Double.doubleToLongBits(Math.nextDown(start));
+            assertEquals("Result should be next down-number.", nextDownBits,
+                    resultBits);
+        }
+
+        // test for cases with NaN
+        assertTrue("The result should be NaN.", Double.isNaN(Math
+                .nextDown(Double.NaN)));
+
+        // test for exception
+        try {
+            Math.nextDown((Double) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    /**
+     * {@link java.lang.Math#nextDown(float)}
+     * @since 1.8
+     */
+    @SuppressWarnings("boxing")
+    public void test_nextDown_F() {
+        // This method is semantically equivalent to nextAfter(f,
+        // Float.NEGATIVE_INFINITY),
+        // so we use the data of test_nextAfter_FD
+        for (int i = 0; i < NEXTAFTER_FD_START_CASES.length; i++) {
+            final float start = NEXTAFTER_FD_START_CASES[i][0];
+            final int nextDownBits = Float
+                    .floatToIntBits(NEXTAFTER_FD_START_CASES[i][2]);
+            final int resultBits = Float.floatToIntBits(Math.nextDown(start));
+            assertEquals("Result should be next down-number.", nextDownBits,
+                    resultBits);
+        }
+
+        // test for cases with NaN
+        assertTrue("The result should be NaN.", Float.isNaN(Math
+                .nextDown(Float.NaN)));
+
+        // test for exception
+        try {
+            Math.nextDown((Float) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    /**
      * java.lang.Math#pow(double, double)
      */
     public void test_powDD() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/StrictMathTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/StrictMathTest.java
index cce8935..055fbfe 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/StrictMathTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/StrictMathTest.java
@@ -881,6 +881,70 @@
     }
 
     /**
+     * {@link java.lang.StrictMath#nextDown(double)}
+     * @since 1.8
+     */
+    @SuppressWarnings("boxing")
+    public void test_nextDown_D() {
+        // This method is semantically equivalent to nextAfter(d,
+        // Double.NEGATIVE_INFINITY),
+        // so we use the data of test_nextAfter_DD
+        for (int i = 0; i < NEXTAFTER_DD_START_CASES.length; i++) {
+            final double start = NEXTAFTER_DD_START_CASES[i][0];
+            final long nextDownBits = Double
+                    .doubleToLongBits(NEXTAFTER_DD_START_CASES[i][2]);
+            final long resultBits = Double.doubleToLongBits(StrictMath
+                    .nextDown(start));
+            assertEquals("Result should be next down-number.", nextDownBits,
+                    resultBits);
+        }
+
+        // test for cases with NaN
+        assertTrue("The result should be NaN.", Double.isNaN(StrictMath
+                .nextDown(Double.NaN)));
+
+        // test for exception
+        try {
+            StrictMath.nextDown((Double) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    /**
+     * {@link java.lang.StrictMath#nextDown(float)}
+     * @since 1.8
+     */
+    @SuppressWarnings("boxing")
+    public void test_nextDown_F() {
+        // This method is semantically equivalent to nextAfter(f,
+        // Float.NEGATIVE_INFINITY),
+        // so we use the data of test_nextAfter_FD
+        for (int i = 0; i < NEXTAFTER_FD_START_CASES.length; i++) {
+            final float start = NEXTAFTER_FD_START_CASES[i][0];
+            final int nextDownBits = Float
+                    .floatToIntBits(NEXTAFTER_FD_START_CASES[i][2]);
+            final int resultBits = Float.floatToIntBits(StrictMath
+                    .nextDown(start));
+            assertEquals("Result should be next down-number.", nextDownBits,
+                    resultBits);
+        }
+
+        // test for cases with NaN
+        assertTrue("The result should be NaN.", Float.isNaN(StrictMath
+                .nextDown(Float.NaN)));
+
+        // test for exception
+        try {
+            StrictMath.nextDown((Float) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    /**
      * java.lang.StrictMath#pow(double, double)
      */
     public void test_powDD() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
index e8f8e29..4998dc5 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
@@ -390,8 +390,11 @@
 
     public void test_getSoTimeout() throws Exception {
         DatagramSocket ds = new DatagramSocket();
-        ds.setSoTimeout(100);
-        assertEquals("Returned incorrect timeout", 100, ds.getSoTimeout());
+        final int timeoutSet = 100;
+        ds.setSoTimeout(timeoutSet);
+        int actualTimeout = ds.getSoTimeout();
+        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+        assertTrue("Returned incorrect timeout", Math.abs(actualTimeout - timeoutSet) <= 10);
     }
 
     static final class TestDatagramSocketImpl extends DatagramSocketImpl {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index 264e004..d0bb14a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -71,7 +71,7 @@
 
         // Determine if the device is marked to support multicast or not. If this propery is not
         // set we assume the device has an interface capable of supporting multicast.
-        supportsMulticast = Boolean.valueOf(
+        supportsMulticast = Boolean.parseBoolean(
                 System.getProperty("android.cts.device.multicast", "true"));
         if (!supportsMulticast) {
             return;
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/ServerSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/ServerSocketTest.java
index 1c1a544..5279464 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/ServerSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/ServerSocketTest.java
@@ -296,9 +296,12 @@
      */
     public void test_getSoTimeout() throws IOException {
         s = new ServerSocket(0);
+        final int timeoutSet = 100;
         try {
-            s.setSoTimeout(100);
-            assertEquals("Returned incorrect sotimeout", 100, s.getSoTimeout());
+            s.setSoTimeout(timeoutSet);
+            int actualTimeout = s.getSoTimeout();
+            // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+            assertTrue("Returned incorrect sotimeout", Math.abs(timeoutSet - actualTimeout) <= 10);
         } finally {
             s.close();
         }
@@ -348,12 +351,15 @@
      */
     public void test_setSoTimeoutI() throws IOException {
         // Timeout should trigger and throw InterruptedIOException
+        final int timeoutSet = 100;
         try {
             s = new ServerSocket(0);
-            s.setSoTimeout(100);
+            s.setSoTimeout(timeoutSet);
             s.accept();
         } catch (InterruptedIOException e) {
-            assertEquals("Set incorrect sotimeout", 100, s.getSoTimeout());
+            int actualSoTimeout = s.getSoTimeout();
+            // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+            assertTrue("Set incorrect sotimeout", Math.abs(timeoutSet - actualSoTimeout) <= 10);
             return;
         }
 
@@ -372,7 +378,7 @@
         try {
             int portNumber = s.getLocalPort();
             // In IPv6, the all-zeros-address is written as "::"
-            assertEquals("ServerSocket[addr=/::,localport="
+            assertEquals("ServerSocket[addr=::/::,localport="
                     + portNumber + "]", s.toString());
         } finally {
             s.close();
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/SocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/SocketTest.java
index 4df92e2..0915a27 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/SocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/SocketTest.java
@@ -967,8 +967,11 @@
     public void test_getSoTimeout() throws Exception {
         ServerSocket server = new ServerSocket(0);
         Socket client = new Socket(InetAddress.getLocalHost(), server.getLocalPort());
-        client.setSoTimeout(100);
-        assertEquals("Returned incorrect sotimeout", 100, client.getSoTimeout());
+        final int timeoutSet = 100;
+        client.setSoTimeout(timeoutSet);
+        int actualTimeout = client.getSoTimeout();
+        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+        assertTrue("Returned incorrect sotimeout", Math.abs(timeoutSet - actualTimeout) <= 10);
         client.close();
         server.close();
     }
@@ -1492,8 +1495,11 @@
     public void test_setSoTimeoutI() throws Exception {
         ServerSocket server = new ServerSocket(0);
         Socket client = new Socket(InetAddress.getLocalHost(), server.getLocalPort());
-        client.setSoTimeout(100);
-        assertEquals("Set incorrect sotimeout", 100, client.getSoTimeout());
+        final int timeoutSet = 100;
+        client.setSoTimeout(timeoutSet);
+        int actualTimeout = client.getSoTimeout();
+        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+        assertTrue("Set incorrect sotimeout", Math.abs(timeoutSet - actualTimeout) <= 10);
         client.close();
         server.close();
     }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
index f3b5f8b..d6dacb4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
@@ -46,6 +46,8 @@
 
 import junit.framework.TestCase;
 
+import libcore.io.IoUtils;
+
 public class FileChannelTest extends TestCase {
 
     private static final int CAPACITY = 100;
@@ -76,8 +78,12 @@
 
     private FileChannel readOnlyFileChannel;
 
+    private FileChannel readOnlyFileChannel2;
+
     private FileChannel writeOnlyFileChannel;
 
+    private FileChannel writeOnlyFileChannel2;
+
     private FileChannel readWriteFileChannel;
 
     private File fileOfReadOnlyFileChannel;
@@ -121,41 +127,23 @@
         fileLock = null;
         readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
                 .getChannel();
+        readOnlyFileChannel2 = new FileInputStream(fileOfReadOnlyFileChannel)
+                .getChannel();
         writeOnlyFileChannel = new FileOutputStream(fileOfWriteOnlyFileChannel)
                 .getChannel();
+        writeOnlyFileChannel2 = new FileOutputStream(fileOfWriteOnlyFileChannel)
+                .getChannel();
         readWriteFileChannel = new RandomAccessFile(fileOfReadWriteFileChannel,
                 "rw").getChannel();
     }
 
     protected void tearDown() {
-        if (null != readOnlyFileChannel) {
-            try {
-                readOnlyFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != writeOnlyFileChannel) {
-            try {
-                writeOnlyFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != readWriteFileChannel) {
-            try {
-                readWriteFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != fis) {
-            try {
-                fis.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
+        IoUtils.closeQuietly(readOnlyFileChannel);
+        IoUtils.closeQuietly(readOnlyFileChannel2);
+        IoUtils.closeQuietly(writeOnlyFileChannel);
+        IoUtils.closeQuietly(writeOnlyFileChannel2);
+        IoUtils.closeQuietly(readWriteFileChannel);
+        IoUtils.closeQuietly(fis);
 
         if (null != fileLock) {
             try {
@@ -174,56 +162,15 @@
         if (null != fileOfReadWriteFileChannel) {
             fileOfReadWriteFileChannel.delete();
         }
-        if (null != datagramChannelSender) {
-            try {
-                datagramChannelSender.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != datagramChannelReceiver) {
-            try {
-                datagramChannelReceiver.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != serverSocketChannel) {
-            try {
-                serverSocketChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != socketChannelSender) {
-            try {
-                socketChannelSender.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != socketChannelReceiver) {
-            try {
-                socketChannelReceiver.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
+
+        IoUtils.closeQuietly(datagramChannelSender);
+        IoUtils.closeQuietly(datagramChannelReceiver);
+        IoUtils.closeQuietly(serverSocketChannel);
+        IoUtils.closeQuietly(socketChannelSender);
+        IoUtils.closeQuietly(socketChannelReceiver);
         if (null != pipe) {
-            if (null != pipe.source()) {
-                try {
-                    pipe.source().close();
-                } catch (IOException e) {
-                    // do nothing
-                }
-            }
-            if (null != pipe.sink()) {
-                try {
-                    pipe.sink().close();
-                } catch (IOException e) {
-                    // do nothing
-                }
-            }
+            IoUtils.closeQuietly(pipe.source());
+            IoUtils.closeQuietly(pipe.sink());
         }
     }
 
@@ -653,14 +600,81 @@
     /**
      * @tests java.nio.channels.FileChannel#lock()
      */
+    public void test_lock_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.lock();
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
     public void test_lock() throws Exception {
-        MockFileChannel mockFileChannel = new MockFileChannel();
-        // Verify that calling lock() leads to the method
-        // lock(long, long, boolean) being called with a 0 for the
-        // first parameter, Long.MAX_VALUE as the second parameter and false
-        // as the third parameter.
-        mockFileChannel.lock();
-        assertTrue(mockFileChannel.isLockCalled);
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(Long.MAX_VALUE, fileLock.size());
+        assertEquals(0, fileLock.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_OverlappingException() throws Exception {
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+
+        // Test the same channel cannot be locked twice.
+        try {
+            writeOnlyFileChannel.lock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.lock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.lock();
+        fileLock.release();
+        // After release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+
+        // A different channel should be able to obtain a lock after it has been released
+        fileLock.release();
+        assertTrue(writeOnlyFileChannel2.lock().isValid());
     }
 
     /**
@@ -826,12 +840,17 @@
         fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
         assertTrue(fileLock.isValid());
 
+        // Test the same channel cannot be locked twice.
         try {
             writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
             fail("should throw OverlappingFileLockException");
-        } catch (OverlappingFileLockException e) {
-            // expected
-        }
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.lock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
     }
 
     /**
@@ -861,14 +880,88 @@
     /**
      * @tests java.nio.channels.FileChannel#tryLock()
      */
+    public void test_tryLock_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.tryLock();
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
     public void test_tryLock() throws Exception {
-        MockFileChannel mockFileChannel = new MockFileChannel();
-        // Verify that calling tryLock() leads to the method
-        // tryLock(long, long, boolean) being called with a 0 for the
-        // first parameter, Long.MAX_VALUE as the second parameter and false
-        // as the third parameter.
-        mockFileChannel.tryLock();
-        assertTrue(mockFileChannel.isTryLockCalled);
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(0, fileLock.position());
+        assertEquals(Long.MAX_VALUE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_Overlapping() throws Exception {
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test the same channel cannot be locked twice.
+        try {
+            writeOnlyFileChannel.tryLock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.tryLock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.tryLock();
+        fileLock.release();
+
+        // After release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test that the same channel can acquire the lock after it has been released
+        fileLock.release();
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test that a different channel can acquire the lock after it has been released
+        fileLock.release();
+        fileLock = writeOnlyFileChannel2.tryLock();
+        assertTrue(fileLock.isValid());
     }
 
     /**
@@ -1034,12 +1127,17 @@
         fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
         assertTrue(fileLock.isValid());
 
+        // Test the same channel cannot be locked twice.
         try {
-            writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+            writeOnlyFileChannel.tryLock(POSITION + 1, SIZE, false);
             fail("should throw OverlappingFileLockException");
-        } catch (OverlappingFileLockException e) {
-            // expected
-        }
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.tryLock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
     }
 
     /**
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/MockDatagramChannel.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/MockDatagramChannel.java
index 8b0f5b3..8978714 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/MockDatagramChannel.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/MockDatagramChannel.java
@@ -25,6 +25,7 @@
 import java.net.SocketOption;
 import java.nio.ByteBuffer;
 import java.nio.channels.DatagramChannel;
+import java.nio.channels.MembershipKey;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.spi.SelectorProvider;
 import java.util.Set;
@@ -111,13 +112,23 @@
         return null;
     }
 
-    @Override
-    public Set<SocketOption<?>> supportedOptions() {
+    public DatagramChannel bind(SocketAddress local) throws IOException {
         return null;
     }
 
     @Override
-    public DatagramChannel bind(SocketAddress local) throws IOException {
+    public MembershipKey join(InetAddress group, NetworkInterface interf) {
+        return null;
+    }
+
+    @Override
+    public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
+            throws IOException {
+        return null;
+    }
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
         return null;
     }
 
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/ChoiceFormatTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/ChoiceFormatTest.java
index d52e586..e7acfdf 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/ChoiceFormatTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/ChoiceFormatTest.java
@@ -21,6 +21,7 @@
 import java.text.FieldPosition;
 import java.text.MessageFormat;
 import java.text.ParsePosition;
+import java.util.Arrays;
 import java.util.Locale;
 
 import junit.framework.TestCase;
@@ -300,9 +301,11 @@
         // java.text.ChoiceFormat.getFormats()
         String[] orgFormats = (String[]) formats.clone();
         String[] f = (String[]) f1.getFormats();
-        assertTrue("Wrong formats", f.equals(formats));
+        // getFormats() documentation says "Get the formats passed in the constructor",
+        // which can be interpreted as object identity.
+        assertTrue("Wrong formats", f == formats);
         f[0] = "Modified";
-        assertTrue("Formats copied", !f.equals(orgFormats));
+        assertTrue("Formats copied", f != orgFormats);
     }
 
     /**
@@ -312,9 +315,11 @@
         // Test for method double [] java.text.ChoiceFormat.getLimits()
         double[] orgLimits = (double[]) limits.clone();
         double[] l = f1.getLimits();
-        assertTrue("Wrong limits", l.equals(limits));
+        // getLimits() documentation says "Get the limits passed in the constructor",
+        // which can be interpreted as object identity.
+        assertTrue("Wrong limits", l == limits);
         l[0] = 3.14527;
-        assertTrue("Limits copied", !l.equals(orgLimits));
+        assertTrue("Limits copied", l != orgLimits);
     }
 
     /**
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/Arrays2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/Arrays2Test.java
index a61e343..3caf588 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/Arrays2Test.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/Arrays2Test.java
@@ -486,4 +486,21 @@
             fail();
         } catch(NullPointerException expected) {}
     }
+
+    public void test_replaceAll() throws Exception {
+        List<Integer> list = Arrays.asList(0, 1, 2);
+        list.replaceAll(k -> k + 1);
+        assertEquals((Integer)1, list.get(0));
+        assertEquals((Integer)2, list.get(1));
+        assertEquals((Integer)3, list.get(2));
+        assertEquals(3, list.size());
+    }
+
+    public void test_replaceAll_NPE() throws Exception {
+        List<Integer> list = Arrays.asList(0, 1, 2);
+        try {
+            list.replaceAll(null);
+            fail();
+        } catch(NullPointerException expected) {}
+    }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
index afec098..bbd8c50 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
@@ -37,6 +37,8 @@
     public void setUp() throws Exception {
         super.setUp();
         defaultLocale = Locale.getDefault();
+        // Most tests are locale independent, but locale does affect start-of-week.
+        Locale.setDefault(Locale.US);
     }
 
     @Override
@@ -537,8 +539,6 @@
      * java.util.GregorianCalendar#roll(int, boolean)
      */
     public void test_rollIZ() {
-        Locale.setDefault(Locale.US);
-
         // Test for method void java.util.GregorianCalendar.roll(int, boolean)
         GregorianCalendar gc = new GregorianCalendar(1972, Calendar.OCTOBER,
                 13, 19, 9, 59);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/IdentityHashMapTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/IdentityHashMapTest.java
index bf8db02..ee1a372 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/IdentityHashMapTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/IdentityHashMapTest.java
@@ -36,6 +36,7 @@
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.function.BiFunction;
 
 public class IdentityHashMapTest extends junit.framework.TestCase {
     private static final String ID = "hello";
@@ -1054,6 +1055,34 @@
         SpliteratorTester.testSpliteratorNPE(values.spliterator());
     }
 
+    public void test_replaceAll() {
+        IdentityHashMap<String, String> map = new IdentityHashMap<>();
+        String key1 = "key1";
+        String key2 = "key2";
+        String key3 = "key3";
+
+        map.put(key1, "1");
+        map.put(key2, "2");
+        map.put(key3, "3");
+
+        map.replaceAll((k, v) -> k + v);
+
+        assertEquals("key11", map.get(key1));
+        assertEquals("key22", map.get(key2));
+        assertEquals("key33", map.get(key3));
+        assertEquals(3, map.size());
+
+        try {
+            map.replaceAll(new BiFunction<String, String, String>() {
+                @Override
+                public String apply(String s, String s2) {
+                    map.put("key4", "4");
+                    return "";
+                }
+            });
+        } catch (ConcurrentModificationException expected) {}
+    }
+
 
     // comparator for IdentityHashMap objects
     private static final SerializableAssert COMPARATOR = new SerializableAssert() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
index 11be2fe..db2ee7a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
@@ -395,4 +395,12 @@
 
         Locale.setDefault(defLocale);
     }
+
+    // http://b/26879578
+    public void testBundleWithUtf8Values() {
+        ResourceBundle bundle = ResourceBundle.getBundle(
+                "org.apache.harmony.tests.java.util.TestUtf8ResourceBundle");
+        assertEquals("Страх мой удивительный UTF-8 синтаксического анализа",
+                bundle.getString("key"));
+    }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
index 173e37e..958d9bc 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
@@ -300,27 +300,6 @@
         assertEquals(6, i);
     }
 
-    public void test_entries2() throws Exception {
-        Support_Resources.copyFile(resources, null, jarName);
-        JarFile jarFile = new JarFile(new File(resources, jarName));
-        Enumeration<JarEntry> enumeration = jarFile.entries();
-        jarFile.close();
-        try {
-            enumeration.hasMoreElements();
-            fail("hasMoreElements() did not detect a closed jar file");
-        } catch (IllegalStateException e) {
-        }
-        Support_Resources.copyFile(resources, null, jarName);
-        jarFile = new JarFile(new File(resources, jarName));
-        enumeration = jarFile.entries();
-        jarFile.close();
-        try {
-            enumeration.nextElement();
-            fail("nextElement() did not detect closed jar file");
-        } catch (IllegalStateException e) {
-        }
-    }
-
     /**
      * @throws IOException
      * java.util.jar.JarFile#getJarEntry(java.lang.String)
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HttpsURLConnectionTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HttpsURLConnectionTest.java
index f2705ea..2b4b916 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HttpsURLConnectionTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HttpsURLConnectionTest.java
@@ -97,16 +97,6 @@
     }
 
     /**
-     * javax.net.ssl.HttpsURLConnection#getDefaultSSLSocketFactory()
-     */
-    public final void test_getDefaultSSLSocketFactory() {
-        SSLSocketFactory sf = HttpsURLConnection.getDefaultSSLSocketFactory();
-        if (!sf.equals(SSLSocketFactory.getDefault())) {
-            fail("incorrect DefaultSSLSocketFactory");
-        }
-    }
-
-    /**
      * javax.net.ssl.HttpsURLConnection#getHostnameVerifier()
      */
     public final void test_getHostnameVerifier()
@@ -186,17 +176,6 @@
     }
 
     /**
-     * javax.net.ssl.HttpsURLConnection#getSSLSocketFactory()
-     */
-    public final void test_getSSLSocketFactory() {
-        HttpsURLConnection con = new MyHttpsURLConnection(null);
-        SSLSocketFactory sf = con.getSSLSocketFactory();
-        if (!sf.equals(SSLSocketFactory.getDefault())) {
-            fail("incorrect DefaultSSLSocketFactory");
-        }
-    }
-
-    /**
      * javax.net.ssl.HttpsURLConnection#setDefaultHostnameVerifier()
      */
     public final void test_setDefaultHostnameVerifier() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/callback/PasswordCallbackTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/callback/PasswordCallbackTest.java
index 024c9e9..8682de7 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/callback/PasswordCallbackTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/callback/PasswordCallbackTest.java
@@ -93,7 +93,7 @@
             }
             pc.clearPassword();
             res = pc.getPassword();
-            if (res.equals(psw2)) {
+            if (Arrays.equals(res, psw2)) {
                 fail("Incorrect password was returned after clear");
             }
             pc.setPassword(psw1);
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index 9ea91a6..7902389 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -21,6 +21,7 @@
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 // Note: this class was written without inspecting the non-free org.json sourcecode.
@@ -100,6 +101,8 @@
         @Override public boolean equals(Object o) {
             return o == this || o == null; // API specifies this broken equals implementation
         }
+        // at least make the broken equals(null) consistent with Objects.hashCode(null).
+        @Override public int hashCode() { return Objects.hashCode(null); }
         @Override public String toString() {
             return "null";
         }
diff --git a/json/src/test/java/org/json/JSONObjectTest.java b/json/src/test/java/org/json/JSONObjectTest.java
index 9029ec6..07d1cf6 100644
--- a/json/src/test/java/org/json/JSONObjectTest.java
+++ b/json/src/test/java/org/json/JSONObjectTest.java
@@ -27,6 +27,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
 import junit.framework.TestCase;
@@ -825,6 +826,12 @@
         assertTrue(object.isNull("bar"));
     }
 
+    public void testNullValue_equalsAndHashCode() {
+        assertTrue(JSONObject.NULL.equals(null)); // guaranteed by javadoc
+        // not guaranteed by javadoc, but seems like a good idea
+        assertEquals(Objects.hashCode(null), JSONObject.NULL.hashCode());
+    }
+
     public void testHas() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", 5);
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java
index 60de8b9..5949cbc 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java
@@ -300,7 +300,7 @@
      */
     public void testGetMappedValue() {
         ConcurrentHashMap map = map5();
-        assertNull(map.keySet().getMappedValue());
+        assertNull(((ConcurrentHashMap.KeySetView) map.keySet()).getMappedValue());
         try {
             map.keySet(null);
             shouldThrow();
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 9b7d24a..8b27ca2 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -39,7 +39,7 @@
     // instruction set name should not exceed 7 characters. See installd
     // and the package manager for the actual propeties.
     private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
-            = new HashMap<String, String>();
+            = new HashMap<String, String>(16);
     static {
         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
@@ -396,4 +396,10 @@
      * set.
      */
     public static native boolean didPruneDalvikCache();
+
+    /**
+     * Register the current execution thread to the runtime as sensitive thread.
+     * Should be called just once. Subsequent calls are ignored.
+     */
+    public static native void registerSensitiveThread();
 }
diff --git a/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java b/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
new file mode 100644
index 0000000..8d05711
--- /dev/null
+++ b/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+import java.util.Properties;
+
+/**
+ * A class encoding all hardcoded system property values on Android. A compiler may
+ * take advantage of these properties. Changing them at load-time (-D) or runtime
+ * may not have any effect.
+ *
+ * @hide
+ */
+public final class AndroidHardcodedSystemProperties {
+
+    // This value is shared with sun.misc.Version. It is defined here so that the compiler
+    // can use it.
+    public final static String JAVA_VERSION = "0";
+
+    final static String[][] STATIC_PROPERTIES = {
+        // None of these four are meaningful on Android, but these keys are guaranteed
+        // to be present for System.getProperty. For java.class.version, we use the maximum
+        // class file version that dx currently supports.
+        { "java.class.version", "50.0" },
+        { "java.version", JAVA_VERSION },
+        { "java.compiler", "" },
+        { "java.ext.dirs", "" },
+
+        { "java.specification.name", "Dalvik Core Library" },
+        { "java.specification.vendor", "The Android Project" },
+        { "java.specification.version", "0.9" },
+
+        { "java.vendor", "The Android Project" },
+        { "java.vendor.url", "http://www.android.com/" },
+        { "java.vm.name", "Dalvik" },
+        { "java.vm.specification.name", "Dalvik Virtual Machine Specification" },
+        { "java.vm.specification.vendor", "The Android Project" },
+        { "java.vm.specification.version", "0.9" },
+        { "java.vm.vendor", "The Android Project" },
+
+        { "java.vm.vendor.url", "http://www.android.com/" },
+
+        { "java.net.preferIPv6Addresses", "false" },
+
+        { "file.encoding", "UTF-8" },
+
+        { "file.separator", "/" },
+        { "line.separator", "\n" },
+        { "path.separator", ":" },
+
+        // Turn off ICU debugging. This allows compile-time initialization of a range of
+        // classes. b/28039175
+        { "ICUDebug", null },
+
+        // Hardcode DecimalFormat parsing flag to be default. b/27265238
+        { "android.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", null },
+        // Hardcode MessagePattern apostrophe mode to be default. b/27265238
+        { "android.icu.text.MessagePattern.ApostropheMode", null },
+
+        // Hardcode "sun.io.useCanonCaches" to use the default (on). b/28174137
+        { "sun.io.useCanonCaches", null },
+        { "sun.io.useCanonPrefixCache", null },
+
+        // Hardcode some http properties to use the default. b/28174137
+        { "http.keepAlive", null },
+        { "http.keepAliveDuration", null },
+        { "http.maxConnections", null },
+
+        // Hardcode "os.name" to "Linux." Aids compile-time initialization, checked in System.
+        // b/28174137
+        { "os.name", "Linux" },
+    };
+}
+
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index 2b93f52..0126765 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -35,7 +35,6 @@
 import com.android.dex.Dex;
 import java.lang.annotation.Annotation;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.GenericSignatureParser;
 import libcore.reflect.ListOfTypes;
 import libcore.reflect.Types;
@@ -198,18 +197,17 @@
         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
     }
 
-    @Override public Annotation[] getDeclaredAnnotations() {
-        List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
-        return result.toArray(new Annotation[result.size()]);
-    }
+    @Override public native Annotation[] getDeclaredAnnotations();
 
     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+        return isAnnotationPresentNative(annotationType);
     }
 
+    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
+
     public Annotation[] getAnnotations() {
         return super.getAnnotations();
     }
@@ -253,7 +251,7 @@
      * Returns generic information associated with this method/constructor member.
      */
     final GenericInfo getMethodOrConstructorGenericInfo() {
-        String signatureAttribute = AnnotationAccess.getSignature(this);
+        String signatureAttribute = getSignatureAttribute();
         Member member;
         Class<?>[] exceptionTypes;
         boolean method = this instanceof Method;
@@ -279,6 +277,20 @@
                                parser.returnType, parser.formalTypeParameters);
     }
 
+    private String getSignatureAttribute() {
+        String[] annotation = getSignatureAnnotation();
+        if (annotation == null) {
+            return null;
+        }
+        StringBuilder result = new StringBuilder();
+        for (String s : annotation) {
+            result.append(s);
+        }
+        return result.toString();
+    }
+
+    private native String[] getSignatureAnnotation();
+
     protected boolean equalMethodParameters(Class<?>[] params) {
         Dex dex = declaringClassOfOverriddenMethod.getDex();
         short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
diff --git a/luni/src/main/java/java/math/BigDecimal.java b/luni/src/main/java/java/math/BigDecimal.java
index 0e89762..0f49056 100644
--- a/luni/src/main/java/java/math/BigDecimal.java
+++ b/luni/src/main/java/java/math/BigDecimal.java
@@ -1035,10 +1035,13 @@
 
         if(this.bitLength < 64 && divisor.bitLength < 64 ) {
             if(diffScale == 0) {
-                return dividePrimitiveLongs(this.smallValue,
-                        divisor.smallValue,
-                        scale,
-                        roundingMode );
+                // http://b/26105053 - corner case: Long.MIN_VALUE / (-1) overflows a long
+                if (this.smallValue != Long.MIN_VALUE || divisor.smallValue != -1) {
+                    return dividePrimitiveLongs(this.smallValue,
+                            divisor.smallValue,
+                            scale,
+                            roundingMode);
+                }
             } else if(diffScale > 0) {
                 if(diffScale < MathUtils.LONG_POWERS_OF_TEN.length &&
                         divisor.bitLength + LONG_POWERS_OF_TEN_BIT_LENGTH[(int)diffScale] < 64) {
@@ -1085,7 +1088,7 @@
         if(scaledDivisor.bitLength() < 63) { // 63 in order to avoid out of long after *2
             long rem = remainder.longValue();
             long divisor = scaledDivisor.longValue();
-            compRem = longCompareTo(Math.abs(rem) * 2,Math.abs(divisor));
+            compRem = compareForRounding(rem, divisor);
             // To look if there is a carry
             compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
                     sign * (5 + compRem), roundingMode);
@@ -1113,8 +1116,7 @@
         int sign = Long.signum( scaledDividend ) * Long.signum( scaledDivisor );
         if (remainder != 0) {
             // Checking if:  remainder * 2 >= scaledDivisor
-            int compRem;                                      // 'compare to remainder'
-            compRem = longCompareTo(Math.abs(remainder) * 2,Math.abs(scaledDivisor));
+            int compRem = compareForRounding(remainder, scaledDivisor); // 'compare to remainder'
             // To look if there is a carry
             quotient += roundingBehavior(((int)quotient) & 1,
                     sign * (5 + compRem),
@@ -2700,9 +2702,36 @@
         setUnscaledValue(integerAndFraction[0]);
     }
 
-    private static int longCompareTo(long value1, long value2) {
+    /**
+     * Returns -1, 0, and 1, respectively, if {@code value1 <, ==, > value2},
+     * respectively, when comparing without regard to the values' sign.
+     * This corresponds to the partial order where {@code 0L} is the smallest
+     * possible value and {@link Long#MIN_VALUE} is the largest because its
+     * absolute value is larger than any possible long value.
+     */
+    private static int compareAbsoluteValues(long value1, long value2) {
+        // Because Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE,
+        // -1 <= Math.abs(v) - 1 <= Long.MAX_VALUE with correct ordering
+        // for v == Long.MIN_VALUE.
+        value1 = Math.abs(value1) - 1;
+        value2 = Math.abs(value2) - 1;
+        // Unlike Long.compare(), we guarantee to return specifically -1 and +1
         return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
     }
+
+    /**
+     * Returns {@code -1, 0, +1} respectively for {@code abs(n/d) <, ==, > 0.5},
+     * respectively, using overflow and rounding safe arithmetics.
+     */
+    private static int compareForRounding(long n, long d) {
+        long halfD = d / 2;
+        if (n == halfD || n == -halfD) {
+            return (int) (d & 1);
+        } else {
+            return compareAbsoluteValues(n, halfD);
+        }
+    }
+
     /**
      * This method implements an efficient rounding for numbers which unscaled
      * value fits in the type {@code long}.
@@ -2724,7 +2753,7 @@
         // If the discarded fraction is non-zero perform rounding
         if (fraction != 0) {
             // To check if the discarded fraction >= 0.5
-            compRem = longCompareTo(Math.abs(fraction) * 2, sizeOfFraction);
+            compRem = compareForRounding(fraction, sizeOfFraction);
             // To look if there is a carry
             integer += roundingBehavior( ((int)integer) & 1,
                     Long.signum(fraction) * (5 + compRem),
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
index 38be0c2..0a73c9f 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
@@ -68,6 +68,7 @@
     private CharsetDecoderICU(Charset cs, float averageCharsPerByte, long address) {
         super(cs, averageCharsPerByte, MAX_CHARS_PER_BYTE);
         this.converterHandle = address;
+        NativeConverter.registerConverter(this, converterHandle);
     }
 
     @Override protected void implReplaceWith(String newReplacement) {
@@ -155,14 +156,6 @@
         }
     }
 
-    @Override protected void finalize() throws Throwable {
-        try {
-            NativeConverter.closeConverter(converterHandle);
-            converterHandle = 0;
-        } finally {
-            super.finalize();
-        }
-    }
 
     private int getArray(CharBuffer out) {
         if (out.hasArray()) {
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index 3583e19..a981c18 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -21,6 +21,7 @@
 import libcore.icu.ICU;
 import libcore.icu.NativeConverter;
 import libcore.util.EmptyArray;
+import libcore.util.NativeAllocationRegistry;
 
 final class CharsetEncoderICU extends CharsetEncoder {
     private static final Map<String, byte[]> DEFAULT_REPLACEMENTS = new HashMap<String, byte[]>();
@@ -49,7 +50,7 @@
     private int[] data = new int[3];
 
     /* handle to the ICU converter that is opened */
-    private long converterHandle=0;
+    private final long converterHandle;
 
     private char[] input = null;
     private byte[] output = null;
@@ -95,6 +96,7 @@
         super(cs, averageBytesPerChar, maxBytesPerChar, replacement, true);
         // Our native peer needs to know what just happened...
         this.converterHandle = address;
+        NativeConverter.registerConverter(this, converterHandle);
         updateCallback();
     }
 
@@ -184,15 +186,6 @@
         }
     }
 
-    @Override protected void finalize() throws Throwable {
-        try {
-            NativeConverter.closeConverter(converterHandle);
-            converterHandle=0;
-        } finally {
-            super.finalize();
-        }
-    }
-
     private int getArray(ByteBuffer out) {
         if (out.hasArray()) {
             output = out.array();
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index 2581230..e4c6df0 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -1201,6 +1201,9 @@
      * operations.  It does not support the {@code add} or
      * {@code addAll} operations.
      *
+     * <p> The set returned by this method is guaranteed to an instance of
+     * {@link KeySetView}.
+     *
      * <p>The view's iterators and spliterators are
      * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
      *
@@ -1209,7 +1212,8 @@
      *
      * @return the set view
      */
-    public KeySetView<K,V> keySet() {
+    // NOTE: The upstream version of this function returns KeySetView (See http://b/28099367).
+    public Set<K> keySet() {
         KeySetView<K,V> ks;
         return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
     }
@@ -4553,8 +4557,7 @@
      * A view of a ConcurrentHashMap as a {@link Set} of keys, in
      * which additions may optionally be enabled by mapping to a
      * common value.  This class cannot be directly instantiated.
-     * See {@link #keySet() keySet()},
-     * {@link #keySet(Object) keySet(V)},
+     * See {@link #keySet(Object) keySet(V)},
      * {@link #newKeySet() newKeySet()},
      * {@link #newKeySet(int) newKeySet(int)}.
      *
diff --git a/luni/src/main/java/javax/xml/datatype/FactoryFinder.java b/luni/src/main/java/javax/xml/datatype/FactoryFinder.java
index 1fbca2f..c31bee3 100644
--- a/luni/src/main/java/javax/xml/datatype/FactoryFinder.java
+++ b/luni/src/main/java/javax/xml/datatype/FactoryFinder.java
@@ -61,8 +61,8 @@
             File f = new File(configFile);
             if (f.exists()) {
                 if (debug) debugPrintln("Read properties file " + f);
-                try {
-                    cacheProps.load(new FileInputStream(f));
+                try (FileInputStream inputStream = new FileInputStream(f)) {
+                    cacheProps.load(inputStream);
                 } catch (Exception ex) {
                     if (debug) {
                         ex.printStackTrace();
diff --git a/luni/src/main/java/javax/xml/validation/SchemaFactoryFinder.java b/luni/src/main/java/javax/xml/validation/SchemaFactoryFinder.java
index 0060612..50a644f 100644
--- a/luni/src/main/java/javax/xml/validation/SchemaFactoryFinder.java
+++ b/luni/src/main/java/javax/xml/validation/SchemaFactoryFinder.java
@@ -62,8 +62,8 @@
             File f = new File(configFile);
             if (f.exists()) {
                 if (debug) debugPrintln("Read properties file " + f);
-                try {
-                    cacheProps.load(new FileInputStream(f));
+                try (FileInputStream inputStream = new FileInputStream(f)) {
+                    cacheProps.load(inputStream);
                 } catch (Exception ex) {
                     if (debug) {
                         ex.printStackTrace();
diff --git a/luni/src/main/java/javax/xml/xpath/XPathFactoryFinder.java b/luni/src/main/java/javax/xml/xpath/XPathFactoryFinder.java
index 5a7663c..7a4f6b3 100644
--- a/luni/src/main/java/javax/xml/xpath/XPathFactoryFinder.java
+++ b/luni/src/main/java/javax/xml/xpath/XPathFactoryFinder.java
@@ -69,8 +69,8 @@
             File f = new File(configFile);
             if (f.exists()) {
                 if (debug) debugPrintln("Read properties file " + f);
-                try {
-                    cacheProps.load(new FileInputStream(f));
+                try (FileInputStream inputStream = new FileInputStream(f)) {
+                    cacheProps.load(inputStream);
                 } catch (Exception ex) {
                     if (debug) {
                         ex.printStackTrace();
diff --git a/luni/src/main/java/libcore/icu/NativeConverter.java b/luni/src/main/java/libcore/icu/NativeConverter.java
index 17be458..a2b5798 100644
--- a/luni/src/main/java/libcore/icu/NativeConverter.java
+++ b/luni/src/main/java/libcore/icu/NativeConverter.java
@@ -9,12 +9,17 @@
 
 package libcore.icu;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CodingErrorAction;
 
 public final class NativeConverter {
+    private static final NativeAllocationRegistry registry = new NativeAllocationRegistry(
+            getNativeFinalizer(), getNativeSize());
+
     public static native int decode(long converterHandle, byte[] input, int inEnd,
             char[] output, int outEnd, int[] data, boolean flush);
 
@@ -24,6 +29,10 @@
     public static native long openConverter(String charsetName);
     public static native void closeConverter(long converterHandle);
 
+    public static void registerConverter(Object referrent, long converterHandle) {
+        registry.registerNativeAllocation(referrent, converterHandle);
+    }
+
     public static native void resetByteToChar(long converterHandle);
     public static native void resetCharToByte(long converterHandle);
 
@@ -67,4 +76,7 @@
                           encoder.replacement());
     }
     private static native void setCallbackEncode(long converterHandle, int onMalformedInput, int onUnmappableInput, byte[] subBytes);
+
+    public static native long getNativeFinalizer();
+    public static native long getNativeSize();
 }
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
deleted file mode 100644
index 2a72c18..0000000
--- a/luni/src/main/java/libcore/reflect/AnnotationAccess.java
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.reflect;
-
-import com.android.dex.Dex;
-import com.android.dex.EncodedValueReader;
-import com.android.dex.FieldId;
-import com.android.dex.MethodId;
-import com.android.dex.ProtoId;
-import com.android.dex.TypeList;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Inherited;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import libcore.util.EmptyArray;
-
-/**
- * Look up annotations from a dex file.
- */
-public final class AnnotationAccess {
-    private AnnotationAccess() {
-    }
-
-    /*
-     * Classes like arrays, primitives and proxies will not have a Dex file.
-     * Such classes never have annotations.
-     */
-
-    private static final Class<?>[] NO_ARGUMENTS = null;
-    @SuppressWarnings("unused")
-    private static final byte VISIBILITY_BUILD = 0x00;
-    private static final byte VISIBILITY_RUNTIME = 0x01;
-    @SuppressWarnings("unused")
-    private static final byte VISIBILITY_SYSTEM = 0x02;
-
-    /*
-     * Class annotations. This includes declared class annotations plus
-     * annotations on the superclass that have @Inherited.
-     */
-
-    public static <A extends java.lang.annotation.Annotation> A getAnnotation(
-            Class<?> c, Class<A> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-
-        A annotation = getDeclaredAnnotation(c, annotationType);
-        if (annotation != null) {
-            return annotation;
-        }
-
-        if (isInherited(annotationType)) {
-            for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-                annotation = getDeclaredAnnotation(sup, annotationType);
-                if (annotation != null) {
-                    return annotation;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns true if {@code annotationType} annotations on the superclass
-     * apply to subclasses that don't have another annotation of the same
-     * type.
-     */
-    private static boolean isInherited(Class<? extends Annotation> annotationType) {
-        return isDeclaredAnnotationPresent(annotationType, Inherited.class);
-    }
-
-    public static Annotation[] getAnnotations(Class<?> c) {
-        /*
-         * We need to get the annotations declared on this class, plus the
-         * annotations from superclasses that have the "@Inherited" annotation
-         * set.  We create a temporary map to use while we accumulate the
-         * annotations and convert it to an array at the end.
-         *
-         * It's possible to have duplicates when annotations are inherited.
-         * We use a Map to filter those out.
-         *
-         * HashMap might be overkill here.
-         */
-        HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
-        for (Annotation declaredAnnotation : getDeclaredAnnotations(c)) {
-            map.put(declaredAnnotation.annotationType(), declaredAnnotation);
-        }
-        for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-            for (Annotation declaredAnnotation : getDeclaredAnnotations(sup)) {
-                Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
-                if (!map.containsKey(clazz) && isInherited(clazz)) {
-                    map.put(clazz, declaredAnnotation);
-                }
-            }
-        }
-
-        /* convert annotation values from HashMap to array */
-        Collection<Annotation> coll = map.values();
-        return coll.toArray(new Annotation[coll.size()]);
-    }
-
-    /**
-     * Returns true if {@code c} is annotated by {@code annotationType}.
-     */
-    public static boolean isAnnotationPresent(
-            Class<?> c, Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-
-        if (isDeclaredAnnotationPresent(c, annotationType)) {
-            return true;
-        }
-
-        if (isInherited(annotationType)) {
-            for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-                if (isDeclaredAnnotationPresent(sup, annotationType)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /*
-     * Class, Field, Method, Constructor and Parameter annotations
-     */
-
-    /**
-     * Returns the annotations on {@code element}.
-     */
-    public static List<Annotation> getDeclaredAnnotations(AnnotatedElement element) {
-        int offset = getAnnotationSetOffset(element);
-        return annotationSetToAnnotations(getDexClass(element), offset);
-    }
-
-    /**
-     * Returns the annotation if it exists.
-     */
-    public static <A extends Annotation> A getDeclaredAnnotation(
-            AnnotatedElement element, Class<A> annotationClass) {
-        com.android.dex.Annotation a = getAnnotation(element, annotationClass);
-        return a != null
-                ? toAnnotationInstance(getDexClass(element), annotationClass, a)
-                : null;
-    }
-
-    /**
-     * Returns true if the annotation exists.
-     */
-    public static boolean isDeclaredAnnotationPresent(
-            AnnotatedElement element, Class<? extends Annotation> annotationClass) {
-        return getAnnotation(element, annotationClass) != null;
-    }
-
-    private static com.android.dex.Annotation getAnnotation(
-            AnnotatedElement element, Class<? extends Annotation> annotationClass) {
-        int annotationSetOffset = getAnnotationSetOffset(element);
-        if (annotationSetOffset == 0) {
-            return null; // no annotation
-        }
-
-        Class<?> dexClass = getDexClass(element);
-        Dex dex = dexClass.getDex();
-        Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
-        String annotationInternalName = InternalNames.getInternalName(annotationClass);
-        for (int i = 0, size = setIn.readInt(); i < size; i++) {
-            int annotationOffset = setIn.readInt();
-            Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
-            // The internal string name of the annotation is compared here and deliberately not
-            // the value of annotationClass.getTypeIndex(). The annotationClass may have been
-            // defined by a different dex file, which would make the indexes incomparable.
-            com.android.dex.Annotation candidate = annotationIn.readAnnotation();
-            String candidateInternalName = dex.typeNames().get(candidate.getTypeIndex());
-            if (candidateInternalName.equals(annotationInternalName)) {
-                return candidate;
-            }
-        }
-
-        return null; // This set doesn't contain the annotation.
-    }
-
-    /**
-     * @param element a class, a field, a method or a constructor.
-     */
-    private static int getAnnotationSetOffset(AnnotatedElement element) {
-        Class<?> dexClass = getDexClass(element);
-        int directoryOffset = dexClass.getDexAnnotationDirectoryOffset();
-        if (directoryOffset == 0) {
-            return 0; // nothing on this class has annotations
-        }
-
-        Dex.Section directoryIn = dexClass.getDex().open(directoryOffset);
-        int classSetOffset = directoryIn.readInt();
-        if (element instanceof Class) {
-            return classSetOffset;
-        }
-
-        int fieldsSize = directoryIn.readInt();
-        int methodsSize = directoryIn.readInt();
-        directoryIn.readInt(); // parameters size
-
-        if (element instanceof Field) {
-            int fieldIndex = ((Field) element).getDexFieldIndex();
-            for (int i = 0; i < fieldsSize; i++) {
-                int candidateFieldIndex = directoryIn.readInt();
-                int annotationSetOffset = directoryIn.readInt();
-                if (candidateFieldIndex == fieldIndex) {
-                    return annotationSetOffset;
-                }
-            }
-            // if we were searching for a field then we missed
-            return 0;
-        }
-
-        // Skip through the fields without reading them and look for constructors or methods.
-        directoryIn.skip(8 * fieldsSize);
-
-        int methodIndex= element instanceof Method ? ((Method) element).getDexMethodIndex()
-                                                   : ((Constructor<?>) element).getDexMethodIndex();
-        for (int i = 0; i < methodsSize; i++) {
-            int candidateMethodIndex = directoryIn.readInt();
-            int annotationSetOffset = directoryIn.readInt();
-            if (candidateMethodIndex == methodIndex) {
-                return annotationSetOffset;
-            }
-        }
-
-        return 0;
-    }
-
-    /**
-     * Returns {@code element} if it is a class; and the class declaring
-     * {@code element} otherwise. The dex file of the returned class also
-     * defines {@code element}.
-     */
-    private static Class<?> getDexClass(AnnotatedElement element) {
-        return element instanceof Class
-                ? ((Class<?>) element)
-                : ((Member) element).getDeclaringClass();
-    }
-
-    /**
-     * Returns the parameter annotations on {@code member}.
-     */
-    public static Annotation[][] getParameterAnnotations(Class<?> declaringClass,
-                                                         int methodDexIndex) {
-        Dex dex = declaringClass.getDex();
-        int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
-        ProtoId proto = dex.protoIds().get(protoIndex);
-        TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
-        short[] types = parametersList.getTypes();
-        int typesCount = types.length;
-
-        int directoryOffset = declaringClass.getDexAnnotationDirectoryOffset();
-        if (directoryOffset == 0) {
-            return new Annotation[typesCount][0]; // nothing on this class has annotations
-        }
-
-        Dex.Section directoryIn = dex.open(directoryOffset);
-        directoryIn.readInt(); // class annotations
-        int fieldsSize = directoryIn.readInt();
-        int methodsSize = directoryIn.readInt();
-        int parametersSize = directoryIn.readInt();
-
-        for (int i = 0; i < fieldsSize; i++) {
-            directoryIn.readInt(); // field_index
-            directoryIn.readInt(); // annotation_set
-        }
-
-        for (int i = 0; i < methodsSize; i++) {
-            directoryIn.readInt(); // method_index
-            directoryIn.readInt(); // annotation_set
-        }
-
-        for (int i = 0; i < parametersSize; i++) {
-            int candidateMethodDexIndex = directoryIn.readInt();
-            int annotationSetRefListOffset = directoryIn.readInt();
-            if (candidateMethodDexIndex != methodDexIndex) {
-                continue;
-            }
-
-            Dex.Section refList = dex.open(annotationSetRefListOffset);
-            int parameterCount = refList.readInt();
-            Annotation[][] result = new Annotation[parameterCount][];
-            for (int p = 0; p < parameterCount; p++) {
-                int annotationSetOffset = refList.readInt();
-                List<Annotation> annotations
-                        = annotationSetToAnnotations(declaringClass, annotationSetOffset);
-                result[p] = annotations.toArray(new Annotation[annotations.size()]);
-            }
-            return result;
-        }
-
-        return new Annotation[typesCount][0];
-    }
-
-    /*
-     * System annotations.
-     */
-
-    public static Object getDefaultValue(Method method) {
-        /*
-         * Dex represents this with @AnnotationDefault on annotations that have
-         * default values:
-         *
-         * @AnnotationDefault(value=@Foo(a=7))
-         * public @interface Foo {
-         *   int a() default 7;
-         *   int b();
-         * }
-         */
-
-        Class<?> annotationClass = method.getDeclaringClass();
-        // All lookups of type and string indexes are within the Dex that declares the annotation so
-        // the indexes can be compared directly.
-        Dex dex = annotationClass.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, annotationClass, "Ldalvik/annotation/AnnotationDefault;");
-        if (reader == null) {
-            return null;
-        }
-
-        int fieldCount = reader.readAnnotation();
-        if (reader.getAnnotationType() != annotationClass.getDexTypeIndex()) {
-            throw new AssertionError("annotation value type != annotation class");
-        }
-
-        int methodNameIndex = dex.findStringIndex(method.getName());
-        for (int i = 0; i < fieldCount; i++) {
-            int candidateNameIndex = reader.readAnnotationName();
-            if (candidateNameIndex == methodNameIndex) {
-                Class<?> returnType = method.getReturnType();
-                return decodeValue(annotationClass, returnType, dex, reader);
-            } else {
-                reader.skipValue();
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the class of which {@code c} is a direct member. If {@code c} is
-     * defined in a method or constructor, this is not transitive.
-     */
-    public static Class<?> getEnclosingClass(Class<?> c) {
-        /*
-         * public class Bar {
-         *   @EnclosingClass(value=Bar)
-         *   public class Foo {}
-         * }
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, c, "Ldalvik/annotation/EnclosingClass;");
-        if (reader == null) {
-            return null;
-        }
-        return c.getDexCacheType(dex, reader.readType());
-    }
-
-    public static AccessibleObject getEnclosingMethodOrConstructor(Class<?> c) {
-        /*
-         * public class Bar {
-         *   public void quux(String s, int i) {
-         *     @EnclosingMethod(value=Bar.quux(String,int))
-         *     class Foo {}
-         *   }
-         * }
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, c, "Ldalvik/annotation/EnclosingMethod;");
-        if (reader == null) {
-            return null;
-        }
-        return indexToMethod(c, dex, reader.readMethod());
-    }
-
-    public static Class<?>[] getMemberClasses(Class<?> c) {
-        /*
-         * @MemberClasses(value=[Bar, Baz])
-         * public class Foo {
-         *   class Bar {}
-         *   class Baz {}
-         * }
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, c, "Ldalvik/annotation/MemberClasses;");
-        if (reader == null) {
-            return EmptyArray.CLASS;
-        }
-        return (Class[]) decodeValue(c, Class[].class, dex, reader);
-    }
-
-    /**
-     * @param element a class, a field, a method or a constructor.
-     */
-    public static String getSignature(AnnotatedElement element) {
-        /*
-         * @Signature(value=["Ljava/util/List", "<", "Ljava/lang/String;", ">;"])
-         * List<String> foo;
-         */
-        Class<?> dexClass = getDexClass(element);
-        Dex dex = dexClass.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, element, "Ldalvik/annotation/Signature;");
-        if (reader == null) {
-            return null;
-        }
-        String[] array = (String[]) decodeValue(dexClass, String[].class, dex, reader);
-        StringBuilder result = new StringBuilder();
-        for (String s : array) {
-            result.append(s);
-        }
-        return result.toString();
-    }
-
-    /**
-     * @param element a method or a constructor.
-     */
-    public static Class<?>[] getExceptions(AnnotatedElement element) {
-        /*
-         * @Throws(value=[IOException.class])
-         * void foo() throws IOException;
-         */
-        Class<?> dexClass = getDexClass(element);
-        Dex dex = dexClass.getDex();
-        EncodedValueReader reader = getOnlyAnnotationValue(
-                dex, element, "Ldalvik/annotation/Throws;");
-        if (reader == null) {
-            return EmptyArray.CLASS;
-        }
-        return (Class<?>[]) decodeValue(dexClass, Class[].class, dex, reader);
-    }
-
-    public static int getInnerClassFlags(Class<?> c, int defaultValue) {
-        /*
-         * @InnerClass(accessFlags=0x01,name="Foo")
-         * class Foo {};
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getAnnotationReader(
-                dex, c, "Ldalvik/annotation/InnerClass;", 2);
-        if (reader == null) {
-            return defaultValue;
-        }
-        reader.readAnnotationName(); // accessFlags
-        return reader.readInt();
-    }
-
-    public static String getInnerClassName(Class<?> c) {
-        /*
-         * @InnerClass(accessFlags=0x01,name="Foo")
-         * class Foo {};
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getAnnotationReader(
-                dex, c, "Ldalvik/annotation/InnerClass;", 2);
-        if (reader == null) {
-            return null;
-        }
-        reader.readAnnotationName(); // accessFlags
-        reader.readInt();
-        reader.readAnnotationName(); // name
-        return reader.peek() == EncodedValueReader.ENCODED_NULL
-                ? null
-                : (String) decodeValue(c, String.class, dex, reader);
-    }
-
-    public static boolean isAnonymousClass(Class<?> c) {
-        /*
-         * @InnerClass(accessFlags=0x01,name="Foo")
-         * class Foo {};
-         */
-        Dex dex = c.getDex();
-        EncodedValueReader reader = getAnnotationReader(
-                dex, c, "Ldalvik/annotation/InnerClass;", 2);
-        if (reader == null) {
-            return false;
-        }
-        reader.readAnnotationName(); // accessFlags
-        reader.readInt();
-        reader.readAnnotationName(); // name
-        return reader.peek() == EncodedValueReader.ENCODED_NULL;
-    }
-
-    /*
-     * Dex support.
-     *
-     * Different classes come from different Dex files. This class is careful
-     * to guarantee that Dex-relative indices and encoded values are interpreted
-     * using the Dex that they were read from. Methods that use Dex-relative
-     * values accept that Dex as a parameter or the class from which that Dex
-     * was derived.
-     */
-
-    private static EncodedValueReader getAnnotationReader(
-            Dex dex, AnnotatedElement element, String annotationName, int expectedFieldCount) {
-        int annotationSetOffset = getAnnotationSetOffset(element);
-        if (annotationSetOffset == 0) {
-            return null; // no annotations on the class
-        }
-
-        Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
-        com.android.dex.Annotation annotation = null;
-        // TODO: is it better to compute the index of the annotation name in the dex file and check
-        //       indices below?
-        for (int i = 0, size = setIn.readInt(); i < size; i++) {
-            int annotationOffset = setIn.readInt();
-            Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
-            com.android.dex.Annotation candidate = annotationIn.readAnnotation();
-            String candidateAnnotationName = dex.typeNames().get(candidate.getTypeIndex());
-            if (annotationName.equals(candidateAnnotationName)) {
-                annotation = candidate;
-                break;
-            }
-        }
-        if (annotation == null) {
-            return null; // no annotation
-        }
-
-        EncodedValueReader reader = annotation.getReader();
-        int fieldCount = reader.readAnnotation();
-        String readerAnnotationName = dex.typeNames().get(reader.getAnnotationType());
-        if (!readerAnnotationName.equals(annotationName)) {
-            throw new AssertionError();
-        }
-        if (fieldCount != expectedFieldCount) {
-            return null; // not the expected values on this annotation; give up
-        }
-
-        return reader;
-    }
-
-    /**
-     * Returns a reader ready to read the only value of the annotation on
-     * {@code element}, or null if that annotation doesn't exist.
-     */
-    private static EncodedValueReader getOnlyAnnotationValue(
-            Dex dex, AnnotatedElement element, String annotationName) {
-        EncodedValueReader reader = getAnnotationReader(dex, element, annotationName, 1);
-        if (reader == null) {
-            return null;
-        }
-        reader.readAnnotationName(); // skip the name
-        return reader;
-    }
-
-    private static Class<? extends Annotation> getAnnotationClass(Class<?> context, Dex dex,
-                                                                  int typeIndex) {
-        try {
-            @SuppressWarnings("unchecked") // we do a runtime check
-            Class<? extends Annotation> result =
-                (Class<? extends Annotation>) context.getDexCacheType(dex, typeIndex);
-            if (!result.isAnnotation()) {
-                throw new IncompatibleClassChangeError("Expected annotation: " + result.getName());
-            }
-            return result;
-        } catch (NoClassDefFoundError ncdfe) {
-            return null;
-        }
-    }
-
-    private static AccessibleObject indexToMethod(Class<?> context, Dex dex, int methodIndex) {
-        Class<?> declaringClass =
-            context.getDexCacheType(dex, dex.declaringClassIndexFromMethodIndex(methodIndex));
-        String name = context.getDexCacheString(dex, dex.nameIndexFromMethodIndex(methodIndex));
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(methodIndex);
-        Class<?>[] parametersArray = new Class[types.length];
-        for (int i = 0; i < types.length; i++) {
-            parametersArray[i] = context.getDexCacheType(dex, types[i]);
-        }
-        try {
-            return name.equals("<init>")
-                ? declaringClass.getDeclaredConstructor(parametersArray)
-                : declaringClass.getDeclaredMethod(name, parametersArray);
-        } catch (NoSuchMethodException e) {
-            throw new IncompatibleClassChangeError("Couldn't find " + declaringClass.getName()
-                                                   + "." + name + Arrays.toString(parametersArray));
-        }
-    }
-
-    private static List<Annotation> annotationSetToAnnotations(Class<?> context, int offset) {
-        if (offset == 0) {
-            return Collections.emptyList(); // no annotations in the set
-        }
-
-        Dex dex = context.getDex();
-        Dex.Section setIn = dex.open(offset); // annotation_set_item
-        int size = setIn.readInt();
-        List<Annotation> result = new ArrayList<Annotation>(size);
-
-        for (int i = 0; i < size; i++) {
-            int annotationOffset = setIn.readInt();
-            Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
-            com.android.dex.Annotation annotation = annotationIn.readAnnotation();
-            if (annotation.getVisibility() != VISIBILITY_RUNTIME) {
-                continue;
-            }
-            Class<? extends Annotation> annotationClass =
-                    getAnnotationClass(context, dex, annotation.getTypeIndex());
-            if (annotationClass != null) {
-                result.add(toAnnotationInstance(context, dex, annotationClass, annotation.getReader()));
-            }
-        }
-        return result;
-    }
-
-    private static <A extends Annotation> A toAnnotationInstance(Class<?> context,
-            Class<A> annotationClass, com.android.dex.Annotation annotation) {
-        return toAnnotationInstance(context, context.getDex(), annotationClass,
-                annotation.getReader());
-    }
-
-    private static <A extends Annotation> A toAnnotationInstance(Class<?> context, Dex dex,
-            Class<A> annotationClass, EncodedValueReader reader) {
-        int fieldCount = reader.readAnnotation();
-        if (annotationClass != context.getDexCacheType(dex, reader.getAnnotationType())) {
-            throw new AssertionError("annotation value type != return type");
-        }
-        AnnotationMember[] members = new AnnotationMember[fieldCount];
-        for (int i = 0; i < fieldCount; i++) {
-            int name = reader.readAnnotationName();
-            String nameString = dex.strings().get(name);
-            Method method;
-            try {
-                method = annotationClass.getMethod(nameString, NO_ARGUMENTS);
-            } catch (NoSuchMethodException e) {
-                throw new IncompatibleClassChangeError(
-                        "Couldn't find " + annotationClass.getName() + "." + nameString);
-            }
-            Class<?> returnType = method.getReturnType();
-            Object value = decodeValue(context, returnType, dex, reader);
-            members[i] = new AnnotationMember(nameString, value, returnType, method);
-        }
-        return AnnotationFactory.createAnnotation(annotationClass, members);
-    }
-
-    private static Object decodeValue(Class<?> context, Class<?> type,
-            Dex dex, EncodedValueReader reader) {
-        if (type.isArray()) {
-            int size = reader.readArray();
-            Class<?> componentType = type.getComponentType();
-            Object array = Array.newInstance(componentType, size);
-            for (int i = 0; i < size; i++) {
-                Array.set(array, i, decodeValue(context, componentType, dex, reader));
-            }
-            return array;
-        } else if (type.isEnum()) {
-            int fieldIndex = reader.readEnum();
-            FieldId fieldId = dex.fieldIds().get(fieldIndex);
-            String fieldName = dex.strings().get(fieldId.getNameIndex());
-            Field field;
-            try {
-                field = type.getDeclaredField(fieldName);
-                return field.get(null);
-            } catch (NoSuchFieldException e) {
-                NoSuchFieldError error = new NoSuchFieldError();
-                error.initCause(e);
-                throw error;
-            } catch (IllegalAccessException e) {
-                IllegalAccessError error = new IllegalAccessError();
-                error.initCause(e);
-                throw error;
-            }
-        } else if (type.isAnnotation()) {
-            @SuppressWarnings("unchecked") // Class.isAnnotation is the runtime check
-            Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) type;
-            return toAnnotationInstance(context, dex, annotationClass, reader);
-        } else if (type == String.class) {
-            int index = reader.readString();
-            return context.getDexCacheString(dex, index);
-        } else if (type == Class.class) {
-            int index = reader.readType();
-            return context.getDexCacheType(dex, index);
-        } else if (type == byte.class) {
-            return reader.readByte();
-        } else if (type == short.class) {
-            return reader.readShort();
-        } else if (type == int.class) {
-            return reader.readInt();
-        } else if (type == long.class) {
-            return reader.readLong();
-        } else if (type == float.class) {
-            return reader.readFloat();
-        } else if (type == double.class) {
-            return reader.readDouble();
-        } else if (type == char.class) {
-            return reader.readChar();
-        } else if (type == boolean.class) {
-            return reader.readBoolean();
-        } else {
-            // is null legit?
-            throw new AssertionError("Unexpected annotation value type: " + type);
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/reflect/TypeVariableImpl.java b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
index 2eb9827..6bf1881 100644
--- a/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
+++ b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
@@ -84,7 +84,8 @@
         if (decl instanceof Class) {
             // FIXME: Is the following hierarchy correct?:
             Class cl = (Class)decl;
-            decl = (GenericDeclaration) AnnotationAccess.getEnclosingMethodOrConstructor(cl);
+            Method m = cl.getEnclosingMethod();
+            decl = (GenericDeclaration) m != null ? m : cl.getEnclosingConstructor();
             if (decl != null) {
                 return decl;
             }
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/DOMConfigurationImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/DOMConfigurationImpl.java
index 6724776..0eda8f0 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/DOMConfigurationImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/DOMConfigurationImpl.java
@@ -357,6 +357,10 @@
     }
 
     public DOMStringList getParameterNames() {
+        return internalGetParameterNames();
+    }
+
+    private static DOMStringList internalGetParameterNames() {
         final String[] result = PARAMETERS.keySet().toArray(new String[PARAMETERS.size()]);
         return new DOMStringList() {
             public String item(int index) {
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
index e1b62fa..e4002ea 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
@@ -56,7 +56,6 @@
      */
     private String documentUri;
     private String inputEncoding;
-    private String xmlEncoding;
     private String xmlVersion = "1.0";
     private boolean xmlStandalone = false;
     private boolean strictErrorChecking = true;
@@ -437,7 +436,7 @@
     }
 
     public String getXmlEncoding() {
-        return xmlEncoding;
+        return null;
     }
 
     public boolean getXmlStandalone() {
diff --git a/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
index 040a012..4f54fb5 100644
--- a/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
@@ -129,11 +129,12 @@
 
             parser.require(XmlPullParser.END_DOCUMENT, null, null);
         } catch (XmlPullParserException ex) {
-            if (ex.getDetail() instanceof IOException) {
-                throw (IOException) ex.getDetail();
+            Throwable detail = ex.getDetail();
+            if (detail instanceof IOException) {
+                throw (IOException) detail;
             }
-            if (ex.getDetail() instanceof RuntimeException) {
-                throw (RuntimeException) ex.getDetail();
+            if (detail instanceof RuntimeException) {
+                throw (RuntimeException) detail;
             }
 
             LocatorImpl locator = new LocatorImpl();
diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
index c4ff069..39dd367 100644
--- a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
+++ b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
@@ -126,9 +126,12 @@
             in = loader.getResourceAsStream (service);
 
         if (in != null) {
-            reader = new BufferedReader (new InputStreamReader (in, StandardCharsets.UTF_8));
-            className = reader.readLine ();
-            in.close ();
+            try {
+                reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+                className = reader.readLine();
+            } finally {
+                in.close(); // may throw IOException
+            }
         }
         } catch (Exception e) {
         }
diff --git a/luni/src/main/native/java_util_regex_Matcher.cpp b/luni/src/main/native/java_util_regex_Matcher.cpp
index 35d014c..3b25233 100644
--- a/luni/src/main/native/java_util_regex_Matcher.cpp
+++ b/luni/src/main/native/java_util_regex_Matcher.cpp
@@ -116,8 +116,18 @@
     void operator=(const MatcherAccessor&);
 };
 
-static void Matcher_closeImpl(JNIEnv*, jclass, jlong address) {
-    delete toRegexMatcher(address);
+static void Matcher_free(void* address) {
+    delete reinterpret_cast<icu::RegexMatcher*>(address);
+}
+
+static jlong Matcher_getNativeFinalizer(JNIEnv*, jclass) {
+    return reinterpret_cast<jlong>(&Matcher_free);
+}
+
+// Return a guess of the amount of native memory to be deallocated by a typical call to
+// Matcher_free().
+static jint Matcher_nativeSize(JNIEnv*, jclass) {
+    return 200;  // Very rough guess based on a quick look at the implementation.
 }
 
 static jint Matcher_findImpl(JNIEnv* env, jclass, jlong addr, jstring javaText, jint startIndex, jintArray offsets) {
@@ -198,13 +208,14 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(Matcher, closeImpl, "(J)V"),
     NATIVE_METHOD(Matcher, findImpl, "(JLjava/lang/String;I[I)Z"),
     NATIVE_METHOD(Matcher, findNextImpl, "(JLjava/lang/String;[I)Z"),
+    NATIVE_METHOD(Matcher, getNativeFinalizer, "()J"),
     NATIVE_METHOD(Matcher, groupCountImpl, "(J)I"),
     NATIVE_METHOD(Matcher, hitEndImpl, "(J)Z"),
     NATIVE_METHOD(Matcher, lookingAtImpl, "(JLjava/lang/String;[I)Z"),
     NATIVE_METHOD(Matcher, matchesImpl, "(JLjava/lang/String;[I)Z"),
+    NATIVE_METHOD(Matcher, nativeSize, "()I"),
     NATIVE_METHOD(Matcher, openImpl, "(J)J"),
     NATIVE_METHOD(Matcher, requireEndImpl, "(J)Z"),
     NATIVE_METHOD(Matcher, setInputImpl, "(JLjava/lang/String;II)V"),
diff --git a/luni/src/main/native/java_util_regex_Pattern.cpp b/luni/src/main/native/java_util_regex_Pattern.cpp
index f2c07dc..4166da03 100644
--- a/luni/src/main/native/java_util_regex_Pattern.cpp
+++ b/luni/src/main/native/java_util_regex_Pattern.cpp
@@ -27,10 +27,6 @@
 
 // ICU documentation: http://icu-project.org/apiref/icu4c/classRegexPattern.html
 
-static icu::RegexPattern* toRegexPattern(jlong addr) {
-    return reinterpret_cast<icu::RegexPattern*>(static_cast<uintptr_t>(addr));
-}
-
 static const char* regexDetailMessage(UErrorCode status) {
     // These human-readable error messages were culled from "utypes.h", and then slightly tuned
     // to make more sense in context.
@@ -71,8 +67,18 @@
     env->Throw(reinterpret_cast<jthrowable>(exception));
 }
 
-static void Pattern_closeImpl(JNIEnv*, jclass, jlong addr) {
-    delete toRegexPattern(addr);
+static void Pattern_free(void* addr) {
+    delete reinterpret_cast<icu::RegexPattern*>(addr);
+}
+
+static jlong Pattern_getNativeFinalizer(JNIEnv*, jclass) {
+    return reinterpret_cast<jlong>(&Pattern_free);
+}
+
+// Return a guess of the amount of native memory to be deallocated by a typical call to
+// Pattern_free().
+static jint Pattern_nativeSize(JNIEnv*, jclass) {
+    return 500;  // Very rough guess based on a quick look at the implementation.
 }
 
 static jlong Pattern_compileImpl(JNIEnv* env, jclass, jstring javaRegex, jint flags) {
@@ -95,9 +101,11 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(Pattern, closeImpl, "(J)V"),
     NATIVE_METHOD(Pattern, compileImpl, "(Ljava/lang/String;I)J"),
+    NATIVE_METHOD(Pattern, getNativeFinalizer, "()J"),
+    NATIVE_METHOD(Pattern, nativeSize, "()I"),
 };
+
 void register_java_util_regex_Pattern(JNIEnv* env) {
     jniRegisterNativeMethods(env, "java/util/regex/Pattern", gMethods, NELEM(gMethods));
 }
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 334f4c9..bf938d1 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -611,6 +611,20 @@
             javaCanonicalName, icuCanonicalNameStr, javaAliases);
 }
 
+static void FreeNativeConverter(void *converter) {
+    ucnv_close(reinterpret_cast<UConverter*>(converter));
+}
+
+static jlong NativeConverter_getNativeFinalizer(JNIEnv*, jclass) {
+    return reinterpret_cast<jlong>(&FreeNativeConverter);
+}
+
+
+static jlong NativeConverter_getNativeSize(JNIEnv*, jclass, jstring) {
+    // TODO: Improve estimate.
+    return 200;
+}
+
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"),
     NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"),
@@ -628,6 +642,8 @@
     NATIVE_METHOD(NativeConverter, resetCharToByte, "(J)V"),
     NATIVE_METHOD(NativeConverter, setCallbackDecode, "(JIILjava/lang/String;)V"),
     NATIVE_METHOD(NativeConverter, setCallbackEncode, "(JII[B)V"),
+    NATIVE_METHOD(NativeConverter, getNativeFinalizer, "()J"),
+    NATIVE_METHOD(NativeConverter, getNativeSize, "()J")
 };
 void register_libcore_icu_NativeConverter(JNIEnv* env) {
     jniRegisterNativeMethods(env, "libcore/icu/NativeConverter", gMethods, NELEM(gMethods));
diff --git a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
index 398adbc..74432e5 100644
--- a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
@@ -223,6 +223,28 @@
         assertTrue(getOpenFdsForPrefix("test_bug_25695227").isEmpty());
     }
 
+    // http://b/28192631
+    public void testSkipOnLargeFiles() throws Exception {
+        File largeFile = File.createTempFile("FileInputStreamTest_testSkipOnLargeFiles", "");
+        FileOutputStream fos = new FileOutputStream(largeFile);
+        try {
+            byte[] buffer = new byte[1024 * 1024]; // 1 MB
+            for (int i = 0; i < 3 * 1024; i++) { // 3 GB
+                fos.write(buffer);
+            }
+        } finally {
+            fos.close();
+        }
+
+        FileInputStream fis = new FileInputStream(largeFile);
+        long lastByte = 3 * 1024 * 1024 * 1024L - 1;
+        assertEquals(0, Libcore.os.lseek(fis.getFD(), 0, OsConstants.SEEK_CUR));
+        assertEquals(lastByte, fis.skip(lastByte));
+
+        // Proactively cleanup - it's a pretty large file.
+        assertTrue(largeFile.delete());
+    }
+
     private static List<Integer> getOpenFdsForPrefix(String path) throws Exception {
         File[] fds = new File("/proc/self/fd").listFiles();
         List<Integer> list = new ArrayList<>();
diff --git a/luni/src/test/java/libcore/java/io/FileTest.java b/luni/src/test/java/libcore/java/io/FileTest.java
index 93b6708..5d5317a 100644
--- a/luni/src/test/java/libcore/java/io/FileTest.java
+++ b/luni/src/test/java/libcore/java/io/FileTest.java
@@ -337,13 +337,14 @@
     // http://b/27273930
     public void testJavaIoTmpdirMutable() throws Exception {
         final String oldTmpDir = System.getProperty("java.io.tmpdir");
-        final String newTmpDir = oldTmpDir + "/newTemp";
-        File subDir = new File(oldTmpDir, "newTemp");
+        final String directoryName = "/newTemp" + Integer.toString(Math.randomIntInternal());
+        final String newTmpDir = oldTmpDir + directoryName;
+        File subDir = new File(oldTmpDir, directoryName);
         assertTrue(subDir.mkdir());
         try {
             System.setProperty("java.io.tmpdir", newTmpDir);
             File tempFile = File.createTempFile("foo", ".bar");
-            assertTrue(tempFile.getAbsolutePath().contains("/newTemp/"));
+            assertTrue(tempFile.getAbsolutePath().contains(directoryName));
         } finally {
             System.setProperty("java.io.tmpdir", oldTmpDir);
         }
diff --git a/luni/src/test/java/libcore/java/io/ObjectOutputStreamTest.java b/luni/src/test/java/libcore/java/io/ObjectOutputStreamTest.java
index 9228162..3adc030 100644
--- a/luni/src/test/java/libcore/java/io/ObjectOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/ObjectOutputStreamTest.java
@@ -16,8 +16,14 @@
 
 package libcore.java.io;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
 import junit.framework.TestCase;
 
 public final class ObjectOutputStreamTest extends TestCase {
@@ -32,4 +38,74 @@
         ObjectOutputStream os = new ObjectOutputStream(new ByteArrayOutputStream());
         os.writeObject(s);
     }
+
+    public static class CallsCloseInWriteObjectMethod implements Serializable {
+        private String message;
+
+        public CallsCloseInWriteObjectMethod(String message) {
+            this.message = message;
+        }
+
+        private void writeObject(ObjectOutputStream oos) throws IOException {
+            oos.writeObject(message);
+            oos.close();
+        }
+
+        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+            message = (String) ois.readObject();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            CallsCloseInWriteObjectMethod that = (CallsCloseInWriteObjectMethod) o;
+
+            return message.equals(that.message);
+        }
+
+        @Override
+        public int hashCode() {
+            return message.hashCode();
+        }
+    }
+
+    // http://b/28159133
+    public void testCloseInWriteObject() throws Exception {
+        String hello = "Hello";
+        CallsCloseInWriteObjectMethod object = new CallsCloseInWriteObjectMethod(hello);
+        // This reproduces the problem in http://b/28159133 as follows:
+        //   the list class gets handle N
+        //   the object closes the ObjectOutputStream and clears the handle table
+        //   the hello gets handle N
+        //   the reuse of hello has a reference to handle N
+        // When it is deserialized the list contains object, hello, Arrays.asList().getClass()
+        // instead of object, hello, hello.
+        List<Serializable> input = Arrays.asList(object, hello, hello);
+        @SuppressWarnings("unchecked")
+        List<CallsCloseInWriteObjectMethod> output = (List<CallsCloseInWriteObjectMethod>)
+                roundTrip(input);
+
+        assertEquals(input, output);
+    }
+
+    private Serializable roundTrip(Object object)
+            throws IOException, ClassNotFoundException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(object);
+        }
+
+        Serializable read;
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        try (ObjectInputStream ois = new ObjectInputStream(bais)) {
+            read = (Serializable) ois.readObject();
+        }
+        return read;
+    }
 }
diff --git a/luni/src/test/java/libcore/java/io/UncheckedIOExceptionTest.java b/luni/src/test/java/libcore/java/io/UncheckedIOExceptionTest.java
new file mode 100644
index 0000000..0d67277
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/UncheckedIOExceptionTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
+public class UncheckedIOExceptionTest extends TestCase {
+
+    /**
+     * java.lang.UncheckedIOException#UncheckedIOException(java.io.IOException)
+     */
+    public void test_ConstructorLjava_lang_IOException() {
+        IOException ioException = new IOException();
+        UncheckedIOException e = new UncheckedIOException(ioException);
+        assertEquals("java.io.IOException", e.getMessage());
+        assertSame(ioException, e.getCause());
+    }
+
+    /**
+     * java.lang.UncheckedIOException#UncheckedIOException(java.lang.String, java.io.IOException)
+     */
+    public void test_ConstructorLjava_lang_String_IOException() {
+        IOException ioException = new IOException();
+        UncheckedIOException e = new UncheckedIOException("errmsg", ioException);
+        assertEquals("errmsg", e.getMessage());
+        assertSame(ioException, e.getCause());
+    }
+
+    /**
+     * serialization/deserialization.
+     */
+    public void testSerializationSelf() throws Exception {
+        SerializationTest.verifySelf(new UncheckedIOException(new IOException()));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/BooleanTest.java b/luni/src/test/java/libcore/java/lang/BooleanTest.java
index b1f536f..10dac92 100644
--- a/luni/src/test/java/libcore/java/lang/BooleanTest.java
+++ b/luni/src/test/java/libcore/java/lang/BooleanTest.java
@@ -38,4 +38,25 @@
         assertEquals(Boolean.TRUE.hashCode(), Boolean.hashCode(true));
         assertEquals(Boolean.FALSE.hashCode(), Boolean.hashCode(false));
     }
+
+    public void testLogicalAnd() {
+        assertTrue(Boolean.logicalAnd(Boolean.TRUE, Boolean.TRUE));
+        assertFalse(Boolean.logicalAnd(Boolean.TRUE, Boolean.FALSE));
+        assertFalse(Boolean.logicalAnd(Boolean.FALSE, Boolean.TRUE));
+        assertFalse(Boolean.logicalAnd(Boolean.FALSE, Boolean.FALSE));
+    }
+
+    public void testLogicalOr() {
+        assertTrue(Boolean.logicalOr(Boolean.TRUE, Boolean.TRUE));
+        assertTrue(Boolean.logicalOr(Boolean.TRUE, Boolean.FALSE));
+        assertTrue(Boolean.logicalOr(Boolean.FALSE, Boolean.TRUE));
+        assertFalse(Boolean.logicalOr(Boolean.FALSE, Boolean.FALSE));
+    }
+
+    public void testLogicalXor() {
+        assertFalse(Boolean.logicalXor(Boolean.TRUE, Boolean.TRUE));
+        assertTrue(Boolean.logicalXor(Boolean.TRUE, Boolean.FALSE));
+        assertTrue(Boolean.logicalXor(Boolean.FALSE, Boolean.TRUE));
+        assertFalse(Boolean.logicalXor(Boolean.FALSE, Boolean.FALSE));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/MathTest.java b/luni/src/test/java/libcore/java/lang/MathTest.java
new file mode 100644
index 0000000..f7ebaa6
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/MathTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang;
+
+import junit.framework.TestCase;
+
+import java.math.BigInteger;
+
+public class MathTest extends TestCase {
+
+    public void testIntExact() {
+        testIntExact(123, 456);
+        testIntExact(-456, 456);
+        testIntExact(0, 0);
+        testIntExact(Integer.MAX_VALUE, 1);
+        testIntExact(Integer.MAX_VALUE, -1);
+        testIntExact(Integer.MIN_VALUE, 1);
+        testIntExact(Integer.MIN_VALUE, -1);
+        testIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
+        testIntExact(Integer.MIN_VALUE, Integer.MIN_VALUE);
+    }
+
+    private void testIntExact(int a, int b) {
+        testAddExactI(a, b);
+        testSubtractExactI(a, b);
+        testMultiplyExactI(a, b);
+        testIncrementExactI(a);
+        testDecrementExactI(a);
+        testNegateExactI(a);
+    }
+
+    private void testAddExactI(int a, int b) {
+        long expected = (long) a + (long) b;
+        try {
+            assertEquals(expected, Math.addExact(a, b));
+        } catch (ArithmeticException e) {
+            if (expected == a + b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testSubtractExactI(int a, int b) {
+        long expected = (long) a - (long) b;
+        try {
+            assertEquals(expected, Math.subtractExact(a, b));
+        } catch (ArithmeticException e) {
+            long result = (long) a - (long) b;
+            if (expected == a - b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testMultiplyExactI(int a, int b) {
+        long expected = (long) a * (long) b;
+        try {
+            assertEquals(expected, Math.multiplyExact(a, b));
+        } catch (ArithmeticException e) {
+            if (expected == a * b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testIncrementExactI(int a) {
+        long expected = (long) a + 1L;
+        try {
+            assertEquals(expected, Math.incrementExact(a));
+        } catch (ArithmeticException e) {
+            if (expected == a + 1) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testDecrementExactI(int a) {
+        long expected = (long) a - 1L;
+        try {
+            assertEquals(expected, Math.decrementExact(a));
+        } catch (ArithmeticException e) {
+            if (expected == a - 1) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testNegateExactI(int a) {
+        long expected = -((long) a);
+        try {
+            assertEquals(expected, Math.negateExact(a));
+        } catch (ArithmeticException e) {
+            if (expected == -a) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    public void testLongExact() {
+        testLongExact(123, 456);
+        testLongExact(-456, 456);
+        testLongExact(0, 0);
+        testLongExact(Long.MAX_VALUE, 1);
+        testLongExact(Long.MAX_VALUE, -1);
+        testLongExact(Long.MIN_VALUE, 1);
+        testLongExact(Long.MIN_VALUE, -1);
+        testLongExact(Long.MAX_VALUE, Long.MAX_VALUE);
+        testLongExact(Long.MIN_VALUE, Long.MIN_VALUE);
+    }
+
+    private void testLongExact(long a, long b) {
+        testAddExactL(a, b);
+        testSubtractExactL(a, b);
+        testMultiplyExactL(a, b);
+        testIncrementExactL(a);
+        testDecrementExactL(a);
+        testNegateExactL(a);
+        testToIntExactL(a);
+    }
+
+    private void testAddExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).add(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.addExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a + b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testSubtractExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).subtract(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.subtractExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a - b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testMultiplyExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).multiply(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.multiplyExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a * b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testIncrementExactL(long a) {
+        BigInteger expected = BigInteger.valueOf(a).add(BigInteger.ONE);
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.incrementExact(a)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a + 1L))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testDecrementExactL(long a) {
+        BigInteger expected = BigInteger.valueOf(a).subtract(BigInteger.ONE);
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.decrementExact(a)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a - 1L))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testNegateExactL(long a) {
+        BigInteger expected = BigInteger.valueOf(a).negate();
+        try {
+            assertEquals(expected, BigInteger.valueOf(Math.negateExact(a)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(-a))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testToIntExactL(long a) {
+        try {
+            assertEquals((int) a, Math.toIntExact(a));
+            assertEquals(a, Math.toIntExact(a)); // Is not exact, should throw AE.
+        } catch (ArithmeticException e) {
+            if (a <= Integer.MAX_VALUE && a >= Integer.MIN_VALUE) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    public void testIntFloorDivMod() {
+        testFloorDivModI(123, 456);
+        testFloorDivModI(456, 123);
+        testFloorDivModI(369, 123);
+        testFloorDivModI(1, 0);
+        testFloorDivModI(Integer.MAX_VALUE, 1);
+        testFloorDivModI(Integer.MAX_VALUE, -1);
+        testFloorDivModI(Integer.MIN_VALUE, 1);
+        testFloorDivModI(Integer.MIN_VALUE, -1);
+    }
+
+    private void testFloorDivModI(int a, int b) {
+        testFloorDivI(a, b);
+        testFloorModI(a, b);
+    }
+
+    private void testFloorDivI(int a, int b) {
+        try {
+            int floorDiv = Math.floorDiv(a, b);
+            int expected = a / b;
+            if (expected < 0 && a % b != 0) {
+                --expected;
+            }
+            assertEquals(expected, floorDiv);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    private void testFloorModI(int a, int b) {
+        try {
+            int floorMod = Math.floorMod(a, b);
+            int expected = a % b;
+            if ((a ^ b) < 0 && expected != 0) {
+                expected = b - expected;
+            }
+            assertEquals(expected, floorMod);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    public void testLongFloorDivMod() {
+        testFloorDivModL(123L, 456L);
+        testFloorDivModL(456L, 123L);
+        testFloorDivModL(369L, 123L);
+        testFloorDivModL(1L, 0L);
+        testFloorDivModL(Long.MAX_VALUE, 1L);
+        testFloorDivModL(Long.MAX_VALUE, -1L);
+        testFloorDivModL(Long.MIN_VALUE, 1L);
+        testFloorDivModL(Long.MIN_VALUE, -1L);
+    }
+
+    private void testFloorDivModL(long a, long b) {
+        testFloorDivL(a, b);
+        testFloorModL(a, b);
+    }
+
+    private void testFloorDivL(long a, long b) {
+        try {
+            long floorDiv = Math.floorDiv(a, b);
+            long expected = a / b;
+            if (expected < 0 && a % b != 0) {
+                --expected;
+            }
+            assertEquals(expected, floorDiv);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    private void testFloorModL(long a, long b) {
+        try {
+            long floorMod = Math.floorMod(a, b);
+            long expected = a % b;
+            if ((a ^ b) < 0 && expected != 0) {
+                expected = b - expected;
+            }
+            assertEquals(expected, floorMod);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/OldSystemTest.java b/luni/src/test/java/libcore/java/lang/OldSystemTest.java
index f7a69a3..6c12250 100644
--- a/luni/src/test/java/libcore/java/lang/OldSystemTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldSystemTest.java
@@ -258,8 +258,8 @@
     public void test_gc() {
         Runtime rt =  Runtime.getRuntime();
         Vector<StringBuffer> vec = new Vector<StringBuffer>();
-        long beforeTest = rt.freeMemory();
-        while(rt.freeMemory() < beforeTest * 2/3) {
+        long beforeTest = rt.totalMemory() - rt.freeMemory();
+        while (rt.totalMemory() - rt.freeMemory() < beforeTest * 2) {
              vec.add(new StringBuffer(1000));
         }
         long beforeGC = rt.totalMemory() - rt.freeMemory();
diff --git a/luni/src/test/java/libcore/java/lang/PackageTest.java b/luni/src/test/java/libcore/java/lang/PackageTest.java
index c004e23..269831f 100644
--- a/luni/src/test/java/libcore/java/lang/PackageTest.java
+++ b/luni/src/test/java/libcore/java/lang/PackageTest.java
@@ -37,6 +37,12 @@
         assertEquals(getClass().getPackage(), libcoreJavaLang);
     }
 
+    // http://b/28057303
+    public void test_toString() throws Exception {
+        Package libcoreJavaLang = Package.getPackage("libcore.java.lang");
+        assertEquals("package libcore.java.lang", libcoreJavaLang.toString());
+    }
+
     // http://b/5171136
     public void testGetPackages() {
         assertTrue(packages.contains(getClass().getPackage()));
diff --git a/luni/src/test/java/libcore/java/lang/StrictMathTest.java b/luni/src/test/java/libcore/java/lang/StrictMathTest.java
new file mode 100644
index 0000000..2509af8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/StrictMathTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang;
+
+import junit.framework.TestCase;
+
+import java.math.BigInteger;
+
+public class StrictMathTest extends TestCase {
+
+    public void testIntExact() {
+        testIntExact(123, 456);
+        testIntExact(-456, 456);
+        testIntExact(0, 0);
+        testIntExact(Integer.MAX_VALUE, 1);
+        testIntExact(Integer.MAX_VALUE, -1);
+        testIntExact(Integer.MIN_VALUE, 1);
+        testIntExact(Integer.MIN_VALUE, -1);
+        testIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
+        testIntExact(Integer.MIN_VALUE, Integer.MIN_VALUE);
+    }
+
+    private void testIntExact(int a, int b) {
+        testAddExactI(a, b);
+        testSubtractExactI(a, b);
+        testMultiplyExactI(a, b);
+    }
+
+    private void testAddExactI(int a, int b) {
+        long expected = (long) a + (long) b;
+        try {
+            assertEquals(expected, StrictMath.addExact(a, b));
+        } catch (ArithmeticException e) {
+            if (expected == a + b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testSubtractExactI(int a, int b) {
+        long expected = (long) a - (long) b;
+        try {
+            assertEquals(expected, StrictMath.subtractExact(a, b));
+        } catch (ArithmeticException e) {
+            long result = (long) a - (long) b;
+            if (expected == a - b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testMultiplyExactI(int a, int b) {
+        long expected = (long) a * (long) b;
+        try {
+            assertEquals(expected, StrictMath.multiplyExact(a, b));
+        } catch (ArithmeticException e) {
+            if (expected == a * b) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    public void testLongExact() {
+        testLongExact(123, 456);
+        testLongExact(-456, 456);
+        testLongExact(0, 0);
+        testLongExact(Long.MAX_VALUE, 1);
+        testLongExact(Long.MAX_VALUE, -1);
+        testLongExact(Long.MIN_VALUE, 1);
+        testLongExact(Long.MIN_VALUE, -1);
+        testLongExact(Long.MAX_VALUE, Long.MAX_VALUE);
+        testLongExact(Long.MIN_VALUE, Long.MIN_VALUE);
+    }
+
+    private void testLongExact(long a, long b) {
+        testAddExactL(a, b);
+        testSubtractExactL(a, b);
+        testMultiplyExactL(a, b);
+        testToIntExactL(a);
+    }
+
+    private void testAddExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).add(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(StrictMath.addExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a + b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testSubtractExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).subtract(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(StrictMath.subtractExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a - b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testMultiplyExactL(long a, long b) {
+        BigInteger expected = BigInteger.valueOf(a).multiply(BigInteger.valueOf(b));
+        try {
+            assertEquals(expected, BigInteger.valueOf(StrictMath.multiplyExact(a, b)));
+        } catch (ArithmeticException e) {
+            if (expected.equals(BigInteger.valueOf(a * b))) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    private void testToIntExactL(long a) {
+        try {
+            assertEquals((int) a, StrictMath.toIntExact(a));
+            assertEquals(a, StrictMath.toIntExact(a)); // Is not exact, should throw AE.
+        } catch (ArithmeticException e) {
+            if (a <= Integer.MAX_VALUE && a >= Integer.MIN_VALUE) {
+                fail(); // This is not an overflow
+            }
+        }
+    }
+
+    public void testIntFloorDivMod() {
+        testFloorDivModI(123, 456);
+        testFloorDivModI(456, 123);
+        testFloorDivModI(369, 123);
+        testFloorDivModI(1, 0);
+        testFloorDivModI(Integer.MAX_VALUE, 1);
+        testFloorDivModI(Integer.MAX_VALUE, -1);
+        testFloorDivModI(Integer.MIN_VALUE, 1);
+        testFloorDivModI(Integer.MIN_VALUE, -1);
+    }
+
+    private void testFloorDivModI(int a, int b) {
+        testFloorDivI(a, b);
+        testFloorModI(a, b);
+    }
+
+    private void testFloorDivI(int a, int b) {
+        try {
+            int floorDiv = StrictMath.floorDiv(a, b);
+            int expected = a / b;
+            if (expected < 0 && a % b != 0) {
+                --expected;
+            }
+            assertEquals(expected, floorDiv);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    private void testFloorModI(int a, int b) {
+        try {
+            int floorMod = StrictMath.floorMod(a, b);
+            int expected = a % b;
+            if ((a ^ b) < 0 && expected != 0) {
+                expected = b - expected;
+            }
+            assertEquals(expected, floorMod);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    public void testLongFloorDivMod() {
+        testFloorDivModL(123L, 456L);
+        testFloorDivModL(456L, 123L);
+        testFloorDivModL(369L, 123L);
+        testFloorDivModL(1L, 0L);
+        testFloorDivModL(Long.MAX_VALUE, 1L);
+        testFloorDivModL(Long.MAX_VALUE, -1L);
+        testFloorDivModL(Long.MIN_VALUE, 1L);
+        testFloorDivModL(Long.MIN_VALUE, -1L);
+    }
+
+    private void testFloorDivModL(long a, long b) {
+        testFloorDivL(a, b);
+        testFloorModL(a, b);
+    }
+
+    private void testFloorDivL(long a, long b) {
+        try {
+            long floorDiv = StrictMath.floorDiv(a, b);
+            long expected = a / b;
+            if (expected < 0 && a % b != 0) {
+                --expected;
+            }
+            assertEquals(expected, floorDiv);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+
+    private void testFloorModL(long a, long b) {
+        try {
+            long floorMod = StrictMath.floorMod(a, b);
+            long expected = a % b;
+            if ((a ^ b) < 0 && expected != 0) {
+                expected = b - expected;
+            }
+            assertEquals(expected, floorMod);
+        } catch (ArithmeticException e) {
+            if (b != 0) {
+                fail(); // Should only throw AE when b is zero.
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/StringBufferTest.java b/luni/src/test/java/libcore/java/lang/StringBufferTest.java
new file mode 100644
index 0000000..402bc36
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/StringBufferTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class StringBufferTest extends TestCase {
+
+    public void testChars() {
+        StringBuffer s = new StringBuffer("Hello\n\tworld");
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.chars().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        StringBuffer surrogateCP = new StringBuffer().append(new char[]{high, low, low});
+        assertTrue(Arrays.equals(new int[]{high, low, low}, surrogateCP.chars().toArray()));
+    }
+
+    public void testCodePoints() {
+        StringBuffer s = new StringBuffer("Hello\n\tworld");
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.codePoints().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        StringBuffer surrogateCP = new StringBuffer().append(new char[]{high, low, low, '0'});
+        assertEquals(Character.toCodePoint(high, low), surrogateCP.codePoints().toArray()[0]);
+        assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
+        assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/StringBuilderTest.java b/luni/src/test/java/libcore/java/lang/StringBuilderTest.java
index 1f9abbf..20d2974 100644
--- a/luni/src/test/java/libcore/java/lang/StringBuilderTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringBuilderTest.java
@@ -16,6 +16,8 @@
 
 package libcore.java.lang;
 
+import java.util.Arrays;
+
 public class StringBuilderTest extends junit.framework.TestCase {
     // See https://code.google.com/p/android/issues/detail?id=60639
     public void test_deleteChatAt_lastRange() {
@@ -129,4 +131,34 @@
         sb.delete(sb.length() - 1, sb.length());
         assertEquals("mogw", sb.toString());
     }
+
+    public void testChars() {
+        StringBuilder s = new StringBuilder("Hello\n\tworld");
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.chars().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        StringBuilder surrogateCP = new StringBuilder().append(new char[]{high, low, low});
+        assertTrue(Arrays.equals(new int[]{high, low, low}, surrogateCP.chars().toArray()));
+    }
+
+    public void testCodePoints() {
+        StringBuilder s = new StringBuilder("Hello\n\tworld");
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.codePoints().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        StringBuilder surrogateCP = new StringBuilder().append(new char[]{high, low, low, '0'});
+        assertEquals(Character.toCodePoint(high, low), surrogateCP.codePoints().toArray()[0]);
+        assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
+        assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 63f991e..60c3467 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -16,8 +16,6 @@
 
 package libcore.java.lang;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.ReadOnlyBufferException;
@@ -317,6 +315,24 @@
         assertEquals("-h-e-l-l-o- -w-o-r-l-d-", "hello world".replace("", "-"));
         assertEquals("-w-o-r-l-d-", "hello world".substring(6).replace("", "-"));
         assertEquals("-*-w-*-o-*-r-*-l-*-d-*-", "hello world".substring(6).replace("", "-*-"));
+
+        // Replace on an empty string with an empty target should insert the pattern
+        // precisely once.
+        assertEquals("", "".replace("", ""));
+        assertEquals("food", "".replace("", "food"));
+    }
+
+    public void test_replace() {
+        // Replace on an empty string is a no-op.
+        assertEquals("", "".replace("foo", "bar"));
+        // Replace on a string which doesn't contain the target sequence is a no-op.
+        assertEquals("baz", "baz".replace("foo", "bar"));
+        // Test that we iterate forward on the string.
+        assertEquals("mmmba", "bababa".replace("baba", "mmm"));
+        // Test replacements at the end of the string.
+        assertEquals("foodie", "foolish".replace("lish", "die"));
+        // Test a string that has multiple replacements.
+        assertEquals("hahahaha", "kkkk".replace("k", "ha"));
     }
 
     public void test_String_getBytes() throws Exception {
@@ -437,4 +453,34 @@
         } catch (StringIndexOutOfBoundsException expected) {
         }
     }
+
+    public void testChars() {
+        String s = "Hello\n\tworld";
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.chars().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        String surrogateCP = new String(new char[]{high, low, low});
+        assertTrue(Arrays.equals(new int[]{high, low, low}, surrogateCP.chars().toArray()));
+    }
+
+    public void testCodePoints() {
+        String s = "Hello\n\tworld";
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, s.codePoints().toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        String surrogateCP = new String(new char[]{high, low, low, '0'});
+        assertEquals(Character.toCodePoint(high, low), surrogateCP.codePoints().toArray()[0]);
+        assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
+        assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ThreadTest.java b/luni/src/test/java/libcore/java/lang/ThreadTest.java
index 8545a20..10ca9a7 100644
--- a/luni/src/test/java/libcore/java/lang/ThreadTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThreadTest.java
@@ -22,6 +22,9 @@
 import libcore.java.lang.ref.FinalizationTester;
 
 public final class ThreadTest extends TestCase {
+    static {
+        System.loadLibrary("javacoretests");
+    }
 
     /**
      * getContextClassLoader returned a non-application class loader.
@@ -167,6 +170,19 @@
         assertTrue("Must have traces for all threads", visibleTraces.get() > 1);
     }
 
+    // http://b/27748318
+    public void testNativeThreadNames() throws Exception {
+        String testResult = nativeTestNativeThreadNames();
+        // Not using assertNull here because this results in a better error message.
+        if (testResult != null) {
+            fail(testResult);
+        }
+    }
+
+    // This method returns {@code null} if all tests pass, or a non-null String containing
+    // failure details if an error occured.
+    private static native String nativeTestNativeThreadNames();
+
     private Thread newThread(final AtomicInteger finalizedThreadsCount, final int size) {
         return new Thread() {
             long[] memoryPressure = new long[size];
diff --git a/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java b/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java
index a37806f..c9cd3d1 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java
@@ -298,6 +298,12 @@
         assertDeclared(true, aPackage, RepeatableAnnotations.class);
     }
 
+    public void testRetentionPolicy() {
+        assertNull(RetentionAnnotations.class.getAnnotation(ClassRetentionAnnotation.class));
+        assertNotNull(RetentionAnnotations.class.getAnnotation(RuntimeRetentionAnnotation.class));
+        assertNull(RetentionAnnotations.class.getAnnotation(SourceRetentionAnnotation.class));
+    }
+
     private static final Object staticAnonymous = new Object() {};
 
     private static class Foo {
@@ -340,6 +346,15 @@
         RepeatableAnnotation[] value();
     }
 
+    @Retention(RetentionPolicy.CLASS)
+    public @interface ClassRetentionAnnotation {}
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface RuntimeRetentionAnnotation {}
+
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SourceRetentionAnnotation {}
+
     @AnnotationA @AnnotationB @RepeatableAnnotation
     public static class Type {
         @AnnotationA @AnnotationC public Type() {}
@@ -358,6 +373,9 @@
     @RepeatableAnnotations({ @RepeatableAnnotation, @RepeatableAnnotation})
     public static class TypeWithExplicitRepeatableAnnotations {}
 
+    @ClassRetentionAnnotation @RuntimeRetentionAnnotation @SourceRetentionAnnotation
+    public static class RetentionAnnotations {}
+
     static enum Breakfast { WAFFLES, PANCAKES }
 
     @Retention(RetentionPolicy.RUNTIME)
diff --git a/luni/src/test/java/libcore/java/math/BigDecimalTest.java b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
index cdfab6c..e2dae32 100644
--- a/luni/src/test/java/libcore/java/math/BigDecimalTest.java
+++ b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
@@ -17,8 +17,11 @@
 package libcore.java.math;
 
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.math.MathContext;
 import java.math.RoundingMode;
+import java.util.Locale;
+
 import junit.framework.TestCase;
 
 public final class BigDecimalTest extends TestCase {
@@ -67,26 +70,36 @@
 
     // https://code.google.com/p/android/issues/detail?id=43480
     public void testPrecisionFromString() {
-      BigDecimal a = new BigDecimal("-0.011111111111111111111");
-      BigDecimal b = a.multiply(BigDecimal.ONE);
+        BigDecimal a = new BigDecimal("-0.011111111111111111111");
+        BigDecimal b = a.multiply(BigDecimal.ONE);
 
-      assertEquals("-0.011111111111111111111", a.toString());
-      assertEquals("-0.011111111111111111111", b.toString());
+        assertEquals("-0.011111111111111111111", a.toString());
+        assertEquals("-0.011111111111111111111", b.toString());
 
-      assertEquals(20, a.precision());
-      assertEquals(20, b.precision());
+        assertEquals(20, a.precision());
+        assertEquals(20, b.precision());
 
-      assertEquals(21, a.scale());
-      assertEquals(21, b.scale());
+        assertEquals(21, a.scale());
+        assertEquals(21, b.scale());
 
-      assertEquals("-11111111111111111111", a.unscaledValue().toString());
-      assertEquals("-11111111111111111111", b.unscaledValue().toString());
+        assertEquals("-11111111111111111111", a.unscaledValue().toString());
+        assertEquals("-11111111111111111111", b.unscaledValue().toString());
 
-      assertEquals(a, b);
-      assertEquals(b, a);
+        assertEquals(a, b);
+        assertEquals(b, a);
 
-      assertEquals(0, a.subtract(b).signum());
-      assertEquals(0, a.compareTo(b));
+        assertEquals(0, a.subtract(b).signum());
+        assertEquals(0, a.compareTo(b));
+    }
+
+    public void testPrecisionFromString_simplePowersOfTen() {
+        assertEquals(new BigDecimal(BigInteger.valueOf(-10), 1), new BigDecimal("-1.0"));
+        assertEquals(new BigDecimal(BigInteger.valueOf(-1), 1), new BigDecimal("-0.1"));
+        assertEquals(new BigDecimal(BigInteger.valueOf(-1), -1), new BigDecimal("-1E+1"));
+
+        assertEquals(new BigDecimal(BigInteger.valueOf(10), 1), new BigDecimal("1.0"));
+        assertEquals(new BigDecimal(BigInteger.valueOf(1), 0), new BigDecimal("1"));
+        assertFalse(new BigDecimal("1.0").equals(new BigDecimal("1")));
     }
 
     // https://code.google.com/p/android/issues/detail?id=54580
@@ -108,4 +121,81 @@
         assertFalse(zero.equals(other));
         assertFalse(other.equals(zero));
     }
+
+    private static void checkDivide(String expected, long n, long d, int scale, RoundingMode rm) {
+        assertEquals(String.format(Locale.US, "%d/%d [%d, %s]", n, d, scale, rm.name()),
+                new BigDecimal(expected),
+                new BigDecimal(n).divide(new BigDecimal(d), scale, rm));
+    }
+
+    public void testDivideRounding() {
+        checkDivide("0", 1, Long.MIN_VALUE, 0, RoundingMode.DOWN);
+        checkDivide("-1", 1, Long.MIN_VALUE, 0, RoundingMode.UP);
+        checkDivide("-1", 1, Long.MIN_VALUE, 0, RoundingMode.FLOOR);
+        checkDivide("0", 1, Long.MIN_VALUE, 0, RoundingMode.CEILING);
+        checkDivide("0", 1, Long.MIN_VALUE, 0, RoundingMode.HALF_EVEN);
+        checkDivide("0", 1, Long.MIN_VALUE, 0, RoundingMode.HALF_UP);
+        checkDivide("0", 1, Long.MIN_VALUE, 0, RoundingMode.HALF_DOWN);
+
+        checkDivide("1", Long.MAX_VALUE, Long.MAX_VALUE / 2 + 1, 0, RoundingMode.DOWN);
+        checkDivide("2", Long.MAX_VALUE, Long.MAX_VALUE / 2, 0, RoundingMode.DOWN);
+        checkDivide("0.50", Long.MAX_VALUE / 2, Long.MAX_VALUE, 2, RoundingMode.HALF_UP);
+        checkDivide("0.50", Long.MIN_VALUE / 2, Long.MIN_VALUE, 2, RoundingMode.HALF_UP);
+        checkDivide("0.5000", Long.MIN_VALUE / 2, Long.MIN_VALUE, 4, RoundingMode.HALF_UP);
+        // (-2^62 + 1) / (-2^63) = (2^62 - 1) / 2^63 = 0.5 - 2^-63
+        checkDivide("0", Long.MIN_VALUE / 2 + 1, Long.MIN_VALUE, 0, RoundingMode.HALF_UP);
+        checkDivide("1", Long.MIN_VALUE / 2, Long.MIN_VALUE, 0, RoundingMode.HALF_UP);
+        checkDivide("0", Long.MIN_VALUE / 2, Long.MIN_VALUE, 0, RoundingMode.HALF_DOWN);
+        // (-2^62 - 1) / (-2^63) = (2^62 + 1) / 2^63 = 0.5 + 2^-63
+        checkDivide("1", Long.MIN_VALUE / 2 - 1, Long.MIN_VALUE, 0, RoundingMode.HALF_DOWN);
+    }
+
+    /**
+     * Tests that Long.MIN_VALUE / -1 doesn't overflow back to Long.MIN_VALUE,
+     * like it would in long arithmetic.
+     */
+    // https://code.google.com/p/android/issues/detail?id=196555
+    public void testDivideAvoids64bitOverflow() throws Exception {
+        BigDecimal minLong = new BigDecimal("-9223372036854775808");
+        assertEquals("9223372036854775808/(-1)",
+                new BigDecimal("9223372036854775808"),
+                minLong.divide(new BigDecimal("-1"), /* scale = */ 0, RoundingMode.UNNECESSARY));
+
+        assertEquals("922337203685477580.8/(-0.1)",
+                new BigDecimal("9223372036854775808"),
+                new BigDecimal("-922337203685477580.8")
+                        .divide(new BigDecimal("-0.1"), /* scale = */ 0, RoundingMode.UNNECESSARY));
+
+        assertEquals("92233720368547758080/(-1E+1)",
+                new BigDecimal("9223372036854775808"),
+                new BigDecimal("-92233720368547758080")
+                        .divide(new BigDecimal("-1E+1"), /* scale = */ 0, RoundingMode.UNNECESSARY));
+
+        assertEquals("9223372036854775808/(-10) with one decimal of precision",
+                new BigDecimal("922337203685477580.8"),
+                minLong.divide(new BigDecimal("-1E+1"), /* scale = */ 1, RoundingMode.UNNECESSARY));
+
+        // cases that request adjustment of the result scale, i.e. (diffScale != 0)
+        // i.e. result scale != (numerator.scale - divisor.scale)
+        assertEquals("9223372036854775808/(-1) with one decimal of precision",//
+                new BigDecimal("9223372036854775808.0"),
+                minLong.divide(new BigDecimal("-1"), /* scale = */ 1, RoundingMode.UNNECESSARY));
+
+        assertEquals("9223372036854775808/(-1.0)",//
+                new BigDecimal("9223372036854775808"),
+                minLong.divide(new BigDecimal("-1.0"), /* scale = */ 0, RoundingMode.UNNECESSARY));
+
+        assertEquals("9223372036854775808/(-1.0) with one decimal of precision",//
+                new BigDecimal("9223372036854775808.0"),
+                minLong.divide(new BigDecimal("-1.0"), /* scale = */ 1, RoundingMode.UNNECESSARY));
+
+        // another arbitrary calculation that results in Long.MAX_VALUE + 1
+        // via a different route
+        assertEquals("4611686018427387904/(-5E-1)",//
+                new BigDecimal("9223372036854775808"),
+                new BigDecimal("-4611686018427387904").divide(
+                        new BigDecimal("-5E-1"), /* scale = */ 0, RoundingMode.UNNECESSARY));
+
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/math/BigIntegerTest.java b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
index 58c68a1..80041c2 100644
--- a/luni/src/test/java/libcore/java/math/BigIntegerTest.java
+++ b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
@@ -184,4 +184,15 @@
 
         assertEquals(trimmed, extraZeroes);
     }
+
+    /**
+     * Tests that Long.MIN_VALUE / -1 doesn't overflow back to Long.MIN_VALUE,
+     * like it would in long arithmetic.
+     */
+    public void test_divide_avoids64bitOverflow() throws Exception {
+        BigInteger negV = BigInteger.valueOf(Long.MIN_VALUE);
+        BigInteger posV = negV.divide(BigInteger.valueOf(-1));
+        assertEquals("-9223372036854775808", negV.toString());
+        assertEquals( "9223372036854775808", posV.toString());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/net/OldServerSocketTest.java b/luni/src/test/java/libcore/java/net/OldServerSocketTest.java
index 6518897..8588144 100644
--- a/luni/src/test/java/libcore/java/net/OldServerSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/OldServerSocketTest.java
@@ -238,11 +238,11 @@
     public void test_getSoTimeout_setSoTimeout() throws Exception {
         // TODO: a useful test would check that setSoTimeout actually causes timeouts!
         ServerSocket s = new ServerSocket();
-        s.setSoTimeout(1500);
-        int ms = s.getSoTimeout();
-        if (ms < 1500-10 || ms > 1500+10) {
-            fail("suspicious timeout: " + ms);
-        }
+        final int timeoutSet = 1500;
+        s.setSoTimeout(timeoutSet);
+        int actualTimeout = s.getSoTimeout();
+        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+        assertTrue("suspicious timeout: " + actualTimeout, Math.abs(actualTimeout - timeoutSet) <= 10);
         s.close();
         try {
             s.getSoTimeout();
diff --git a/luni/src/test/java/libcore/java/net/OldSocketTest.java b/luni/src/test/java/libcore/java/net/OldSocketTest.java
index ded5802..4254516 100644
--- a/luni/src/test/java/libcore/java/net/OldSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/OldSocketTest.java
@@ -389,9 +389,7 @@
         Socket s = new Socket();
         s.setSoTimeout(1500);
         int ms = s.getSoTimeout();
-        if (ms < 1500-10 || ms > 1500+10) {
-            fail("suspicious timeout: " + ms);
-        }
+        assertTrue("suspicious timeout: " + ms, Math.abs(ms - 1500) <= 10);
         s.close();
         try {
             s.getSoTimeout();
@@ -1384,10 +1382,10 @@
         connector.start();
         theSocket.setSoTimeout(1000);
         Thread.sleep(10);
-        assertEquals("Socket option not set during connect: 10 ", 1000, theSocket.getSoTimeout());
+        assertTrue("Socket option not set during connect: 10 ", Math.abs(1000 - theSocket.getSoTimeout()) <= 10);
         Thread.sleep(50);
         theSocket.setSoTimeout(2000);
-        assertEquals("Socket option not set during connect: 50 ", 2000, theSocket.getSoTimeout());
+        assertTrue("Socket option not set during connect: 50 ", Math.abs(2000 - theSocket.getSoTimeout()) <= 10);
         Thread.sleep(5000);
         theSocket.close();
 
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 383461e..468787f 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -1929,8 +1929,8 @@
 
             assertEquals(Arrays.asList("verify " + hostName), hostnameVerifier.calls);
             assertEquals(Arrays.asList("checkServerTrusted ["
-                    + "CN=" + hostName + " 1, "
-                    + "CN=Test Intermediate Certificate Authority 1, "
+                    + "CN=" + hostName + " 3, "
+                    + "CN=Test Intermediate Certificate Authority 2, "
                     + "CN=Test Root Certificate Authority 1"
                     + "] ECDHE_RSA"),
                     trustManager.calls);
diff --git a/luni/src/test/java/libcore/java/nio/CharBufferTest.java b/luni/src/test/java/libcore/java/nio/CharBufferTest.java
new file mode 100644
index 0000000..26e5778
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/CharBufferTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package libcore.java.nio;
+
+import junit.framework.TestCase;
+
+import java.nio.CharBuffer;
+import java.util.Arrays;
+
+public class CharBufferTest extends TestCase {
+
+    public void testChars() {
+        char highSurrogate = '\uD83D', lowSurrogate = '\uDE02';
+        String s = "Hello\n\tworld" + highSurrogate + lowSurrogate;
+        CharBuffer cb = CharBuffer.allocate(32).append(s);
+        cb.rewind();
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);
+        }
+        assertTrue(Arrays.equals(expected, cb.chars().limit(s.length()).toArray()));
+    }
+
+    public void testCodePoints() {
+        String s = "Hello\n\tworld";
+        CharBuffer cb = CharBuffer.allocate(32).append(s);
+        cb.rewind();
+        int[] expected = new int[s.length()];
+        for (int i = 0; i < s.length(); ++i) {
+            expected[i] = (int) s.charAt(i);}
+        assertTrue(Arrays.equals(expected, cb.codePoints().limit(s.length()).toArray()));
+
+        // Surrogate code point
+        char high = '\uD83D', low = '\uDE02';
+        String surrogateCP = new String(new char[]{high, low, low, '0'});
+        cb = CharBuffer.allocate(32).append(surrogateCP);
+        cb.rewind();
+        assertEquals(Character.toCodePoint(high, low), cb.codePoints().toArray()[0]);
+        assertEquals((int) low, cb.codePoints().toArray()[1]); // Unmatched surrogate.
+        assertEquals((int) '0', cb.codePoints().toArray()[2]);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
index 609a990..f3bd7ff 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
@@ -17,20 +17,23 @@
 package libcore.java.nio.channels;
 
 import java.io.IOException;
+import java.net.BindException;
 import java.net.DatagramSocket;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
+import java.net.ProtocolFamily;
+import java.net.StandardProtocolFamily;
 import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.DatagramChannel;
-import java.nio.channels.SocketChannel;
-import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
 import java.util.Enumeration;
-import java.util.Set;
 
 public class DatagramChannelTest extends junit.framework.TestCase {
     public void test_read_intoReadOnlyByteArrays() throws Exception {
@@ -181,6 +184,75 @@
         assertNotNull(socket.getFileDescriptor$());
     }
 
+    public void test_bind() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        DatagramChannel channel = DatagramChannel.open();
+        channel.bind(socketAddress);
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress)(channel.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress)(channel.getLocalAddress())).getPort() > 0);
+
+        try {
+            channel.bind(socketAddress);
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK,
+                ((InetSocketAddress)(channel.getLocalAddress())).getPort());
+        try {
+            DatagramChannel.open().bind(socketAddress);
+            fail();
+        } catch (BindException expected) {}
+
+        channel.close();
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        try {
+            channel.bind(socketAddress);
+        } catch (ClosedChannelException expected) {}
+    }
+
+    public void test_getRemoteAddress() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        DatagramChannel clientChannel = DatagramChannel.open();
+        DatagramChannel serverChannel = DatagramChannel.open();
+        serverChannel.bind(socketAddress);
+
+        assertNull(clientChannel.getRemoteAddress());
+
+        clientChannel.connect(serverChannel.getLocalAddress());
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress)(clientChannel.getRemoteAddress())).getAddress());
+        assertEquals(((InetSocketAddress)(serverChannel.getLocalAddress())).getPort(),
+                ((InetSocketAddress)(clientChannel.getRemoteAddress())).getPort());
+    }
+
+    public void test_open$java_net_ProtocolFamily() throws IOException {
+        DatagramChannel channel = DatagramChannel.open(StandardProtocolFamily.INET);
+
+        channel.bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0));
+        assertEquals(SelectorProvider.provider(), channel.provider());
+
+        try {
+            // Should not support IPv6 Address
+            // InetSocketAddress(int) returns IPv6 ANY  address
+            DatagramChannel.open(StandardProtocolFamily.INET).bind(new InetSocketAddress(0));
+            fail();
+        } catch (UnsupportedAddressTypeException expected) {}
+
+        DatagramChannel.open(StandardProtocolFamily.INET6).bind(new InetSocketAddress(0));
+
+        try {
+            DatagramChannel.open(MockProtocolFamily.MOCK);
+            fail();
+        } catch (UnsupportedOperationException expected) {}
+
+        try {
+            DatagramChannel.open(null);
+            fail();
+        } catch (NullPointerException expected) {}
+    }
+
     private static InetAddress getNonLoopbackNetworkInterfaceAddress(boolean ipv4) throws IOException {
         Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
         while (networkInterfaces.hasMoreElements()) {
@@ -199,4 +271,8 @@
         }
         return null;
     }
+
+    enum MockProtocolFamily implements ProtocolFamily {
+        MOCK,
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
index 1178b70..113779d 100644
--- a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
@@ -22,10 +22,13 @@
 import java.net.NetworkInterface;
 import java.net.ServerSocket;
 import java.net.SocketException;
+import java.net.StandardSocketOptions;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
 import java.util.Enumeration;
 import java.util.Set;
 
@@ -136,6 +139,58 @@
         ssc.close();
     }
 
+    public void test_bind$SocketAddress() throws IOException {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+        assertEquals(InetAddress.getLoopbackAddress(),
+                ((InetSocketAddress)(ssc.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress)(ssc.getLocalAddress())).getPort() > 0);
+
+        try {
+            ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(),
+                    ((InetSocketAddress)(ssc.getLocalAddress())).getPort()));
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        try {
+            ServerSocketChannel ssc1 = ServerSocketChannel.open();
+            ssc1.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
+            fail();
+        } catch (UnresolvedAddressException expected) {
+        }
+
+        ssc.close();
+        try {
+            ssc.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_setOption() throws Exception {
+        ServerSocketChannel sc = ServerSocketChannel.open();
+        sc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
+
+        // Assert that we can read back the option from the channel...
+        assertTrue(sc.getOption(StandardSocketOptions.SO_REUSEADDR));
+
+        sc.setOption(StandardSocketOptions.SO_REUSEADDR, false);
+
+        // Assert that we can read back the option from the channel...
+        assertEquals(false, (boolean)sc.getOption(StandardSocketOptions.SO_REUSEADDR));
+
+        sc.setOption(StandardSocketOptions.SO_RCVBUF, 1100);
+        assertTrue(1100 <= sc.getOption(StandardSocketOptions.SO_RCVBUF));
+
+        sc.close();
+        try {
+            sc.setOption(StandardSocketOptions.SO_RCVBUF, 2000);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
     private static boolean canConnect(InetSocketAddress address) {
         try {
             SocketChannel socketChannel = SocketChannel.open(address);
diff --git a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
index d31b222..72609ee 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
@@ -20,278 +20,378 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
+import java.net.BindException;
 import java.net.ConnectException;
-import java.net.Socket;
-import java.net.SocketImpl;
+import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketImpl;
 import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
-import java.nio.channels.SocketChannel;
-import java.nio.channels.Selector;
+import java.nio.channels.NotYetConnectedException;
 import java.nio.channels.SelectionKey;
-import java.nio.channels.UnresolvedAddressException;
-import java.util.Set;
-
-import static android.system.OsConstants.*;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 
 public class SocketChannelTest extends junit.framework.TestCase {
 
-  public void test_read_intoReadOnlyByteArrays() throws Exception {
-    ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
-    ServerSocket ss = new ServerSocket(0);
-    ss.setReuseAddress(true);
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    try {
-      sc.read(readOnly);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-    try {
-      sc.read(new ByteBuffer[] { readOnly });
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-    try {
-      sc.read(new ByteBuffer[] { readOnly }, 0, 1);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-  }
-
-  // https://code.google.com/p/android/issues/detail?id=56684
-  public void test_56684() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    sc.configureBlocking(false);
-
-    Selector selector = Selector.open();
-    SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
-
-    try {
-      // This test originally mocked the connect syscall to return ENETUNREACH.
-      // This is not easily doable in openJdk libcore, but a connect to broadcast
-      // address (255.255.255.255) for a TCP connection produces ENETUNREACH
-      // Kernel code that does it is at
-      // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182
-      sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] {
-                    (byte) 255, (byte) 255, (byte)255, (byte)255 }), 0));
-      fail();
-    } catch (ConnectException ex) {
+    public void test_read_intoReadOnlyByteArrays() throws Exception {
+        ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
+        ServerSocket ss = new ServerSocket(0);
+        ss.setReuseAddress(true);
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        try {
+            sc.read(readOnly);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            sc.read(new ByteBuffer[] { readOnly });
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            sc.read(new ByteBuffer[] { readOnly }, 0, 1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
-    try {
-      sc.finishConnect();
-      fail();
-    } catch (ClosedChannelException expected) {
-    }
-  }
+    // https://code.google.com/p/android/issues/detail?id=56684
+    public void test_56684() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
 
-  /** Checks that closing a Socket's output stream also closes the Socket and SocketChannel. */
-  public void test_channelSocketOutputStreamClosureState() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
+        Selector selector = Selector.open();
+        SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
 
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    sc.configureBlocking(true);
+        try {
+            // This test originally mocked the connect syscall to return ENETUNREACH.
+            // This is not easily doable in openJdk libcore, but a connect to broadcast
+            // address (255.255.255.255) for a TCP connection produces ENETUNREACH
+            // Kernel code that does it is at
+            // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182
+            sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] {
+                    (byte) 255, (byte) 255, (byte) 255, (byte) 255 }), 0));
+            fail();
+        } catch (ConnectException ex) {
+        }
 
-    Socket scSocket = sc.socket();
-    OutputStream os = scSocket.getOutputStream();
-
-    assertTrue(sc.isOpen());
-    assertFalse(scSocket.isClosed());
-
-    os.close();
-
-    assertFalse(sc.isOpen());
-    assertTrue(scSocket.isClosed());
-
-    ss.close();
-  }
-
-  /** Checks that closing a Socket's input stream also closes the Socket and SocketChannel. */
-  public void test_channelSocketInputStreamClosureState() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
-
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    sc.configureBlocking(true);
-
-    Socket scSocket = sc.socket();
-    InputStream is = scSocket.getInputStream();
-
-    assertTrue(sc.isOpen());
-    assertFalse(scSocket.isClosed());
-
-    is.close();
-
-    assertFalse(sc.isOpen());
-    assertTrue(scSocket.isClosed());
-
-    ss.close();
-  }
-
-  /** Checks the state of the SocketChannel and associated Socket after open() */
-  public void test_open_initialState() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    try {
-      assertNull(sc.socket().getLocalSocketAddress());
-
-      Socket socket = sc.socket();
-      assertFalse(socket.isBound());
-      assertFalse(socket.isClosed());
-      assertFalse(socket.isConnected());
-      assertEquals(-1, socket.getLocalPort());
-      assertTrue(socket.getLocalAddress().isAnyLocalAddress());
-      assertNull(socket.getLocalSocketAddress());
-      assertNull(socket.getInetAddress());
-      assertEquals(0, socket.getPort());
-      assertNull(socket.getRemoteSocketAddress());
-      assertFalse(socket.getReuseAddress());
-
-      assertSame(sc, socket.getChannel());
-    } finally {
-      sc.close();
-    }
-  }
-
-  public void test_bind_unresolvedAddress() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    try {
-      sc.socket().bind(new InetSocketAddress("unresolvedname", 31415));
-      fail();
-    } catch (IOException expected) {
+        try {
+            sc.finishConnect();
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
     }
 
-    assertNull(sc.socket().getLocalSocketAddress());
-    assertTrue(sc.isOpen());
-    assertFalse(sc.isConnected());
+    /** Checks that closing a Socket's output stream also closes the Socket and SocketChannel. */
+    public void test_channelSocketOutputStreamClosureState() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-    sc.close();
-  }
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        sc.configureBlocking(true);
 
-  /** Checks that the SocketChannel and associated Socket agree on the socket state. */
-  public void test_bind_socketStateSync() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    assertNull(sc.socket().getLocalSocketAddress());
+        Socket scSocket = sc.socket();
+        OutputStream os = scSocket.getOutputStream();
 
-    Socket socket = sc.socket();
-    assertNull(socket.getLocalSocketAddress());
-    assertFalse(socket.isBound());
+        assertTrue(sc.isOpen());
+        assertFalse(scSocket.isClosed());
 
-    InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
-    sc.socket().bind(bindAddr);
+        os.close();
 
-    InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
-    assertEquals(actualAddr, socket.getLocalSocketAddress());
-    assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
-    assertTrue(socket.isBound());
-    assertFalse(socket.isConnected());
-    assertFalse(socket.isClosed());
+        assertFalse(sc.isOpen());
+        assertTrue(scSocket.isClosed());
 
-    sc.close();
+        ss.close();
+    }
 
-    assertFalse(sc.isOpen());
-    assertTrue(socket.isClosed());
-  }
+    /** Checks that closing a Socket's input stream also closes the Socket and SocketChannel. */
+    public void test_channelSocketInputStreamClosureState() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-  /**
-   * Checks that the SocketChannel and associated Socket agree on the socket state, even if
-   * the Socket object is requested/created after bind().
-   */
-  public void test_bind_socketObjectCreationAfterBind() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    assertNull(sc.socket().getLocalSocketAddress());
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        sc.configureBlocking(true);
 
-    InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
-    sc.socket().bind(bindAddr);
+        Socket scSocket = sc.socket();
+        InputStream is = scSocket.getInputStream();
 
-    // Socket object creation after bind().
-    Socket socket = sc.socket();
-    InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
-    assertEquals(actualAddr, socket.getLocalSocketAddress());
-    assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
-    assertTrue(socket.isBound());
-    assertFalse(socket.isConnected());
-    assertFalse(socket.isClosed());
+        assertTrue(sc.isOpen());
+        assertFalse(scSocket.isClosed());
 
-    sc.close();
+        is.close();
 
-    assertFalse(sc.isOpen());
-    assertTrue(socket.isClosed());
-  }
+        assertFalse(sc.isOpen());
+        assertTrue(scSocket.isClosed());
 
-  /**
-   * Tests connect() and object state for a blocking SocketChannel. Blocking mode is the default.
-   */
-  public void test_connect_blocking() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
+        ss.close();
+    }
 
-    SocketChannel sc = SocketChannel.open();
-    assertTrue(sc.isBlocking());
+    /** Checks the state of the SocketChannel and associated Socket after open() */
+    public void test_open_initialState() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        try {
+            assertNull(sc.socket().getLocalSocketAddress());
 
-    assertTrue(sc.connect(ss.getLocalSocketAddress()));
+            Socket socket = sc.socket();
+            assertFalse(socket.isBound());
+            assertFalse(socket.isClosed());
+            assertFalse(socket.isConnected());
+            assertEquals(-1, socket.getLocalPort());
+            assertTrue(socket.getLocalAddress().isAnyLocalAddress());
+            assertNull(socket.getLocalSocketAddress());
+            assertNull(socket.getInetAddress());
+            assertEquals(0, socket.getPort());
+            assertNull(socket.getRemoteSocketAddress());
+            assertFalse(socket.getReuseAddress());
 
-    assertTrue(sc.socket().isBound());
-    assertTrue(sc.isConnected());
-    assertTrue(sc.socket().isConnected());
-    assertFalse(sc.socket().isClosed());
-    assertTrue(sc.isBlocking());
+            assertSame(sc, socket.getChannel());
+        } finally {
+            sc.close();
+        }
+    }
 
-    ss.close();
-    sc.close();
-  }
+    public void test_bind_unresolvedAddress() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        try {
+            sc.socket().bind(new InetSocketAddress("unresolvedname", 31415));
+            fail();
+        } catch (IOException expected) {
+        }
 
-  /** Tests connect() and object state for a non-blocking SocketChannel. */
-  public void test_connect_nonBlocking() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
-
-    SocketChannel sc = SocketChannel.open();
-    assertTrue(sc.isBlocking());
-    sc.configureBlocking(false);
-    assertFalse(sc.isBlocking());
-
-    if (!sc.connect(ss.getLocalSocketAddress())) {
-      do {
-        assertTrue(sc.socket().isBound());
+        assertNull(sc.socket().getLocalSocketAddress());
+        assertTrue(sc.isOpen());
         assertFalse(sc.isConnected());
-        assertFalse(sc.socket().isConnected());
+
+        sc.close();
+    }
+
+    /** Checks that the SocketChannel and associated Socket agree on the socket state. */
+    public void test_bind_socketStateSync() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        assertNull(sc.socket().getLocalSocketAddress());
+
+        Socket socket = sc.socket();
+        assertNull(socket.getLocalSocketAddress());
+        assertFalse(socket.isBound());
+
+        InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
+        sc.socket().bind(bindAddr);
+
+        InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
+        assertEquals(actualAddr, socket.getLocalSocketAddress());
+        assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
+        assertTrue(socket.isBound());
+        assertFalse(socket.isConnected());
+        assertFalse(socket.isClosed());
+
+        sc.close();
+
+        assertFalse(sc.isOpen());
+        assertTrue(socket.isClosed());
+    }
+
+    /**
+     * Checks that the SocketChannel and associated Socket agree on the socket state, even if
+     * the Socket object is requested/created after bind().
+     */
+    public void test_bind_socketObjectCreationAfterBind() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        assertNull(sc.socket().getLocalSocketAddress());
+
+        InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
+        sc.socket().bind(bindAddr);
+
+        // Socket object creation after bind().
+        Socket socket = sc.socket();
+        InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
+        assertEquals(actualAddr, socket.getLocalSocketAddress());
+        assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
+        assertTrue(socket.isBound());
+        assertFalse(socket.isConnected());
+        assertFalse(socket.isClosed());
+
+        sc.close();
+
+        assertFalse(sc.isOpen());
+        assertTrue(socket.isClosed());
+    }
+
+    /**
+     * Tests connect() and object state for a blocking SocketChannel. Blocking mode is the default.
+     */
+    public void test_connect_blocking() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
+
+        SocketChannel sc = SocketChannel.open();
+        assertTrue(sc.isBlocking());
+
+        assertTrue(sc.connect(ss.getLocalSocketAddress()));
+
+        assertTrue(sc.socket().isBound());
+        assertTrue(sc.isConnected());
+        assertTrue(sc.socket().isConnected());
         assertFalse(sc.socket().isClosed());
-      } while (!sc.finishConnect());
+        assertTrue(sc.isBlocking());
+
+        ss.close();
+        sc.close();
     }
-    assertTrue(sc.socket().isBound());
-    assertTrue(sc.isConnected());
-    assertTrue(sc.socket().isConnected());
-    assertFalse(sc.socket().isClosed());
-    assertFalse(sc.isBlocking());
 
-    ss.close();
-    sc.close();
-  }
+    /** Tests connect() and object state for a non-blocking SocketChannel. */
+    public void test_connect_nonBlocking() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-  public void test_Socket_impl_notNull() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    Socket socket = sc.socket();
-    Field f_impl = Socket.class.getDeclaredField("impl");
-    f_impl.setAccessible(true);
-    Object implFieldValue = f_impl.get(socket);
-    assertNotNull(implFieldValue);
-    assertTrue(implFieldValue instanceof SocketImpl);
-  }
+        SocketChannel sc = SocketChannel.open();
+        assertTrue(sc.isBlocking());
+        sc.configureBlocking(false);
+        assertFalse(sc.isBlocking());
 
-  public void test_setOption() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    sc.setOption(StandardSocketOptions.SO_LINGER, 1000);
+        if (!sc.connect(ss.getLocalSocketAddress())) {
+            do {
+                assertTrue(sc.socket().isBound());
+                assertFalse(sc.isConnected());
+                assertFalse(sc.socket().isConnected());
+                assertFalse(sc.socket().isClosed());
+            } while (!sc.finishConnect());
+        }
+        assertTrue(sc.socket().isBound());
+        assertTrue(sc.isConnected());
+        assertTrue(sc.socket().isConnected());
+        assertFalse(sc.socket().isClosed());
+        assertFalse(sc.isBlocking());
 
-    // Assert that we can read back the option from the channel...
-    assertEquals(1000, (int) sc.<Integer>getOption(StandardSocketOptions.SO_LINGER));
-    // ... and its socket adaptor.
-    assertEquals(1000, sc.socket().getSoLinger());
-
-    sc.close();
-    try {
-        sc.setOption(StandardSocketOptions.SO_LINGER, 2000);
-        fail();
-    } catch (ClosedChannelException expected) {
+        ss.close();
+        sc.close();
     }
-  }
+
+    public void test_Socket_impl_notNull() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        Socket socket = sc.socket();
+        Field f_impl = Socket.class.getDeclaredField("impl");
+        f_impl.setAccessible(true);
+        Object implFieldValue = f_impl.get(socket);
+        assertNotNull(implFieldValue);
+        assertTrue(implFieldValue instanceof SocketImpl);
+    }
+
+    public void test_setOption() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.setOption(StandardSocketOptions.SO_LINGER, 1000);
+
+        // Assert that we can read back the option from the channel...
+        assertEquals(1000, (int) sc.<Integer>getOption(StandardSocketOptions.SO_LINGER));
+        // ... and its socket adaptor.
+        assertEquals(1000, sc.socket().getSoLinger());
+
+        sc.close();
+        try {
+            sc.setOption(StandardSocketOptions.SO_LINGER, 2000);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_bind() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        SocketChannel sc = SocketChannel.open();
+        sc.bind(socketAddress);
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress) (sc.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress) (sc.getLocalAddress())).getPort() > 0);
+
+        try {
+            sc.bind(socketAddress);
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK,
+                ((InetSocketAddress) (sc.getLocalAddress())).getPort());
+        try {
+            SocketChannel.open().bind(socketAddress);
+            fail();
+        } catch (BindException expected) {
+        }
+
+        sc.close();
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        try {
+            sc.bind(socketAddress);
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_getRemoteAddress() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        ServerSocket ss = new ServerSocket(0);
+
+        assertNull(sc.getRemoteAddress());
+
+        sc.connect(ss.getLocalSocketAddress());
+        assertEquals(sc.getRemoteAddress(), ss.getLocalSocketAddress());
+    }
+
+    public void test_shutdownInput() throws IOException {
+        SocketChannel channel1 = SocketChannel.open();
+        ServerSocket server1 = new ServerSocket(0);
+        InetSocketAddress localAddr1 = new InetSocketAddress("127.0.0.1", server1.getLocalPort());
+
+        // initialize write content
+        byte[] writeContent = new byte[10];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+        // use OutputStream.write to write bytes data.
+        OutputStream out = acceptedSocket.getOutputStream();
+        out.write(writeContent);
+        // use close to guarantee all data is sent
+        acceptedSocket.close();
+
+        channel1.configureBlocking(false);
+        ByteBuffer readContent = ByteBuffer.allocate(10 + 1);
+        channel1.shutdownInput();
+        assertEquals(-1, channel1.read(readContent));
+    }
+
+    public void test_shutdownOutput() throws IOException {
+        SocketChannel channel1 = SocketChannel.open();
+        ServerSocket server1 = new ServerSocket(0);
+        InetSocketAddress localAddr1 = new InetSocketAddress("127.0.0.1", server1.getLocalPort());
+
+        // initialize write content
+        ByteBuffer writeContent = ByteBuffer.allocate(10);
+        for (int i = 0; i < 10; i++) {
+            writeContent.put((byte) i);
+        }
+        writeContent.flip();
+
+        try {
+            channel1.shutdownOutput();
+            fail();
+        } catch (NotYetConnectedException expected) {}
+
+        // establish connection
+        channel1.connect(localAddr1);
+        channel1.shutdownOutput();
+
+        try {
+            channel1.write(writeContent);
+            fail();
+        } catch (ClosedChannelException expected) {}
+
+        channel1.close();
+
+        try {
+            channel1.shutdownOutput();
+            fail();
+        } catch(ClosedChannelException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java
new file mode 100644
index 0000000..0c0ad0c
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security.cert;
+
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.PrivateKey;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.PKIXParameters;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.security.cert.PKIXRevocationChecker.Option;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import com.android.org.bouncycastle.asn1.x509.CRLReason;
+import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import com.android.org.bouncycastle.cert.X509CertificateHolder;
+import com.android.org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+import com.android.org.bouncycastle.cert.ocsp.BasicOCSPResp;
+import com.android.org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
+import com.android.org.bouncycastle.cert.ocsp.CertificateID;
+import com.android.org.bouncycastle.cert.ocsp.CertificateStatus;
+import com.android.org.bouncycastle.cert.ocsp.OCSPResp;
+import com.android.org.bouncycastle.cert.ocsp.OCSPRespBuilder;
+import com.android.org.bouncycastle.cert.ocsp.RevokedStatus;
+import com.android.org.bouncycastle.operator.DigestCalculatorProvider;
+import com.android.org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
+import com.android.org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import junit.framework.TestCase;
+import libcore.java.security.TestKeyStore;
+
+public class CertPathValidatorTest extends TestCase {
+    private OCSPResp generateOCSPResponse(X509Certificate serverCertJca, X509Certificate caCertJca,
+            PrivateKey caKey, CertificateStatus status) throws Exception {
+        X509CertificateHolder caCert = new JcaX509CertificateHolder(caCertJca);
+
+        DigestCalculatorProvider digCalcProv = new BcDigestCalculatorProvider();
+        BasicOCSPRespBuilder basicBuilder = new BasicOCSPRespBuilder(
+                SubjectPublicKeyInfo.getInstance(caCertJca.getPublicKey().getEncoded()),
+                digCalcProv.get(CertificateID.HASH_SHA1));
+
+        CertificateID certId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1),
+                caCert, serverCertJca.getSerialNumber());
+
+        basicBuilder.addResponse(certId, status);
+
+        BasicOCSPResp resp = basicBuilder.build(
+                new JcaContentSignerBuilder("SHA1withRSA").build(caKey), null, new Date());
+
+        OCSPRespBuilder builder = new OCSPRespBuilder();
+        return builder.build(OCSPRespBuilder.SUCCESSFUL, resp);
+    }
+
+    private void runOCSPStapledTest(CertificateStatus certStatus, final boolean goodStatus)
+            throws Exception {
+        PrivateKeyEntry serverEntry = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
+        PrivateKeyEntry caEntry = TestKeyStore.getIntermediateCa().getPrivateKey("RSA", "RSA");
+        PrivateKeyEntry rootCaEntry = TestKeyStore.getRootCa().getPrivateKey("RSA", "RSA");
+
+        X509Certificate serverCert = (X509Certificate) serverEntry.getCertificate();
+        OCSPResp ocspResponse = generateOCSPResponse(serverCert,
+                (X509Certificate) caEntry.getCertificate(), caEntry.getPrivateKey(), certStatus);
+
+        PKIXParameters params = new PKIXParameters(Collections
+                .singleton(new TrustAnchor((X509Certificate) rootCaEntry.getCertificate(), null)));
+
+        // By default we shouldn't have a PKIXRevocationChecker already.
+        for (PKIXCertPathChecker checker : params.getCertPathCheckers()) {
+            assertFalse(checker instanceof PKIXRevocationChecker);
+        }
+
+        CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+
+        PKIXRevocationChecker revChecker = (PKIXRevocationChecker) cpv.getRevocationChecker();
+        revChecker.setOptions(Collections.singleton(Option.ONLY_END_ENTITY));
+        revChecker.setOcspResponses(
+                Collections.singletonMap(serverCert, ocspResponse.getEncoded()));
+
+        List<PKIXCertPathChecker> checkers = new ArrayList<>(params.getCertPathCheckers());
+        checkers.add(revChecker);
+        params.setCertPathCheckers(checkers);
+
+        ArrayList<X509Certificate> chain = new ArrayList<>();
+        chain.add(serverCert);
+        chain.add((X509Certificate) caEntry.getCertificate());
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        CertPath certPath = cf.generateCertPath(chain);
+
+        try {
+            cpv.validate(certPath, params);
+            assertTrue("should fail with failure OCSP status", goodStatus);
+        } catch (CertPathValidatorException maybeExpected) {
+            assertFalse("should not fail with good OCSP status", goodStatus);
+        }
+    }
+
+    public void test_OCSP_EndEntity_KeyCompromise_Failure() throws Exception {
+        runOCSPStapledTest(new RevokedStatus(new Date(), CRLReason.keyCompromise), false);
+    }
+
+    public void test_OCSP_EndEntity_Good_Success() throws Exception {
+        runOCSPStapledTest(CertificateStatus.GOOD, true);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index 0eae20a..2b8b566 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -283,6 +283,13 @@
         assertEquals(expected, numberFormat.format(2.01));
     }
 
+    // http://b/27855939
+    public void testBug27855939() {
+        DecimalFormat df = new DecimalFormat("00");
+        assertEquals("01", df.format(BigDecimal.ONE));
+        assertEquals("00", df.format(BigDecimal.ZERO));
+    }
+
     // Confirm the currency symbol used by a format is determined by the locale of the format
     // not the current default Locale.
     public void testSetCurrency_symbolOrigin() {
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index 2150b50..24c8817 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -31,6 +31,22 @@
     private static final TimeZone AMERICA_LOS_ANGELES = TimeZone.getTimeZone("America/Los_Angeles");
     private static final TimeZone AUSTRALIA_LORD_HOWE = TimeZone.getTimeZone("Australia/Lord_Howe");
 
+    private Locale defaultLocale;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        defaultLocale = Locale.getDefault();
+        // Locale affects timezone names / abbreviations so can affect formatting and parsing.
+        Locale.setDefault(Locale.US);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        Locale.setDefault(defaultLocale);
+        super.tearDown();
+    }
+
     // The RI fails this test.
     public void test2DigitYearStartIsCloned() throws Exception {
         // Test that get2DigitYearStart returns a clone.
diff --git a/luni/src/test/java/libcore/java/util/ArraysTest.java b/luni/src/test/java/libcore/java/util/ArraysTest.java
index e79cb0d..2c9d5c5 100644
--- a/luni/src/test/java/libcore/java/util/ArraysTest.java
+++ b/luni/src/test/java/libcore/java/util/ArraysTest.java
@@ -17,6 +17,7 @@
 package libcore.java.util;
 
 import java.util.Arrays;
+import java.util.Random;
 
 public class ArraysTest extends junit.framework.TestCase {
 
@@ -235,4 +236,302 @@
         } catch (NullPointerException expected) {
         }
     }
+
+    /**
+     * java.util.Array#parallelPrefix(int[], java.util.function.IntBinaryOperator)
+     */
+    public void test_parallelPrefix$I() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        int[] list = new int[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextInt() % 1000; // Prevent overflow
+        }
+
+        int[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = 0; i < seqResult.length - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, (x, y) -> x + y);
+        assertTrue(Arrays.equals(seqResult, list));
+
+        try {
+            Arrays.parallelPrefix(list, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((int[]) null, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator)
+     */
+    public void test_parallelPrefix$III() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        int[] list = new int[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextInt() % 1000; // Prevent overflow
+        }
+
+        int begin = 100, end = 500;
+        int[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = begin; i < end - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y);
+        assertTrue(Arrays.equals(seqResult, list));
+
+        try {
+            Arrays.parallelPrefix(list, begin, end, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((int[]) null, begin, end, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix(list, end, begin, (x, y) -> x + y);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(long[], java.util.function.LongBinaryOperator)
+     */
+    public void test_parallelPrefix$L() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        long[] list = new long[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextLong() % 1000000; // Prevent overflow
+        }
+
+        long[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = 0; i < seqResult.length - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, (x, y) -> x + y);
+        assertTrue(Arrays.equals(seqResult, list));
+
+        try {
+            Arrays.parallelPrefix(list, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((long[]) null, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator)
+     */
+    public void test_parallelPrefix$LII() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        long[] list = new long[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextLong() % 1000000; // Prevent overflow
+        }
+
+        int begin = 100, end = 500;
+        long[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = begin; i < end - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y);
+        assertTrue(Arrays.equals(seqResult, list));
+
+        try {
+            Arrays.parallelPrefix(list, begin, end, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((long[]) null, begin, end, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix(list, end, begin, (x, y) -> x + y);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(double[], java.util.function.DoubleBinaryOperator)
+     */
+    public void test_parallelPrefix$D() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        double[] list = new double[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextDouble() * 1000;
+        }
+
+        double[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = 0; i < seqResult.length - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, (x, y) -> x + y);
+
+        // Parallel double arithmetic contains error, reduce to integer for comparison.
+        int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray();
+        int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray();
+        assertTrue(Arrays.equals(seqResultInInt, listInInt));
+
+        try {
+            Arrays.parallelPrefix(list, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((double[]) null, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator)
+     */
+    public void test_parallelPrefix$DII() {
+        // Get an arbitrary array of ints.
+        Random rand = new Random(0);
+        double[] list = new double[1000];
+        for(int i = 0; i < list.length; ++i) {
+            list[i] = rand.nextDouble() * 1000;
+        }
+
+        int begin = 100, end = 500;
+        double[] seqResult = list.clone();
+
+        // Sequential solution
+        for(int i = begin; i < end - 1; ++i) {
+            seqResult[i + 1] += seqResult[i];
+        }
+
+        Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y);
+
+        // Parallel double arithmetic contains error, reduce to integer for comparison.
+        int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray();
+        int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray();
+        assertTrue(Arrays.equals(seqResultInInt, listInInt));
+
+        try {
+            Arrays.parallelPrefix(list, begin, end, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((double[]) null, begin, end, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix(list, end, begin, (x, y) -> x + y);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(T[], java.util.function.BinaryOperator<T>)
+     */
+    public void test_parallelPrefix$T() {
+        String[] strings = new String[3];
+        strings[0] = "a";
+        strings[1] = "b";
+        strings[2] = "c";
+
+        Arrays.parallelPrefix(strings, (x, y) -> x + y);
+        assertEquals("a", strings[0]);
+        assertEquals("ab", strings[1]);
+        assertEquals("abc", strings[2]);
+
+        try {
+            Arrays.parallelPrefix(strings, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((String[]) null, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * java.util.Array#parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>)
+     */
+    public void test_parallelPrefix$TII() {
+        String[] strings = new String[5];
+        strings[0] = "a";
+        strings[1] = "b";
+        strings[2] = "c";
+        strings[3] = "d";
+        strings[4] = "e";
+        int begin = 1, end = 4;
+
+        Arrays.parallelPrefix(strings, begin, end, (x, y) -> x + y);
+        assertEquals("a", strings[0]);
+        assertEquals("b", strings[1]);
+        assertEquals("bc", strings[2]);
+        assertEquals("bcd", strings[3]);
+        assertEquals("e", strings[4]);
+
+        try {
+            Arrays.parallelPrefix(strings, begin, end, null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix((String[]) null, begin, end, (x, y) -> x + y);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Arrays.parallelPrefix(strings, end, begin, (x, y) -> x + y);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/BitSetTest.java b/luni/src/test/java/libcore/java/util/BitSetTest.java
index 4998a07..c4e8ad3 100644
--- a/luni/src/test/java/libcore/java/util/BitSetTest.java
+++ b/luni/src/test/java/libcore/java/util/BitSetTest.java
@@ -20,6 +20,7 @@
 import java.nio.LongBuffer;
 import java.util.Arrays;
 import java.util.BitSet;
+import java.util.Random;
 
 public class BitSetTest extends junit.framework.TestCase {
     public void test_toString() throws Exception {
@@ -231,4 +232,17 @@
         result.xor(big());
         assertEquals("{10, 1000}", result.toString());
     }
+
+    public void test_stream() {
+        final int size = 128;
+
+        // Generate an arbitrary array of bytes.
+        byte[] bytes = new byte[size];
+        new Random(0).nextBytes(bytes);
+
+        BitSet bs = BitSet.valueOf(bytes);
+
+        assertEquals(bs.cardinality(), bs.stream().count());
+        bs.stream().forEach(x -> assertTrue(bs.get(x)));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/CalendarWeekOfMonthTest.java b/luni/src/test/java/libcore/java/util/CalendarWeekOfMonthTest.java
new file mode 100644
index 0000000..66cd0e8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/CalendarWeekOfMonthTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.java.util;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that Calendar.get(WEEK_OF_MONTH) works as expected.
+ */
+@RunWith(Parameterized.class)
+public class CalendarWeekOfMonthTest {
+
+    private final long timeInMillis;
+
+    private final String date;
+
+    private final int firstDayOfWeek;
+
+    private final int minimalDaysInFirstWeek;
+
+    private final int expectedWeekOfMonth;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {
+                // MinimalDaysInFirstWeek = 4, FirstDayOfWeek MONDAY
+                { 1462107600000L, "01 May 2016", Calendar.MONDAY, 4, 0 },
+                { 1462194000000L, "02 May 2016", Calendar.MONDAY, 4, 1 },
+                { 1462798800000L, "09 May 2016", Calendar.MONDAY, 4, 2 },
+                { 1463403600000L, "16 May 2016", Calendar.MONDAY, 4, 3 },
+                { 1464008400000L, "23 May 2016", Calendar.MONDAY, 4, 4 },
+                { 1464613200000L, "30 May 2016", Calendar.MONDAY, 4, 5 },
+                { 1464786000000L, "01 Jun 2016", Calendar.MONDAY, 4, 1 },
+                { 1465218000000L, "06 Jun 2016", Calendar.MONDAY, 4, 2 },
+                { 1465822800000L, "13 Jun 2016", Calendar.MONDAY, 4, 3 },
+                { 1466427600000L, "20 Jun 2016", Calendar.MONDAY, 4, 4 },
+                { 1467032400000L, "27 Jun 2016", Calendar.MONDAY, 4, 5 },
+                { 1467378000000L, "01 Jul 2016", Calendar.MONDAY, 4, 0 },
+                { 1467637200000L, "04 Jul 2016", Calendar.MONDAY, 4, 1 },
+                { 1468242000000L, "11 Jul 2016", Calendar.MONDAY, 4, 2 },
+                { 1468846800000L, "18 Jul 2016", Calendar.MONDAY, 4, 3 },
+                { 1469451600000L, "25 Jul 2016", Calendar.MONDAY, 4, 4 },
+                { 1470056400000L, "01 Aug 2016", Calendar.MONDAY, 4, 1 },
+                { 1470661200000L, "08 Aug 2016", Calendar.MONDAY, 4, 2 },
+                { 1471266000000L, "15 Aug 2016", Calendar.MONDAY, 4, 3 },
+                { 1471870800000L, "22 Aug 2016", Calendar.MONDAY, 4, 4 },
+                { 1472475600000L, "29 Aug 2016", Calendar.MONDAY, 4, 5 },
+                { 1472734800000L, "01 Sep 2016", Calendar.MONDAY, 4, 1 },
+                { 1473080400000L, "05 Sep 2016", Calendar.MONDAY, 4, 2 },
+                { 1473685200000L, "12 Sep 2016", Calendar.MONDAY, 4, 3 },
+                { 1474290000000L, "19 Sep 2016", Calendar.MONDAY, 4, 4 },
+                { 1474894800000L, "26 Sep 2016", Calendar.MONDAY, 4, 5 },
+                { 1475326800000L, "01 Oct 2016", Calendar.MONDAY, 4, 0 },
+                { 1475499600000L, "03 Oct 2016", Calendar.MONDAY, 4, 1 },
+                { 1476104400000L, "10 Oct 2016", Calendar.MONDAY, 4, 2 },
+                { 1476709200000L, "17 Oct 2016", Calendar.MONDAY, 4, 3 },
+                { 1477314000000L, "24 Oct 2016", Calendar.MONDAY, 4, 4 },
+                { 1477918800000L, "31 Oct 2016", Calendar.MONDAY, 4, 5 },
+                { 1478005200000L, "01 Nov 2016", Calendar.MONDAY, 4, 1 },
+                { 1478523600000L, "07 Nov 2016", Calendar.MONDAY, 4, 2 },
+                { 1479128400000L, "14 Nov 2016", Calendar.MONDAY, 4, 3 },
+                { 1479733200000L, "21 Nov 2016", Calendar.MONDAY, 4, 4 },
+                { 1480338000000L, "28 Nov 2016", Calendar.MONDAY, 4, 5 },
+
+                // MinimalDaysInFirstWeek = 1, FirstDayOfWeek MONDAY
+                { 1462107600000L, "01 May 2016", Calendar.MONDAY, 1, 1 },
+                { 1462194000000L, "02 May 2016", Calendar.MONDAY, 1, 2 },
+                { 1462798800000L, "09 May 2016", Calendar.MONDAY, 1, 3 },
+                { 1463403600000L, "16 May 2016", Calendar.MONDAY, 1, 4 },
+                { 1464008400000L, "23 May 2016", Calendar.MONDAY, 1, 5 },
+                { 1464613200000L, "30 May 2016", Calendar.MONDAY, 1, 6 },
+                { 1464786000000L, "01 Jun 2016", Calendar.MONDAY, 1, 1 },
+                { 1465218000000L, "06 Jun 2016", Calendar.MONDAY, 1, 2 },
+                { 1465822800000L, "13 Jun 2016", Calendar.MONDAY, 1, 3 },
+                { 1466427600000L, "20 Jun 2016", Calendar.MONDAY, 1, 4 },
+                { 1467032400000L, "27 Jun 2016", Calendar.MONDAY, 1, 5 },
+                { 1467378000000L, "01 Jul 2016", Calendar.MONDAY, 1, 1 },
+                { 1467637200000L, "04 Jul 2016", Calendar.MONDAY, 1, 2 },
+                { 1468242000000L, "11 Jul 2016", Calendar.MONDAY, 1, 3 },
+                { 1468846800000L, "18 Jul 2016", Calendar.MONDAY, 1, 4 },
+                { 1469451600000L, "25 Jul 2016", Calendar.MONDAY, 1, 5 },
+                { 1470056400000L, "01 Aug 2016", Calendar.MONDAY, 1, 1 },
+                { 1470661200000L, "08 Aug 2016", Calendar.MONDAY, 1, 2 },
+                { 1471266000000L, "15 Aug 2016", Calendar.MONDAY, 1, 3 },
+                { 1471870800000L, "22 Aug 2016", Calendar.MONDAY, 1, 4 },
+                { 1472475600000L, "29 Aug 2016", Calendar.MONDAY, 1, 5 },
+                { 1472734800000L, "01 Sep 2016", Calendar.MONDAY, 1, 1 },
+                { 1473080400000L, "05 Sep 2016", Calendar.MONDAY, 1, 2 },
+                { 1473685200000L, "12 Sep 2016", Calendar.MONDAY, 1, 3 },
+                { 1474290000000L, "19 Sep 2016", Calendar.MONDAY, 1, 4 },
+                { 1474894800000L, "26 Sep 2016", Calendar.MONDAY, 1, 5 },
+                { 1475326800000L, "01 Oct 2016", Calendar.MONDAY, 1, 1 },
+                { 1475499600000L, "03 Oct 2016", Calendar.MONDAY, 1, 2 },
+                { 1476104400000L, "10 Oct 2016", Calendar.MONDAY, 1, 3 },
+                { 1476709200000L, "17 Oct 2016", Calendar.MONDAY, 1, 4 },
+                { 1477314000000L, "24 Oct 2016", Calendar.MONDAY, 1, 5 },
+                { 1477918800000L, "31 Oct 2016", Calendar.MONDAY, 1, 6 },
+                { 1478005200000L, "01 Nov 2016", Calendar.MONDAY, 1, 1 },
+                { 1478523600000L, "07 Nov 2016", Calendar.MONDAY, 1, 2 },
+                { 1479128400000L, "14 Nov 2016", Calendar.MONDAY, 1, 3 },
+                { 1479733200000L, "21 Nov 2016", Calendar.MONDAY, 1, 4 },
+                { 1480338000000L, "28 Nov 2016", Calendar.MONDAY, 1, 5 },
+
+                // MinimalDaysInFirstWeek = 4, FirstDayOfWeek SUNDAY
+                { 1462107600000L, "01 May 2016", Calendar.SUNDAY, 4, 1 },
+                { 1462712400000L, "08 May 2016", Calendar.SUNDAY, 4, 2 },
+                { 1463317200000L, "15 May 2016", Calendar.SUNDAY, 4, 3 },
+                { 1463922000000L, "22 May 2016", Calendar.SUNDAY, 4, 4 },
+                { 1464526800000L, "29 May 2016", Calendar.SUNDAY, 4, 5 },
+                { 1464786000000L, "01 Jun 2016", Calendar.SUNDAY, 4, 1 },
+                { 1465131600000L, "05 Jun 2016", Calendar.SUNDAY, 4, 2 },
+                { 1465736400000L, "12 Jun 2016", Calendar.SUNDAY, 4, 3 },
+                { 1466341200000L, "19 Jun 2016", Calendar.SUNDAY, 4, 4 },
+                { 1466946000000L, "26 Jun 2016", Calendar.SUNDAY, 4, 5 },
+                { 1467378000000L, "01 Jul 2016", Calendar.SUNDAY, 4, 0 },
+                { 1467550800000L, "03 Jul 2016", Calendar.SUNDAY, 4, 1 },
+                { 1468155600000L, "10 Jul 2016", Calendar.SUNDAY, 4, 2 },
+                { 1468760400000L, "17 Jul 2016", Calendar.SUNDAY, 4, 3 },
+                { 1469365200000L, "24 Jul 2016", Calendar.SUNDAY, 4, 4 },
+                { 1469970000000L, "31 Jul 2016", Calendar.SUNDAY, 4, 5 },
+                { 1470056400000L, "01 Aug 2016", Calendar.SUNDAY, 4, 1 },
+                { 1470574800000L, "07 Aug 2016", Calendar.SUNDAY, 4, 2 },
+                { 1471179600000L, "14 Aug 2016", Calendar.SUNDAY, 4, 3 },
+                { 1471784400000L, "21 Aug 2016", Calendar.SUNDAY, 4, 4 },
+                { 1472389200000L, "28 Aug 2016", Calendar.SUNDAY, 4, 5 },
+                { 1472734800000L, "01 Sep 2016", Calendar.SUNDAY, 4, 0 },
+                { 1472994000000L, "04 Sep 2016", Calendar.SUNDAY, 4, 1 },
+                { 1473598800000L, "11 Sep 2016", Calendar.SUNDAY, 4, 2 },
+                { 1474203600000L, "18 Sep 2016", Calendar.SUNDAY, 4, 3 },
+                { 1474808400000L, "25 Sep 2016", Calendar.SUNDAY, 4, 4 },
+                { 1475326800000L, "01 Oct 2016", Calendar.SUNDAY, 4, 0 },
+                { 1475413200000L, "02 Oct 2016", Calendar.SUNDAY, 4, 1 },
+                { 1476018000000L, "09 Oct 2016", Calendar.SUNDAY, 4, 2 },
+                { 1476622800000L, "16 Oct 2016", Calendar.SUNDAY, 4, 3 },
+                { 1477227600000L, "23 Oct 2016", Calendar.SUNDAY, 4, 4 },
+                { 1477832400000L, "30 Oct 2016", Calendar.SUNDAY, 4, 5 },
+                { 1478005200000L, "01 Nov 2016", Calendar.SUNDAY, 4, 1 },
+                { 1478437200000L, "06 Nov 2016", Calendar.SUNDAY, 4, 2 },
+                { 1479042000000L, "13 Nov 2016", Calendar.SUNDAY, 4, 3 },
+                { 1479646800000L, "20 Nov 2016", Calendar.SUNDAY, 4, 4 },
+                { 1480251600000L, "27 Nov 2016", Calendar.SUNDAY, 4, 5 },
+
+                // MinimalDaysInFirstWeek = 1, FirstDayOfWeek SUNDAY
+                { 1462107600000L, "01 May 2016", Calendar.SUNDAY, 1, 1 },
+                { 1462712400000L, "08 May 2016", Calendar.SUNDAY, 1, 2 },
+                { 1463317200000L, "15 May 2016", Calendar.SUNDAY, 1, 3 },
+                { 1463922000000L, "22 May 2016", Calendar.SUNDAY, 1, 4 },
+                { 1464526800000L, "29 May 2016", Calendar.SUNDAY, 1, 5 },
+                { 1464786000000L, "01 Jun 2016", Calendar.SUNDAY, 1, 1 },
+                { 1465131600000L, "05 Jun 2016", Calendar.SUNDAY, 1, 2 },
+                { 1465736400000L, "12 Jun 2016", Calendar.SUNDAY, 1, 3 },
+                { 1466341200000L, "19 Jun 2016", Calendar.SUNDAY, 1, 4 },
+                { 1466946000000L, "26 Jun 2016", Calendar.SUNDAY, 1, 5 },
+                { 1467378000000L, "01 Jul 2016", Calendar.SUNDAY, 1, 1 },
+                { 1467550800000L, "03 Jul 2016", Calendar.SUNDAY, 1, 2 },
+                { 1468155600000L, "10 Jul 2016", Calendar.SUNDAY, 1, 3 },
+                { 1468760400000L, "17 Jul 2016", Calendar.SUNDAY, 1, 4 },
+                { 1469365200000L, "24 Jul 2016", Calendar.SUNDAY, 1, 5 },
+                { 1469970000000L, "31 Jul 2016", Calendar.SUNDAY, 1, 6 },
+                { 1470056400000L, "01 Aug 2016", Calendar.SUNDAY, 1, 1 },
+                { 1470574800000L, "07 Aug 2016", Calendar.SUNDAY, 1, 2 },
+                { 1471179600000L, "14 Aug 2016", Calendar.SUNDAY, 1, 3 },
+                { 1471784400000L, "21 Aug 2016", Calendar.SUNDAY, 1, 4 },
+                { 1472389200000L, "28 Aug 2016", Calendar.SUNDAY, 1, 5 },
+                { 1472734800000L, "01 Sep 2016", Calendar.SUNDAY, 1, 1 },
+                { 1472994000000L, "04 Sep 2016", Calendar.SUNDAY, 1, 2 },
+                { 1473598800000L, "11 Sep 2016", Calendar.SUNDAY, 1, 3 },
+                { 1474203600000L, "18 Sep 2016", Calendar.SUNDAY, 1, 4 },
+                { 1474808400000L, "25 Sep 2016", Calendar.SUNDAY, 1, 5 },
+                { 1475326800000L, "01 Oct 2016", Calendar.SUNDAY, 1, 1 },
+                { 1475413200000L, "02 Oct 2016", Calendar.SUNDAY, 1, 2 },
+                { 1476018000000L, "09 Oct 2016", Calendar.SUNDAY, 1, 3 },
+                { 1476622800000L, "16 Oct 2016", Calendar.SUNDAY, 1, 4 },
+                { 1477227600000L, "23 Oct 2016", Calendar.SUNDAY, 1, 5 },
+                { 1477832400000L, "30 Oct 2016", Calendar.SUNDAY, 1, 6 },
+                { 1478005200000L, "01 Nov 2016", Calendar.SUNDAY, 1, 1 },
+                { 1478437200000L, "06 Nov 2016", Calendar.SUNDAY, 1, 2 },
+                { 1479042000000L, "13 Nov 2016", Calendar.SUNDAY, 1, 3 },
+                { 1479646800000L, "20 Nov 2016", Calendar.SUNDAY, 1, 4 },
+                { 1480251600000L, "27 Nov 2016", Calendar.SUNDAY, 1, 5 },
+
+        });
+    }
+
+    public CalendarWeekOfMonthTest(long timeInMillis, String date, int firstDayOfWeek,
+            int minimalDaysInFirstWeek, int expectedWeekOfMonth) {
+        this.timeInMillis = timeInMillis;
+        this.date = date;
+        this.firstDayOfWeek = firstDayOfWeek;
+        this.minimalDaysInFirstWeek = minimalDaysInFirstWeek;
+        this.expectedWeekOfMonth = expectedWeekOfMonth;
+    }
+
+    @Test
+    public void test() {
+        Calendar calendar = new GregorianCalendar(
+                TimeZone.getTimeZone("America/Los_Angeles"), Locale.US);
+        calendar.setFirstDayOfWeek(firstDayOfWeek);
+        calendar.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
+        calendar.setTimeInMillis(timeInMillis);
+
+        assertEquals(toString(), expectedWeekOfMonth, calendar.get(Calendar.WEEK_OF_MONTH));
+    }
+
+    @Override
+    public String toString() {
+        return "CalendarWeekOfMonthTest{" + "timeInMillis=" + timeInMillis
+                + ", date='" + date + '\'' + ", firstDayOfWeek=" + firstDayOfWeek
+                + ", minimalDaysInFirstWeek=" + minimalDaysInFirstWeek
+                + ", expectedWeekOfMonth=" + expectedWeekOfMonth + '}';
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/CollectionsTest.java b/luni/src/test/java/libcore/java/util/CollectionsTest.java
index c45b83e..f3284c0 100644
--- a/luni/src/test/java/libcore/java/util/CollectionsTest.java
+++ b/luni/src/test/java/libcore/java/util/CollectionsTest.java
@@ -32,6 +32,9 @@
 
 public final class CollectionsTest extends TestCase {
 
+    private static final Object NOT_A_STRING = new Object();
+    private static final Object A_STRING = "string";
+
     public void testEmptyEnumeration() {
         Enumeration<Object> e = Collections.emptyEnumeration();
         assertFalse(e instanceof Serializable);
@@ -599,4 +602,140 @@
     public void test_SingletonList_sort() {
         Collections.singletonList(1).sort((k1, k2) -> 2);
     }
+
+    public void test_CheckedMap_replaceAll() {
+        Map<Integer, Integer> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Integer.class);
+        checkedMap.put(1, 10);
+        checkedMap.put(2, 20);
+        checkedMap.put(3, 30);
+        checkedMap.replaceAll((k, v) -> (Integer)k + (Integer)v);
+        assertEquals(11, checkedMap.get(1));
+        assertEquals(22, checkedMap.get(2));
+        assertEquals(33, checkedMap.get(3));
+        assertEquals(3, checkedMap.size());
+    }
+
+    public void test_CheckedMap_putIfAbsent() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_putIfAbsent(checkedMap, true /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+
+        // Without generics to check the typeCheck implementation
+        Map checkedMap2 = Collections.checkedMap(new HashMap<>(), Integer.class, String.class);
+
+        // When key is present
+        checkedMap2.putIfAbsent(1, A_STRING);
+        try {
+            checkedMap2.putIfAbsent(1, NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+
+        // When key is absent
+        checkedMap2.clear();
+        try {
+            checkedMap2.putIfAbsent(1, NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_remove() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_remove(checkedMap, true /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+    }
+
+    public void test_CheckedMap_replace$K$V$V() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_replace$K$V$V(checkedMap, true /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+
+        // Without generics to check the typeCheck implementation
+        Map checkedMap2 = Collections.checkedMap(new HashMap<>(), Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+
+        try {
+            checkedMap2.replace(1, NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_replace$K$V() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_replace$K$V(checkedMap, true /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+
+        // Without generics to check the typeCheck implementation
+        Map checkedMap2 = Collections.checkedMap(new HashMap<>(), Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+
+        try {
+            checkedMap2.replace(1, 1, NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_computeIfAbsent() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_computeIfAbsent(checkedMap, true /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+
+        // Without generics to check the typeCheck implementation
+        Map checkedMap2 = Collections.checkedMap(new HashMap<>(), Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+
+        // When key is present
+        try {
+            checkedMap2.computeIfAbsent(1, k -> NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+
+        // When key is absent
+        checkedMap2.clear();
+        try {
+            checkedMap2.computeIfAbsent(1, k -> NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_computeIfPresent() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_computeIfPresent(checkedMap, true /* acceptsNullKey */);
+
+        // Without generics to check the typeCheck implementation
+        Map m = new HashMap();
+        Map checkedMap2 = Collections.checkedMap(m, Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+
+        try {
+            checkedMap2.computeIfPresent(1, (k, v) -> NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_compute() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_compute(checkedMap, true /* acceptsNullKey */);
+
+        Map checkedMap2 = Collections.checkedMap(new HashMap(), Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+        try {
+            checkedMap2.compute(1, (k, v) -> NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
+
+    public void test_CheckedMap_merge() {
+        Map<Integer, Double> map = new HashMap<>();
+        Map checkedMap = Collections.checkedMap(map, Integer.class, Double.class);
+        MapDefaultMethodTester.test_merge(checkedMap, true /* acceptsNullKey */);
+
+        // Without generics to check the typeCheck implementation
+        Map checkedMap2 =
+                Collections.checkedMap(new HashMap<>(), Integer.class, String.class);
+        checkedMap2.put(1, A_STRING);
+
+        try {
+            checkedMap2.merge(1, A_STRING, (v1, v2) -> NOT_A_STRING);
+        } catch (ClassCastException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/GregorianCalendarTest.java b/luni/src/test/java/libcore/java/util/GregorianCalendarTest.java
index 8b417f2..3fa4dab 100644
--- a/luni/src/test/java/libcore/java/util/GregorianCalendarTest.java
+++ b/luni/src/test/java/libcore/java/util/GregorianCalendarTest.java
@@ -38,6 +38,22 @@
             Calendar.NOVEMBER, 2, 0, hours(2),
             hours(1));
 
+    private Locale defaultLocale;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        defaultLocale = Locale.getDefault();
+        // Most tests are locale independent, but locale does affect start-of-week.
+        Locale.setDefault(Locale.US);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        Locale.setDefault(defaultLocale);
+        super.tearDown();
+    }
+
     // Documented a previous difference in behavior between this and the RI, see
     // https://code.google.com/p/android/issues/detail?id=61993 for more details.
     // Switching to OpenJDK has fixed that issue and so this test has been changed to reflect
diff --git a/luni/src/test/java/libcore/java/util/HashMapTest.java b/luni/src/test/java/libcore/java/util/HashMapTest.java
index 5aecbb3..12bf59b 100644
--- a/luni/src/test/java/libcore/java/util/HashMapTest.java
+++ b/luni/src/test/java/libcore/java/util/HashMapTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.util;
 
+import java.util.ConcurrentModificationException;
 import java.util.HashMap;
 
 public class HashMapTest extends junit.framework.TestCase {
@@ -68,4 +69,33 @@
         MapDefaultMethodTester
                 .test_merge(new HashMap<>(), true /*acceptsNullKey*/);
     }
+
+    public void test_replaceAll() throws Exception {
+        HashMap<String, String> map = new HashMap<>();
+        map.put("one", "1");
+        map.put("two", "2");
+        map.put("three", "3");
+
+        map.replaceAll((k, v) -> k + v);
+        assertEquals("one1", map.get("one"));
+        assertEquals("two2", map.get("two"));
+        assertEquals("three3", map.get("three"));
+        assertEquals(3, map.size());
+
+        try {
+            map.replaceAll(new java.util.function.BiFunction<String, String, String>() {
+                @Override
+                public String apply(String k, String v) {
+                    map.put("foo1", v);
+                    return v;
+                }
+            });
+            fail();
+        } catch(ConcurrentModificationException expected) {}
+
+        try {
+            map.replaceAll(null);
+            fail();
+        } catch(NullPointerException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/HashtableTest.java b/luni/src/test/java/libcore/java/util/HashtableTest.java
index 28aa662..40fbf25 100644
--- a/luni/src/test/java/libcore/java/util/HashtableTest.java
+++ b/luni/src/test/java/libcore/java/util/HashtableTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.util;
 
+import java.util.ConcurrentModificationException;
 import java.util.Hashtable;
 import java.util.Map;
 
@@ -68,4 +69,37 @@
     public void test_merge() {
         MapDefaultMethodTester.test_merge(new Hashtable<>(), false /*doesNotAcceptNullKey*/);
     }
+
+    public void test_replaceAll() throws Exception {
+        Hashtable<String, String> ht = new Hashtable<>();
+        ht.put("one", "1");
+        ht.put("two", "2");
+        ht.put("three", "3");
+
+        ht.replaceAll((k, v) -> k + v);
+        assertEquals("one1", ht.get("one"));
+        assertEquals("two2", ht.get("two"));
+        assertEquals("three3", ht.get("three"));
+        assertEquals(3, ht.size());
+
+        try {
+            ht.replaceAll(new java.util.function.BiFunction<String, String, String>() {
+                @Override
+                public String apply(String k, String v) {
+                    ht.put("foo", v);
+                    return v;
+                }
+            });
+            fail();
+        } catch(ConcurrentModificationException expected) {}
+
+        try {
+            ht.replaceAll(null);
+            fail();
+        } catch(NullPointerException expected) {}
+
+        try {
+            ht.replaceAll((k, v) -> null);
+        } catch (NullPointerException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java b/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
index c7de1f6..fec95b1 100644
--- a/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
+++ b/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
@@ -16,8 +16,11 @@
 
 package libcore.java.util;
 
+import java.util.ConcurrentModificationException;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class LinkedHashMapTest extends junit.framework.TestCase {
 
@@ -205,4 +208,60 @@
         assertEquals("key1", newest.getKey());
         assertEquals("value3", newest.getValue());
     }
+
+    // http://b/27929722
+    // This tests the behaviour is consistent with earlier Android releases.
+    // This behaviour is NOT consistent with the RI. Future Android releases
+    // might change this.
+    public void test_removeEldestEntry() {
+        final AtomicBoolean removeEldestEntryReturnValue = new AtomicBoolean(false);
+        final AtomicInteger removeEldestEntryCallCount = new AtomicInteger(0);
+        LinkedHashMap<String, String> m = new LinkedHashMap<String, String>() {
+            @Override
+            protected boolean removeEldestEntry(Entry eldest) {
+                removeEldestEntryCallCount.incrementAndGet();
+                return removeEldestEntryReturnValue.get();
+            }
+        };
+
+        m.put("foo", "bar");
+        assertEquals(0, removeEldestEntryCallCount.get());
+        m.put("baz", "quux");
+        assertEquals(1, removeEldestEntryCallCount.get());
+
+        removeEldestEntryReturnValue.set(true);
+        m.put("foob", "faab");
+        assertEquals(2, removeEldestEntryCallCount.get());
+        assertEquals(2, m.size());
+        assertFalse(m.containsKey("foo"));
+    }
+
+    public void test_replaceAll() {
+        LinkedHashMap<String, String> map = new LinkedHashMap<>();
+        map.put("one", "1");
+        map.put("two", "2");
+        map.put("three", "3");
+
+        map.replaceAll((k, v) -> k + v);
+        assertEquals("one1", map.get("one"));
+        assertEquals("two2", map.get("two"));
+        assertEquals("three3", map.get("three"));
+        assertEquals(3, map.size());
+
+        try {
+            map.replaceAll(new java.util.function.BiFunction<String, String, String>() {
+                @Override
+                public String apply(String k, String v) {
+                    map.put("foo1", v);
+                    return v;
+                }
+            });
+            fail();
+        } catch(ConcurrentModificationException expected) {}
+
+        try {
+            map.replaceAll(null);
+            fail();
+        } catch(NullPointerException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/RandomTest.java b/luni/src/test/java/libcore/java/util/RandomTest.java
index 11bdc63..f72a9be 100644
--- a/luni/src/test/java/libcore/java/util/RandomTest.java
+++ b/luni/src/test/java/libcore/java/util/RandomTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.util;
 
+import java.util.Arrays;
 import java.util.Random;
 
 public class RandomTest extends junit.framework.TestCase {
@@ -40,4 +41,237 @@
         r2.nextInt();
         assertNotNull(r2.state);
     }
+
+    public void test_ints$() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+
+        Random rand = new Random(0);
+        int[] rands = new int[limit];
+        for(int i = 0; i < limit; ++i) {
+            rands[i] = rand.nextInt();
+        }
+
+        int[] streamRands = new Random(0).ints().limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+    }
+
+    public void test_ints$L() {
+        final int size = 32;
+
+        Random rand = new Random(0);
+        int[] rands = new int[size];
+        for(int i = 0; i < size; ++i) {
+            rands[i] = rand.nextInt();
+        }
+
+        int[] streamRands = new Random(0).ints(size).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).ints(size).count());
+
+        try {
+            new Random(0).ints(-1);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_ints$II() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        int[] rands = new int[limit];
+        for(int i = 0; i < limit; ++i) {
+            rands[i] = rand.nextInt(bound - origin) + origin;
+        }
+
+        int[] streamRands = new Random(0).ints(origin, bound).limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+
+        try {
+            new Random(0).ints(100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_ints$LII() {
+        final int size = 32;
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        int[] rands = new int[size];
+        for(int i = 0; i < size; ++i) {
+            rands[i] = rand.nextInt(bound - origin) + origin;
+        }
+
+        int[] streamRands = new Random(0).ints(size, origin, bound).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).ints(size, origin, bound).count());
+
+        try {
+            new Random(0).ints(-1, 10, 20);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        try {
+            new Random(0).ints(10, 100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_longs$() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+
+        Random rand = new Random(0);
+        long[] rands = new long[limit];
+        for(int i = 0; i < limit; ++i) {
+            rands[i] = rand.nextLong();
+        }
+
+        long[] streamRands = new Random(0).longs().limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+    }
+
+    public void test_longs$L() {
+        final int size = 32;
+
+        Random rand = new Random(0);
+        long[] rands = new long[size];
+        for(int i = 0; i < size; ++i) {
+            rands[i] = rand.nextLong();
+        }
+
+        long[] streamRands = new Random(0).longs(size).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).longs(size).count());
+
+        try {
+            new Random(0).longs(-1);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_longs$II() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        long[] rands = new long[limit];
+        for(int i = 0; i < limit; ++i) {
+            rands[i] = (rand.nextLong() & 127) + origin;
+        }
+
+        long[] streamRands = new Random(0).longs(origin, bound).limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+
+        try {
+            new Random(0).longs(100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_longs$LII() {
+        final int size = 32;
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        long[] rands = new long[size];
+        for(int i = 0; i < size; ++i) {
+            rands[i] = (rand.nextLong() & 127) + origin;
+        }
+
+        long[] streamRands = new Random(0).longs(size, origin, bound).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).longs(size, origin, bound).count());
+
+        try {
+            new Random(0).longs(-1, 10, 20);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        try {
+            new Random(0).longs(10, 100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_doubles$() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+
+        Random rand = new Random(0);
+        double[] rands = new double[limit];
+        for(int i = 0; i < limit; ++i) {
+            rands[i] = rand.nextDouble();
+        }
+
+        double[] streamRands = new Random(0).doubles().limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+    }
+
+    public void test_doubles$L() {
+        final int size = 32;
+
+        Random rand = new Random(0);
+        double[] rands = new double[size];
+        for(int i = 0; i < size; ++i) {
+            rands[i] = rand.nextDouble();
+        }
+
+        double[] streamRands = new Random(0).doubles(size).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).doubles(size).count());
+
+        try {
+            new Random(0).ints(-1);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_doubles$II() {
+        final int limit = 128; // We can't test for every element in an infinite stream.
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        double[] rands = new double[limit];
+        for(int i = 0; i < limit; ++i) {
+            double r = rand.nextDouble() * (bound - origin) + origin;
+            if (r >= bound) {
+                r = Math.nextDown(r);
+            }
+            rands[i] = r;
+        }
+
+        double[] streamRands = new Random(0).doubles(origin, bound).limit(limit).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+
+        try {
+            new Random(0).doubles(100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void test_doubles$LII() {
+        final int size = 32;
+        final int origin = 128, bound = 256;
+
+        Random rand = new Random(0);
+        double[] rands = new double[size];
+        for(int i = 0; i < size; ++i) {
+            double r = rand.nextDouble() * (bound - origin) + origin;
+            if (r >= bound) {
+                r = Math.nextDown(r);
+            }
+            rands[i] = r;
+        }
+
+        double[] streamRands = new Random(0).doubles(size, origin, bound).toArray();
+        assertTrue(Arrays.equals(rands, streamRands));
+        assertEquals(size, new Random(0).doubles(size, origin, bound).count());
+
+        try {
+            new Random(0).doubles(-1, 10, 20);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        try {
+            new Random(0).doubles(10, 100, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/TreeMapTest.java b/luni/src/test/java/libcore/java/util/TreeMapTest.java
index 05c5235..355d29d 100644
--- a/luni/src/test/java/libcore/java/util/TreeMapTest.java
+++ b/luni/src/test/java/libcore/java/util/TreeMapTest.java
@@ -567,4 +567,43 @@
         SpliteratorTester.runSortedTests(values, (a, b) -> (a.getKey().compareTo(b.getKey())));
         SpliteratorTester.runOrderedTests(values);
     }
+
+    public void test_replaceAll() throws Exception {
+        TreeMap<String, String> map = new TreeMap<>();
+        map.put("one", "1");
+        map.put("two", "2");
+        map.put("three", "3");
+
+        TreeMap<String, String> output = new TreeMap<>();
+        map.replaceAll((k, v) -> k + v);
+        assertEquals("one1", map.get("one"));
+        assertEquals("two2", map.get("two"));
+        assertEquals("three3", map.get("three"));
+
+        try {
+            map.replaceAll(null);
+            fail();
+        } catch(NullPointerException expected) {}
+
+        try {
+            map.replaceAll(new java.util.function.BiFunction<String, String, String>() {
+                @Override
+                public String apply(String k, String v) {
+                    map.put("foo", v);
+                    return v;
+                }
+            });
+            fail();
+        } catch(ConcurrentModificationException expected) {}
+    }
+
+    public void test_replace$K$V$V() {
+        MapDefaultMethodTester.test_replace$K$V$V(new TreeMap<>(), false /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+    }
+
+    public void test_replace$K$V() {
+        MapDefaultMethodTester.test_replace$K$V(new TreeMap<>(), false /* acceptsNullKey */,
+                true /* acceptsNullValue */);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/WeakHashMapTest.java b/luni/src/test/java/libcore/java/util/WeakHashMapTest.java
new file mode 100644
index 0000000..42a1d22
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/WeakHashMapTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.util;
+
+import junit.framework.TestCase;
+
+import java.util.ConcurrentModificationException;
+import java.util.WeakHashMap;
+
+public class WeakHashMapTest extends TestCase {
+
+    static Data[] data = new Data[100];
+
+    public void test_replaceAll() {
+        initializeData();
+        WeakHashMap<Data, String> map = new WeakHashMap<>();
+        for(int i = 0; i < data.length; i++) {
+            map.put(data[i], "");
+        }
+        map.replaceAll((k, v) -> k.value);
+
+        for(int i = 0; i < data.length; i++) {
+            assertEquals(data[i].value, map.get(data[i]));
+        }
+
+        try {
+            map.replaceAll(new java.util.function.BiFunction<Data, String, String>() {
+                @Override
+                public String apply(Data k, String v) {
+                    map.put(new Data(), "");
+                    return v;
+                }
+            });
+            fail();
+        } catch (ConcurrentModificationException expected) {
+        }
+
+        try {
+            map.replaceAll(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        map.clear();
+        for(int i = 0; i < data.length; i++) {
+            map.put(data[i], data[i].value);
+        }
+
+        map.replaceAll((k, v) -> null);
+
+        for(int i = 0; i < data.length; i++) {
+            assertNull(map.get(data[i]));
+        }
+        assertEquals(data.length, map.size());
+    }
+
+    private void initializeData() {
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new Data();
+            data[i].value = Integer.toString(i);
+        }
+    }
+
+    private static class Data {
+        public String value = "";
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java b/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
index e5c3bdb..29cdffa 100644
--- a/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
+++ b/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
 import junit.framework.TestCase;
@@ -176,9 +178,12 @@
 
         // The Manifest-Version takes precedence,
         // and the Signature-Version gets no special treatment.
-        String[] lines = new String(os.toByteArray(), "UTF-8").split("\r\n");
-        assertEquals("Manifest-Version: 1.0", lines[0]);
-        assertEquals("Aardvark-Version: 3.0", lines[1]);
-        assertEquals("Signature-Version: 2.0", lines[2]);
+        List<String> lines = Arrays.asList(new String(os.toByteArray(), "UTF-8").split("\r\n"));
+        // The first line must always contain the Manifest-Version (or the Signature-Version if
+        // the ManifestVersion is missing.
+        assertEquals("Manifest-Version: 1.0", lines.get(0));
+
+        assertTrue(lines.contains("Aardvark-Version: 3.0"));
+        assertTrue(lines.contains("Signature-Version: 2.0"));
     }
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index bad8a74..ad419ac 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -3683,4 +3683,72 @@
         cipher.init(Cipher.ENCRYPT_MODE, keyGen.generateKeyPair().getPublic());
         cipher.doFinal(new byte[] {1,2,3,4});
     }
+
+    /**
+     * http://b/27224566
+     * http://b/27994930
+     * Check that a PBKDF2WITHHMACSHA1 secret key factory works well with a
+     * PBEWITHSHAAND128BITAES-CBC-BC cipher. The former is PKCS5 and the latter is PKCS12, and so
+     * mixing them is not recommended. However, until 1.52 BouncyCastle was accepting this mixture,
+     * assuming the IV was a 0 vector. Some apps still use this functionality. This
+     * compatibility is likely to be removed in later versions of Android.
+     * TODO(27995180): consider whether we keep this compatibility. Consider whether we only allow
+     * if an IV is passed in the parameters.
+     */
+    public void test_PBKDF2WITHHMACSHA1_SKFactory_and_PBEAESCBC_Cipher_noIV() throws Exception {
+        byte[] plaintext = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                17, 18, 19 };
+        byte[] ciphertext = new byte[] {  92, -65, -128, 16, -102, -115, -44, 52, 16, 124, -34,
+                -45, 58, -70, -17, 127, 119, -67, 87, 91, 63, -13, -40, 9, 97, -17, -71, 97, 10,
+                -61, -19, -73 };
+        SecretKeyFactory skf =
+                SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA1");
+        PBEKeySpec pbeks = new PBEKeySpec("password".toCharArray(),
+                "salt".getBytes(),
+                100, 128);
+        SecretKey secretKey = skf.generateSecret(pbeks);
+
+        Cipher cipher =
+                Cipher.getInstance("PBEWITHSHAAND128BITAES-CBC-BC");
+        PBEParameterSpec paramSpec = new PBEParameterSpec("salt".getBytes(), 100);
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
+        assertEquals(Arrays.toString(ciphertext), Arrays.toString(cipher.doFinal(plaintext)));
+
+        secretKey = skf.generateSecret(pbeks);
+        cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
+        assertEquals(Arrays.toString(plaintext), Arrays.toString(cipher.doFinal(ciphertext)));
+    }
+
+    /**
+     * http://b/27224566
+     * http://b/27994930
+     * Check that a PBKDF2WITHHMACSHA1 secret key factory works well with a
+     * PBEWITHSHAAND128BITAES-CBC-BC cipher. The former is PKCS5 and the latter is PKCS12, and so
+     * mixing them is not recommended. However, until 1.52 BouncyCastle was accepting this mixture,
+     * assuming the IV was a 0 vector. Some apps still use this functionality. This
+     * compatibility is likely to be removed in later versions of Android.
+     * TODO(27995180): consider whether we keep this compatibility. Consider whether we only allow
+     * if an IV is passed in the parameters.
+     */
+    public void test_PBKDF2WITHHMACSHA1_SKFactory_and_PBEAESCBC_Cipher_withIV() throws Exception {
+        byte[] plaintext = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,  12, 13, 14, 15, 16,
+                17, 18, 19 };
+        byte[] ciphertext = { 68, -87, 71, -6, 32, -77, 124, 3, 35, -26, 96, -16, 100, -17, 52, -32,
+                110, 26, -117, 112, -25, -113, -58, -30, 19, -46, -21, 59, -126, -8, -70, -89 };
+        byte[] iv = new byte[] { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+        SecretKeyFactory skf =
+                SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA1");
+        PBEKeySpec pbeks = new PBEKeySpec("password".toCharArray(),
+                "salt".getBytes(),
+                100, 128);
+        SecretKey secretKey = skf.generateSecret(pbeks);
+        Cipher cipher =
+                Cipher.getInstance("PBEWITHSHAAND128BITAES-CBC-BC");
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
+        assertEquals(Arrays.toString(ciphertext), Arrays.toString(cipher.doFinal(plaintext)));
+
+        secretKey = skf.generateSecret(pbeks);
+        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
+        assertEquals(Arrays.toString(plaintext), Arrays.toString(cipher.doFinal(ciphertext)));
+    }
 }
diff --git a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
index 0657f18..b99a3f1 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
@@ -26,6 +26,7 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Set;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -39,17 +40,18 @@
 
 public class KeyManagerFactoryTest extends TestCase {
 
-    private static TestKeyStore TEST_KEY_STORE;
+    private TestKeyStore testKeyStore;
 
-    // note the rare usage of DSA keys here in addition to RSA
-    private static TestKeyStore getTestKeyStore() throws Exception {
-        if (TEST_KEY_STORE == null) {
-            TEST_KEY_STORE = new TestKeyStore.Builder()
-                    .keyAlgorithms("RSA", "DH_RSA", "DSA", "DH_DSA", "EC", "EC_RSA")
-                    .aliasPrefix("rsa-dsa-ec-dh")
-                    .build();
-        }
-        return TEST_KEY_STORE;
+    protected void setUp() throws Exception {
+        // note the rare usage of DSA keys here in addition to RSA
+        testKeyStore = new TestKeyStore.Builder()
+                .keyAlgorithms("RSA", "DH_RSA", "DSA", "DH_DSA", "EC", "EC_RSA")
+                .aliasPrefix("rsa-dsa-ec-dh")
+                .build();
+    }
+
+    private TestKeyStore getTestKeyStore() throws Exception {
+        return testKeyStore;
     }
 
     public void test_KeyManagerFactory_getDefaultAlgorithm() throws Exception {
@@ -230,34 +232,30 @@
         X509Certificate[] certificateChain = km.getCertificateChain(alias);
         PrivateKey privateKey = km.getPrivateKey(alias);
 
-        String keyAlgName;
-        String sigAlgName;
-        if (keyType == null) {
-            keyAlgName = privateKey.getAlgorithm();
-            sigAlgName = keyAlgName;
-        } else {
-            // potentially handle EC_EC or EC_RSA
-            keyAlgName = TestKeyStore.keyAlgorithm(keyType);
-            sigAlgName = TestKeyStore.signatureAlgorithm(keyType);
-            X509Certificate certificate = certificateChain[0];
-            assertEquals(keyType, keyAlgName, certificate.getPublicKey().getAlgorithm());
-            assertEquals(keyType, keyAlgName, privateKey.getAlgorithm());
-            // skip this for EC which could return EC_RSA case instead of EC_EC
-            if (!keyType.equals("EC")) {
-                String expectedSigAlgName = sigAlgName.toUpperCase();
-                String actualSigAlgName = certificate.getSigAlgName().toUpperCase();
-                String expected = actualSigAlgName + " contains " + expectedSigAlgName;
-                assertTrue(expected, actualSigAlgName.contains(expectedSigAlgName));
-            }
-        }
+        String keyAlgName =  privateKey.getAlgorithm();
+
+        X509Certificate certificate = certificateChain[0];
+        assertEquals(keyType, keyAlgName, certificate.getPublicKey().getAlgorithm());
+
+        String sigAlgName = certificate.getSigAlgName();
 
         PrivateKeyEntry privateKeyEntry = getTestKeyStore().getPrivateKey(keyAlgName, sigAlgName);
-        if (!"EC".equals(keyAlgName)) {
-            assertEquals(keyType,
-                         Arrays.<Certificate>asList(privateKeyEntry.getCertificateChain()),
-                         Arrays.<Certificate>asList(certificateChain));
-            assertEquals(keyType,
-                         privateKeyEntry.getPrivateKey(), privateKey);
+
+        assertEquals(keyType,
+                     Arrays.<Certificate>asList(privateKeyEntry.getCertificateChain()),
+                     Arrays.<Certificate>asList(certificateChain));
+        assertEquals(keyType,
+                     privateKeyEntry.getPrivateKey(), privateKey);
+
+        if (keyType != null) {
+            assertEquals(TestKeyStore.keyAlgorithm(keyType), keyAlgName);
+
+            // Skip this when we're given only "DH" or "EC" instead of "DH_DSA",
+            // "EC_RSA", etc. since we don't know what the expected
+            // algorithm was.
+            if (!keyType.equals("DH") && !keyType.equals("EC")) {
+                assertTrue(sigAlgName.contains(TestKeyStore.signatureAlgorithm(keyType)));
+            }
         }
     }
 
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SNIHostNameTest.java b/luni/src/test/java/libcore/javax/net/ssl/SNIHostNameTest.java
new file mode 100644
index 0000000..0e4ed61
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/net/ssl/SNIHostNameTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.javax.net.ssl;
+
+import java.util.Arrays;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.StandardConstants;
+import junit.framework.TestCase;
+
+public class SNIHostNameTest extends TestCase {
+    public void test_byteArray_Constructor() throws Exception {
+        // From draft-josefsson-idn-test-vectors-00 section 5.2
+        byte[] idnEncoded = new byte[] {
+                (byte) 0xE4, (byte) 0xBB, (byte) 0x96, (byte) 0xE4, (byte) 0xBB, (byte) 0xAC,
+                (byte) 0xE4, (byte) 0xB8, (byte) 0xBA, (byte) 0xE4, (byte) 0xBB, (byte) 0x80,
+                (byte) 0xE4, (byte) 0xB9, (byte) 0x88, (byte) 0xE4, (byte) 0xB8, (byte) 0x8D,
+                (byte) 0xE8, (byte) 0xAF, (byte) 0xB4, (byte) 0xE4, (byte) 0xB8, (byte) 0xAD,
+                (byte) 0xE6, (byte) 0x96, (byte) 0x87,
+        };
+
+        SNIHostName hostName = new SNIHostName(idnEncoded);
+        assertEquals("xn--ihqwcrb4cv8a8dqg056pqjye", hostName.getAsciiName());
+        assertEquals(StandardConstants.SNI_HOST_NAME, hostName.getType());
+        assertEquals(Arrays.toString(idnEncoded), Arrays.toString(hostName.getEncoded()));
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 0ed4e88..d17e32b 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -1305,8 +1305,9 @@
         // setting wrapper sets underlying and ...
         int expectedTimeoutMillis = 1000;  // 10 was too small because it was affected by rounding
         wrapping.setSoTimeout(expectedTimeoutMillis);
-        assertEquals(expectedTimeoutMillis, wrapping.getSoTimeout());
-        assertEquals(expectedTimeoutMillis, underlying.getSoTimeout());
+        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
+        assertTrue(Math.abs(expectedTimeoutMillis - wrapping.getSoTimeout()) <= 10);
+        assertTrue(Math.abs(expectedTimeoutMillis - underlying.getSoTimeout()) <= 10);
 
         // ... getting wrapper inspects underlying
         underlying.setSoTimeout(0);
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
index a4f534b..41b9643 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
@@ -1840,4 +1840,44 @@
         mat = pat.matcher(testString);
         assertTrue(mat.matches());
     }
+
+    public void testAsPredicate() {
+        String[][] posSeq = {
+                { "abb", "ababb", "abababbababb", "abababbababbabababbbbbabb" },
+                { "213567", "12324567", "1234567", "213213567",
+                        "21312312312567", "444444567" },
+                { "abcdaab", "aab", "abaab", "cdaab", "acbdadcbaab" },
+                { "213234567", "3458", "0987654", "7689546432", "0398576",
+                        "98432", "5" },
+                {
+                        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+                        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" },
+                { "ababbaAabababblice", "ababbaAliceababab", "ababbAabliceaaa",
+                        "abbbAbbbliceaaa", "Alice" },
+                { "a123", "bnxnvgds156", "for", "while", "if", "struct" },
+                { "xy" }, { "xy" }, { "xcy" }
+        };
+
+        for (int i = 0; i < testPatterns.length; i++) {
+            Pattern p = Pattern.compile(testPatterns[i]);
+            for (int j = 0; j < posSeq[i].length; j++) {
+                assertTrue(p.asPredicate().test(posSeq[i][j]));
+            }
+        }
+    }
+
+    public void testSplitAsStream() {
+        String s[];
+        Pattern pat = Pattern.compile("b");
+        s = pat.splitAsStream("abccbadfebb").toArray(String[]::new);
+        assertEquals(s.length, 3);
+        s = pat.splitAsStream("").toArray(String[]::new);
+        assertEquals(s.length, 0);
+        pat = Pattern.compile("");
+        s = pat.splitAsStream("").toArray(String[]::new);
+        assertEquals(s.length, 0);
+        s = pat.splitAsStream("abccbadfe").toArray(String[]::new);
+        assertEquals(s.length, 9);
+    }
 }
diff --git a/luni/src/test/java/tests/security/cert/CertPathBuilder2Test.java b/luni/src/test/java/tests/security/cert/CertPathBuilder2Test.java
index ffc5d08..5451e85 100644
--- a/luni/src/test/java/tests/security/cert/CertPathBuilder2Test.java
+++ b/luni/src/test/java/tests/security/cert/CertPathBuilder2Test.java
@@ -79,19 +79,6 @@
     private void checkResult(CertPathBuilder certBuild)
             throws InvalidAlgorithmParameterException,
             CertPathBuilderException {
-        String dt = CertPathBuilder.getDefaultType();
-        String propName = CertPathBuilder1Test.DEFAULT_TYPE_PROPERTY;
-        String dtN;
-        for (int i = 0; i <invalidValues.length; i++) {
-            Security.setProperty(propName, invalidValues[i]);
-            dtN = CertPathBuilder.getDefaultType();
-            if (!dtN.equals(invalidValues[i]) && !dtN.equals(dt)) {
-                fail("Incorrect default type: ".concat(dtN));
-            }
-        }
-        Security.setProperty(propName, dt);
-        assertEquals("Incorrect default type", CertPathBuilder.getDefaultType(),
-                dt);
         try {
             certBuild.build(null);
             fail("CertPathBuilderException must be thrown");
@@ -161,10 +148,9 @@
             } catch (NoSuchAlgorithmException e) {
             }
         }
-        String prov = null;
         for (int i = 0; i < validValues.length; i++) {
             try {
-                CertPathBuilder.getInstance(validValues[i], prov);
+                CertPathBuilder.getInstance(validValues[i], (Provider) null);
                 fail("IllegalArgumentException must be thrown when provider is null (type: "
                         .concat(validValues[i]).concat(")"));
             } catch (IllegalArgumentException e) {
@@ -224,10 +210,9 @@
             } catch (NoSuchAlgorithmException e) {
             }
         }
-        Provider prov = null;
         for (int i = 0; i < validValues.length; i++) {
             try {
-                CertPathBuilder.getInstance(validValues[i], prov);
+                CertPathBuilder.getInstance(validValues[i], (Provider) null);
                 fail("IllegalArgumentException must be thrown when provider is null (type: "
                         .concat(validValues[i]).concat(")"));
             } catch (IllegalArgumentException e) {
diff --git a/luni/src/test/java/tests/security/cert/X509CertSelectorTest.java b/luni/src/test/java/tests/security/cert/X509CertSelectorTest.java
index a6eaf05..1616efb 100644
--- a/luni/src/test/java/tests/security/cert/X509CertSelectorTest.java
+++ b/luni/src/test/java/tests/security/cert/X509CertSelectorTest.java
@@ -397,7 +397,8 @@
         selector.setIssuer(iss1);
         assertTrue("The returned issuer should be equal to specified",
                    Arrays.equals(name1, selector.getIssuerAsBytes()));
-        assertFalse("The returned issuer should differ", name2.equals(selector.getIssuerAsBytes()));
+        assertFalse("The returned issuer should differ",
+                   Arrays.equals(name2, selector.getIssuerAsBytes()));
         selector.setIssuer(iss2);
         assertTrue("The returned issuer should be equal to specified",
                    Arrays.equals(name2, selector.getIssuerAsBytes()));
@@ -682,7 +683,7 @@
         assertTrue("The returned issuer should be equal to specified",
                    Arrays.equals(name1, selector.getSubjectAsBytes()));
         assertFalse("The returned issuer should differ",
-                    name2.equals(selector.getSubjectAsBytes()));
+                    Arrays.equals(name2, selector.getSubjectAsBytes()));
         selector.setSubject(sub2);
         assertTrue("The returned issuer should be equal to specified",
                    Arrays.equals(name2, selector.getSubjectAsBytes()));
diff --git a/luni/src/test/native/libcore_java_lang_ThreadTest.cpp b/luni/src/test/native/libcore_java_lang_ThreadTest.cpp
new file mode 100644
index 0000000..68e858a
--- /dev/null
+++ b/luni/src/test/native/libcore_java_lang_ThreadTest.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+
+#include <pthread.h>
+#include <sys/prctl.h>
+
+#include <jni.h>
+#include "JNIHelp.h"
+
+static JavaVM* javaVm = nullptr;
+
+static void* TestThreadNaming(void* arg) {
+    const bool attach_with_name = (reinterpret_cast<uint64_t>(arg) == 1);
+    const std::string native_thread_name = "foozball";
+    pthread_setname_np(pthread_self(), native_thread_name.c_str());
+
+    JNIEnv* env;
+    JavaVMAttachArgs args;
+    args.version = JNI_VERSION_1_6;
+    args.group = nullptr;
+    if (attach_with_name) {
+        args.name = native_thread_name.c_str();
+    } else {
+        args.name = nullptr;
+    }
+
+    if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
+        return new std::string("Attach failed");
+    }
+
+    std::string* exception_message = nullptr;
+    std::unique_ptr<char[]> thread_name(new char[32]);
+    if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name.get()), 0L, 0L, 0L) == 0) {
+        // If a thread is attached with a name, the native thread name must be set to
+        // the supplied name. In this test, the name we attach with == the
+        // native_thread_name.
+        if (attach_with_name && (thread_name.get() != native_thread_name)) {
+            exception_message = new std::string("expected_thread_name != thread_name: ");
+            exception_message->append("expected :");
+            exception_message->append(native_thread_name);
+            exception_message->append(" was :");
+            exception_message->append(thread_name.get());
+        }
+
+        // On the other hand, if the thread isn't attached with a name - the
+        // runtime assigns a name according to the usual thread naming scheme.
+        if (!attach_with_name && strncmp(thread_name.get(), "Thread", 6)) {
+            exception_message = new std::string("unexpected thread name : ");
+            exception_message->append(thread_name.get());
+        }
+    } else {
+        exception_message = new std::string("prctl(PR_GET_NAME) failed :");
+        exception_message->append(strerror(errno));
+    }
+
+
+    if (javaVm->DetachCurrentThread() != JNI_OK) {
+        exception_message = new std::string("Detach failed");
+    }
+
+    return exception_message;
+}
+
+extern "C" jstring Java_libcore_java_lang_ThreadTest_nativeTestNativeThreadNames(
+    JNIEnv* env, jobject /* object */) {
+  std::string result;
+
+  // TEST 1: Test that a thread attaching with a specified name (in the
+  // JavaVMAttachArgs) does not have its name changed.
+  pthread_t attacher;
+  if (pthread_create(&attacher, nullptr, TestThreadNaming,
+                     reinterpret_cast<void*>(static_cast<uint64_t>(0))) != 0) {
+      jniThrowException(env, "java/lang/IllegalStateException", "Attach failed");
+  }
+
+  std::string* result_test1;
+  if (pthread_join(attacher, reinterpret_cast<void**>(&result_test1)) != 0) {
+      jniThrowException(env, "java/lang/IllegalStateException", "Join failed");
+  }
+
+  if (result_test1 != nullptr) {
+      result.append("test 1: ");
+      result.append(*result_test1);
+  }
+
+  // TEST 2: Test that a thread attaching without a specified name (in the
+  // JavaVMAttachArgs) has its native name changed as per the standard naming
+  // convention.
+  pthread_t attacher2;
+  if (pthread_create(&attacher2, nullptr, TestThreadNaming,
+                     reinterpret_cast<void*>(static_cast<uint64_t>(1))) != 0) {
+      jniThrowException(env, "java/lang/IllegalStateException", "Attach failed");
+  }
+
+  std::string* result_test2;
+  if (pthread_join(attacher2, reinterpret_cast<void**>(&result_test2)) != 0) {
+      jniThrowException(env, "java/lang/IllegalStateException", "Join failed");
+  }
+
+  if (result_test2 != nullptr) {
+      result.append("test 2: ");
+      result.append(*result_test2);
+  }
+
+  // Return test results.
+  jstring resultJString = nullptr;
+  if (result.size() > 0) {
+    resultJString = env->NewStringUTF(result.c_str());
+  }
+
+  delete result_test1;
+  delete result_test2;
+
+  return resultJString;
+}
+
+extern "C" int JNI_OnLoad(JavaVM* vm, void*) {
+    javaVm = vm;
+    return JNI_VERSION_1_6;
+}
diff --git a/luni/src/test/resources/org/apache/harmony/tests/java/util/TestUtf8ResourceBundle.properties b/luni/src/test/resources/org/apache/harmony/tests/java/util/TestUtf8ResourceBundle.properties
new file mode 100644
index 0000000..9d872b4
--- /dev/null
+++ b/luni/src/test/resources/org/apache/harmony/tests/java/util/TestUtf8ResourceBundle.properties
@@ -0,0 +1 @@
+key=Страх мой удивительный UTF-8 синтаксического анализа
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index 104a6f3..c50d5ad 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -56,6 +56,7 @@
   libart/src/main/java/dalvik/system/VMStack.java \
   libart/src/main/java/dalvik/system/TransactionAbortError.java \
   dalvik/src/main/java/dalvik/system/ZygoteHooks.java \
+  libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java \
   libart/src/main/java/java/lang/Daemons.java \
   libart/src/main/java/java/lang/DexCache.java \
   luni/src/main/java/java/lang/FindBugsSuppressWarnings.java \
@@ -391,7 +392,6 @@
   luni/src/main/java/libcore/net/http/HttpDate.java \
   luni/src/main/java/libcore/net/http/ResponseUtils.java \
   luni/src/main/java/libcore/reflect/AnnotatedElements.java \
-  luni/src/main/java/libcore/reflect/AnnotationAccess.java \
   luni/src/main/java/libcore/reflect/AnnotationFactory.java \
   luni/src/main/java/libcore/reflect/AnnotationMember.java \
   luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java \
diff --git a/ojluni/src/main/java/java/io/BufferedReader.java b/ojluni/src/main/java/java/io/BufferedReader.java
index 4d2962c..5a45f4b 100755
--- a/ojluni/src/main/java/java/io/BufferedReader.java
+++ b/ojluni/src/main/java/java/io/BufferedReader.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,13 @@
 package java.io;
 
 
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
 /**
  * Reads text from a character-input stream, buffering characters so as to
  * provide for the efficient reading of characters, arrays, and lines.
@@ -530,4 +537,65 @@
             cb = null;
         }
     }
+
+    /**
+     * Returns a {@code Stream}, the elements of which are lines read from
+     * this {@code BufferedReader}.  The {@link Stream} is lazily populated,
+     * i.e., read only occurs during the
+     * <a href="../util/stream/package-summary.html#StreamOps">terminal
+     * stream operation</a>.
+     *
+     * <p> The reader must not be operated on during the execution of the
+     * terminal stream operation. Otherwise, the result of the terminal stream
+     * operation is undefined.
+     *
+     * <p> After execution of the terminal stream operation there are no
+     * guarantees that the reader will be at a specific position from which to
+     * read the next character or line.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the underlying
+     * {@code BufferedReader}, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the {@code Stream}
+     * method that caused the read to take place. This method will return a
+     * Stream if invoked on a BufferedReader that is closed. Any operation on
+     * that stream that requires reading from the BufferedReader after it is
+     * closed, will cause an UncheckedIOException to be thrown.
+     *
+     * @return a {@code Stream<String>} providing the lines of text
+     *         described by this {@code BufferedReader}
+     *
+     * @since 1.8
+     */
+    public Stream<String> lines() {
+        Iterator<String> iter = new Iterator<String>() {
+            String nextLine = null;
+
+            @Override
+            public boolean hasNext() {
+                if (nextLine != null) {
+                    return true;
+                } else {
+                    try {
+                        nextLine = readLine();
+                        return (nextLine != null);
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                }
+            }
+
+            @Override
+            public String next() {
+                if (nextLine != null || hasNext()) {
+                    String line = nextLine;
+                    nextLine = null;
+                    return line;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+        };
+        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
+                iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
+    }
 }
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 6ba4dc3..3352266 100755
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -202,7 +202,7 @@
  * @see java.io.DataInput
  * @see java.io.ObjectOutputStream
  * @see java.io.Serializable
- * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
+ * @see <a href="{@docRoot}/../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  * @since   JDK1.1
  */
 public class ObjectInputStream
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index 93ccd0c..5e5fbfa 100755
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -37,6 +37,7 @@
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
 import java.io.SerialCallbackContext;
+
 import sun.reflect.misc.ReflectUtil;
 
 /**
@@ -157,7 +158,7 @@
  * @see java.io.ObjectInputStream
  * @see java.io.Serializable
  * @see java.io.Externalizable
- * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
+ * @see <a href="{@docRoot}/../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
  * @since       JDK1.1
  */
 public class ObjectOutputStream
@@ -749,7 +750,8 @@
      */
     public void close() throws IOException {
         flush();
-        clear();
+        // http://b/28159133
+        // clear();
         bout.close();
     }
 
@@ -1798,6 +1800,17 @@
         private final DataOutputStream dout;
 
         /**
+         * Indicates that this stream was closed and that a warning must be logged once if an
+         * attempt is made to write to it and the underlying stream does not throw an exception.
+         *
+         * <p>This will be set back to false when a warning is logged to ensure that the log is not
+         * flooded with warnings.
+         *
+         * http://b/28159133
+         */
+        private boolean warnOnceWhenWriting;
+
+        /**
          * Creates new BlockDataOutputStream on top of given underlying stream.
          * Block data mode is turned off by default.
          */
@@ -1830,6 +1843,25 @@
             return blkmode;
         }
 
+        /**
+         * Warns if the stream has been closed.
+         *
+         * <p>This is called after data has been written to the underlying stream in order to allow
+         * the underlying stream to detect and fail if an attempt is made to write to a closed
+         * stream. That ensures that this will only log a warning if the underlying stream does not
+         * so it will not log unnecessary warnings.
+         */
+        private void warnIfClosed() {
+            if (warnOnceWhenWriting) {
+                System.logW("The app is relying on undefined behavior. Attempting to write to a"
+                        + " closed ObjectOutputStream could produce corrupt output in a future"
+                        + " release of Android.", new IOException("Stream Closed"));
+                // Set back to false so no more messages are logged unless the stream is closed
+                // again.
+                warnOnceWhenWriting = false;
+            }
+        }
+
         /* ----------------- generic output stream methods ----------------- */
         /*
          * The following methods are equivalent to their counterparts in
@@ -1860,6 +1892,7 @@
         public void close() throws IOException {
             flush();
             out.close();
+            warnOnceWhenWriting = true;
         }
 
         /**
@@ -1874,6 +1907,7 @@
             if (!(copy || blkmode)) {           // write directly
                 drain();
                 out.write(b, off, len);
+                warnIfClosed();
                 return;
             }
 
@@ -1895,6 +1929,7 @@
                     len -= wlen;
                 }
             }
+            warnIfClosed();
         }
 
         /**
@@ -1910,6 +1945,7 @@
             }
             out.write(buf, 0, pos);
             pos = 0;
+            warnIfClosed();
         }
 
         /**
@@ -1927,6 +1963,7 @@
                 Bits.putInt(hbuf, 1, len);
                 out.write(hbuf, 0, 5);
             }
+            warnIfClosed();
         }
 
 
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index 6167a9f..1c2df71 100755
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -60,13 +60,13 @@
  * loaded in this Java VM can be found/created using the lookup method.
  *
  * <p>The algorithm to compute the SerialVersionUID is described in
- * <a href="../../../platform/serialization/spec/class.html#4100">Object
+ * <a href="{@docRoot}/../platform/serialization/spec/class.html#4100">Object
  * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
  *
  * @author      Mike Warres
  * @author      Roger Riggs
  * @see ObjectStreamField
- * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
+ * @see <a href="{@docRoot}/../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
  * @since   JDK1.1
  */
 public class ObjectStreamClass implements Serializable {
@@ -2272,6 +2272,32 @@
         return matches;
     }
 
+    // NOTE: The following couple of methods are left here because frameworks such as objenesis
+    // use them.
+    //
+    // **** THESE METHODS WILL BE REMOVED IN A FUTURE ANDROID RELEASE ****.
+    //
+    private static long getConstructorId(Class<?> clazz) {
+        System.logE("WARNING: ObjectStreamClass.getConstructorId(Class<?>) is private API and" +
+                "will be removed in a future Android release.");
+        // NOTE: This method is a stub that returns a fixed value. It's meant to be used
+        // with newInstance(Class<?>, long) and our current implementation of that method ignores
+        // the "constructorId" argument. We return :
+        //
+        // oh one one eight nine nine nine
+        // eight eight one nine nine
+        // nine one one nine seven two five
+        // three
+        //
+        // in all cases.
+        return 1189998819991197253L;
+    }
+    private static Object newInstance(Class<?> clazz, long constructorId) {
+        System.logE("WARNING: ObjectStreamClass.newInstance(Class<?>, long) is private API and" +
+                "will be removed in a future Android release.");
+        return sun.misc.Unsafe.getUnsafe().allocateInstance(clazz);
+    }
+
     /**
      * Removes from the specified map any keys that have been enqueued
      * on the specified reference queue.
diff --git a/ojluni/src/main/java/java/io/UncheckedIOException.java b/ojluni/src/main/java/java/io/UncheckedIOException.java
new file mode 100644
index 0000000..22c43e3
--- /dev/null
+++ b/ojluni/src/main/java/java/io/UncheckedIOException.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.io;
+
+import java.util.Objects;
+
+/**
+ * Wraps an {@link IOException} with an unchecked exception.
+ *
+ * @since   1.8
+ */
+public class UncheckedIOException extends RuntimeException {
+    private static final long serialVersionUID = -8134305061645241065L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   message
+     *          the detail message, can be null
+     * @param   cause
+     *          the {@code IOException}
+     *
+     * @throws  NullPointerException
+     *          if the cause is {@code null}
+     */
+    public UncheckedIOException(String message, IOException cause) {
+        super(message, Objects.requireNonNull(cause));
+    }
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   cause
+     *          the {@code IOException}
+     *
+     * @throws  NullPointerException
+     *          if the cause is {@code null}
+     */
+    public UncheckedIOException(IOException cause) {
+        super(Objects.requireNonNull(cause));
+    }
+
+    /**
+     * Returns the cause of this exception.
+     *
+     * @return  the {@code IOException} which is the cause of this exception.
+     */
+    @Override
+    public IOException getCause() {
+        return (IOException) super.getCause();
+    }
+
+    /**
+     * Called to read the object from a stream.
+     *
+     * @throws  InvalidObjectException
+     *          if the object is invalid or has a cause that is not
+     *          an {@code IOException}
+     */
+    private void readObject(ObjectInputStream s)
+        throws IOException, ClassNotFoundException
+    {
+        s.defaultReadObject();
+        Throwable cause = super.getCause();
+        if (!(cause instanceof IOException))
+            throw new InvalidObjectException("Cause must be an IOException");
+    }
+}
diff --git a/ojluni/src/main/java/java/io/package.html b/ojluni/src/main/java/java/io/package.html
index 1b909ad..72e458b 100755
--- a/ojluni/src/main/java/java/io/package.html
+++ b/ojluni/src/main/java/java/io/package.html
@@ -36,7 +36,7 @@
 
 <h2>Package Specification</h2>
 <ul>
-  <li><a href="../../../platform/serialization/spec/serialTOC.html"> Java Object Serialization Specification </a>
+  <li><a href="{@docRoot}/../platform/serialization/spec/serialTOC.html"> Java Object Serialization Specification </a>
 </ul>
 
 <h2>Related Documentation</h2>
@@ -44,7 +44,7 @@
 For overviews, tutorials, examples, guides, and tool documentation,
 please see:
 <ul>
-  <li><a href="../../../technotes/guides/serialization">Serialization Enhancements</a>
+  <li><a href="{@docRoot}/../technotes/guides/serialization">Serialization Enhancements</a>
 </ul>
 
 @since JDK1.0
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
index e11ae3c..63606b3 100755
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -413,7 +413,7 @@
         if (str == null) str = "null";
         int len = str.length();
         ensureCapacityInternal(count + len);
-        str.getChars(0, len, value, count);
+        str.getCharsNoCheck(0, len, value, count);
         count += len;
         return this;
     }
@@ -478,8 +478,16 @@
                 + s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        for (int i = start, j = count; i < end; i++, j++)
-            value[j] = s.charAt(i);
+        if (s instanceof String) {
+            ((String) s).getCharsNoCheck(start, end, value, count);
+        } else if (s instanceof AbstractStringBuilder) {
+            AbstractStringBuilder other = (AbstractStringBuilder) s;
+            System.arraycopy(other.value, start, value, count, len);
+        } else {
+            for (int i = start, j = count; i < end; i++, j++) {
+                value[j] = s.charAt(i);
+            }
+        }
         count += len;
         return this;
     }
@@ -805,7 +813,7 @@
         ensureCapacityInternal(newCount);
 
         System.arraycopy(value, end, value, start + len, count - end);
-        str.getChars(0, len, value, start);
+        str.getCharsNoCheck(0, len, value, start);
         count = newCount;
         return this;
     }
@@ -978,7 +986,7 @@
         int len = str.length();
         ensureCapacityInternal(count + len);
         System.arraycopy(value, offset, value, offset + len, count - offset);
-        str.getChars(0, len, value, offset);
+        str.getCharsNoCheck(0, len, value, offset);
         count += len;
         return this;
     }
diff --git a/ojluni/src/main/java/java/lang/Boolean.java b/ojluni/src/main/java/java/lang/Boolean.java
index cac469b..f71d666 100755
--- a/ojluni/src/main/java/java/lang/Boolean.java
+++ b/ojluni/src/main/java/java/lang/Boolean.java
@@ -292,4 +292,46 @@
     private static boolean toBoolean(String name) {
         return ((name != null) && name.equalsIgnoreCase("true"));
     }
+
+    /**
+     * Returns the result of applying the logical AND operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the logical AND of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalAnd(boolean a, boolean b) {
+        return a && b;
+    }
+
+    /**
+     * Returns the result of applying the logical OR operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the logical OR of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalOr(boolean a, boolean b) {
+        return a || b;
+    }
+
+    /**
+     * Returns the result of applying the logical XOR operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return  the logical XOR of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalXor(boolean a, boolean b) {
+        return a ^ b;
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/CharSequence.java b/ojluni/src/main/java/java/lang/CharSequence.java
index d9e65a0..7b50d74 100755
--- a/ojluni/src/main/java/java/lang/CharSequence.java
+++ b/ojluni/src/main/java/java/lang/CharSequence.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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,13 @@
 
 package java.lang;
 
+import java.util.NoSuchElementException;
+import java.util.PrimitiveIterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.IntConsumer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
 
 /**
  * A <tt>CharSequence</tt> is a readable sequence of <code>char</code> values. This
@@ -108,4 +115,120 @@
      */
     public String toString();
 
+    /**
+     * Returns a stream of {@code int} zero-extending the {@code char} values
+     * from this sequence.  Any char which maps to a <a
+     * href="{@docRoot}/java/lang/Character.html#unicode">surrogate code
+     * point</a> is passed through uninterpreted.
+     *
+     * <p>If the sequence is mutated while the stream is being read, the
+     * result is undefined.
+     *
+     * @return an IntStream of char values from this sequence
+     * @since 1.8
+     */
+    public default IntStream chars() {
+        class CharIterator implements PrimitiveIterator.OfInt {
+            int cur = 0;
+
+            public boolean hasNext() {
+                return cur < length();
+            }
+
+            public int nextInt() {
+                if (hasNext()) {
+                    return charAt(cur++);
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void forEachRemaining(IntConsumer block) {
+                for (; cur < length(); cur++) {
+                    block.accept(charAt(cur));
+                }
+            }
+        }
+
+        return StreamSupport.intStream(() ->
+                Spliterators.spliterator(
+                        new CharIterator(),
+                        length(),
+                        Spliterator.ORDERED),
+                Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,
+                false);
+    }
+
+    /**
+     * Returns a stream of code point values from this sequence.  Any surrogate
+     * pairs encountered in the sequence are combined as if by {@linkplain
+     * Character#toCodePoint Character.toCodePoint} and the result is passed
+     * to the stream. Any other code units, including ordinary BMP characters,
+     * unpaired surrogates, and undefined code units, are zero-extended to
+     * {@code int} values which are then passed to the stream.
+     *
+     * <p>If the sequence is mutated while the stream is being read, the result
+     * is undefined.
+     *
+     * @return an IntStream of Unicode code points from this sequence
+     * @since 1.8
+     */
+    public default IntStream codePoints() {
+        class CodePointIterator implements PrimitiveIterator.OfInt {
+            int cur = 0;
+
+            @Override
+            public void forEachRemaining(IntConsumer block) {
+                final int length = length();
+                int i = cur;
+                try {
+                    while (i < length) {
+                        char c1 = charAt(i++);
+                        if (!Character.isHighSurrogate(c1) || i >= length) {
+                            block.accept(c1);
+                        } else {
+                            char c2 = charAt(i);
+                            if (Character.isLowSurrogate(c2)) {
+                                i++;
+                                block.accept(Character.toCodePoint(c1, c2));
+                            } else {
+                                block.accept(c1);
+                            }
+                        }
+                    }
+                } finally {
+                    cur = i;
+                }
+            }
+
+            public boolean hasNext() {
+                return cur < length();
+            }
+
+            public int nextInt() {
+                final int length = length();
+
+                if (cur >= length) {
+                    throw new NoSuchElementException();
+                }
+                char c1 = charAt(cur++);
+                if (Character.isHighSurrogate(c1) && cur < length) {
+                    char c2 = charAt(cur);
+                    if (Character.isLowSurrogate(c2)) {
+                        cur++;
+                        return Character.toCodePoint(c1, c2);
+                    }
+                }
+                return c1;
+            }
+        }
+
+        return StreamSupport.intStream(() ->
+                Spliterators.spliteratorUnknownSize(
+                        new CodePointIterator(),
+                        Spliterator.ORDERED),
+                Spliterator.ORDERED,
+                false);
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/Character.java b/ojluni/src/main/java/java/lang/Character.java
index bb69d91..5b9038a 100755
--- a/ojluni/src/main/java/java/lang/Character.java
+++ b/ojluni/src/main/java/java/lang/Character.java
@@ -6458,6 +6458,21 @@
      * @since   1.5
      */
     public static int digit(int codePoint, int radix) {
+        if (radix < MIN_RADIX || radix > MAX_RADIX) {
+            return -1;
+        }
+        if (codePoint < 128) {
+            // Optimized for ASCII
+            int result = -1;
+            if ('0' <= codePoint && codePoint <= '9') {
+                result = codePoint - '0';
+            } else if ('a' <= codePoint && codePoint <= 'z') {
+                result = 10 + (codePoint - 'a');
+            } else if ('A' <= codePoint && codePoint <= 'Z') {
+                result = 10 + (codePoint - 'A');
+            }
+            return result < radix ? result : -1;
+        }
         return digitImpl(codePoint, radix);
     }
 
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index a1c471a..09f949b 100755
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -26,6 +26,7 @@
 
 package java.lang;
 
+import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Member;
@@ -65,8 +66,6 @@
 import java.lang.reflect.AccessibleObject;
 import com.android.dex.Dex;
 import dalvik.system.VMStack;
-import libcore.reflect.AnnotatedElements;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.InternalNames;
 import libcore.reflect.GenericSignatureParser;
 import libcore.reflect.Types;
@@ -753,7 +752,7 @@
      * @since 1.5
      */
     @Override public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
-        String annotationSignature = AnnotationAccess.getSignature(this);
+        String annotationSignature = getSignatureAttribute();
         if (annotationSignature == null) {
             return EmptyArray.TYPE_VARIABLE;
         }
@@ -820,7 +819,7 @@
             return null;
         }
 
-        String annotationSignature = AnnotationAccess.getSignature(this);
+        String annotationSignature = getSignatureAttribute();
         if (annotationSignature != null) {
             GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
             parser.parseForClass(this, annotationSignature);
@@ -981,7 +980,7 @@
         synchronized (Caches.genericInterfaces) {
             result = Caches.genericInterfaces.get(this);
             if (result == null) {
-                String annotationSignature = AnnotationAccess.getSignature(this);
+                String annotationSignature = getSignatureAttribute();
                 if (annotationSignature == null) {
                     result = getInterfaces();
                 } else {
@@ -1052,7 +1051,7 @@
             return Modifier.ABSTRACT | Modifier.FINAL | componentModifiers;
         }
         int JAVA_FLAGS_MASK = 0xffff;
-        int modifiers = AnnotationAccess.getInnerClassFlags(this, accessFlags & JAVA_FLAGS_MASK);
+        int modifiers = this.getInnerClassFlags(accessFlags & JAVA_FLAGS_MASK);
         return modifiers & JAVA_FLAGS_MASK;
     }
 
@@ -1242,8 +1241,7 @@
      * @since 1.5
      */
     public boolean isLocalClass() {
-        return !classNameImpliesTopLevel()
-                && AnnotationAccess.getEnclosingMethodOrConstructor(this) != null
+        return (getEnclosingMethod() != null || getEnclosingConstructor() != null)
                 && !isAnonymousClass();
     }
 
@@ -2421,7 +2419,6 @@
         return false;
     }
 
-
     /**
      * Returns an array containing all the annotations of this class. If there are no annotations
      * then an empty array is returned.
@@ -2473,18 +2470,9 @@
      * @since 1.8
      */
     @Override
-    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
-      return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
     public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
       // Find any associated annotations [directly or repeatably (indirectly) present on this].
-      T[] annotations = AnnotatedElements.getAnnotationsByType(this, annotationClass);
+      T[] annotations = AnnotatedElement.super.getAnnotationsByType(annotationClass);
 
       if (annotations.length != 0) {
         return annotations;
@@ -2534,6 +2522,20 @@
         return annotationType;
     }
 
+    private String getSignatureAttribute() {
+        String[] annotation = getSignatureAnnotation();
+        if (annotation == null) {
+            return null;
+        }
+        StringBuilder result = new StringBuilder();
+        for (String s : annotation) {
+            result.append(s);
+        }
+        return result.toString();
+    }
+
+    private native String[] getSignatureAnnotation();
+
     /**
      * Is this a runtime created proxy class?
      *
diff --git a/ojluni/src/main/java/java/lang/ClassLoader.java b/ojluni/src/main/java/java/lang/ClassLoader.java
index 73ca551..332cbd9 100755
--- a/ojluni/src/main/java/java/lang/ClassLoader.java
+++ b/ojluni/src/main/java/java/lang/ClassLoader.java
@@ -205,6 +205,7 @@
      */
     private static ClassLoader createSystemClassLoader() {
         String classPath = System.getProperty("java.class.path", ".");
+        String librarySearchPath = System.getProperty("java.library.path", "");
 
         // String[] paths = classPath.split(":");
         // URL[] urls = new URL[paths.length];
@@ -220,7 +221,7 @@
         // return new java.net.URLClassLoader(urls, null);
 
         // TODO Make this a java.net.URLClassLoader once we have those?
-        return new PathClassLoader(classPath, BootClassLoader.getInstance());
+        return new PathClassLoader(classPath, librarySearchPath, BootClassLoader.getInstance());
     }
 
     // The packages defined in this class loader.  Each package name is mapped
diff --git a/ojluni/src/main/java/java/lang/Integer.java b/ojluni/src/main/java/java/lang/Integer.java
index fe36907..3dbc2d5 100755
--- a/ojluni/src/main/java/java/lang/Integer.java
+++ b/ojluni/src/main/java/java/lang/Integer.java
@@ -480,7 +480,7 @@
          */
 
         if (s == null) {
-            throw new NumberFormatException("null");
+            throw new NumberFormatException("s == null");
         }
 
         if (radix < Character.MIN_RADIX) {
diff --git a/ojluni/src/main/java/java/lang/JavaLangAccess.java b/ojluni/src/main/java/java/lang/JavaLangAccess.java
index 20d673e..2779c60 100644
--- a/ojluni/src/main/java/java/lang/JavaLangAccess.java
+++ b/ojluni/src/main/java/java/lang/JavaLangAccess.java
@@ -35,13 +35,6 @@
   /**
    * @hide
    */
-  public static int getStringHash32(String string) {
-      return string.hash32();
-  }
-
-  /**
-   * @hide
-   */
   public static <E extends Enum<E>>
           E[] getEnumConstantsShared(Class<E> klass) {
       return klass.getEnumConstantsShared();
diff --git a/ojluni/src/main/java/java/lang/Math.java b/ojluni/src/main/java/java/lang/Math.java
index 0e36ab7..4c82331 100755
--- a/ojluni/src/main/java/java/lang/Math.java
+++ b/ojluni/src/main/java/java/lang/Math.java
@@ -737,6 +737,399 @@
     }
 
     /**
+     * Returns the sum of its arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int addExact(int x, int y) {
+        int r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    /**
+     * Returns the sum of its arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long addExact(long x, long y) {
+        long r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    /**
+     * Returns the difference of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value to subtract from the first
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int subtractExact(int x, int y) {
+        int r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    /**
+     * Returns the difference of the arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value to subtract from the first
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long subtractExact(long x, long y) {
+        long r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int multiplyExact(int x, int y) {
+        long r = (long)x * (long)y;
+        if ((int)r != r) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return (int)r;
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long multiplyExact(long x, long y) {
+        long r = x * y;
+        long ax = Math.abs(x);
+        long ay = Math.abs(y);
+        if (((ax | ay) >>> 31 != 0)) {
+            // Some bits greater than 2^31 that might cause overflow
+            // Check the result using the divide operator
+            // and check for the special case of Long.MIN_VALUE * -1
+           if (((y != 0) && (r / y != x)) ||
+               (x == Long.MIN_VALUE && y == -1)) {
+                throw new ArithmeticException("long overflow");
+            }
+        }
+        return r;
+    }
+
+    /**
+     * Returns the argument incremented by one, throwing an exception if the
+     * result overflows an {@code int}.
+     *
+     * @param a the value to increment
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int incrementExact(int a) {
+        if (a == Integer.MAX_VALUE) {
+            throw new ArithmeticException("integer overflow");
+        }
+
+        return a + 1;
+    }
+
+    /**
+     * Returns the argument incremented by one, throwing an exception if the
+     * result overflows a {@code long}.
+     *
+     * @param a the value to increment
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long incrementExact(long a) {
+        if (a == Long.MAX_VALUE) {
+            throw new ArithmeticException("long overflow");
+        }
+
+        return a + 1L;
+    }
+
+    /**
+     * Returns the argument decremented by one, throwing an exception if the
+     * result overflows an {@code int}.
+     *
+     * @param a the value to decrement
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int decrementExact(int a) {
+        if (a == Integer.MIN_VALUE) {
+            throw new ArithmeticException("integer overflow");
+        }
+
+        return a - 1;
+    }
+
+    /**
+     * Returns the argument decremented by one, throwing an exception if the
+     * result overflows a {@code long}.
+     *
+     * @param a the value to decrement
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long decrementExact(long a) {
+        if (a == Long.MIN_VALUE) {
+            throw new ArithmeticException("long overflow");
+        }
+
+        return a - 1L;
+    }
+
+    /**
+     * Returns the negation of the argument, throwing an exception if the
+     * result overflows an {@code int}.
+     *
+     * @param a the value to negate
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int negateExact(int a) {
+        if (a == Integer.MIN_VALUE) {
+            throw new ArithmeticException("integer overflow");
+        }
+
+        return -a;
+    }
+
+    /**
+     * Returns the negation of the argument, throwing an exception if the
+     * result overflows a {@code long}.
+     *
+     * @param a the value to negate
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @since 1.8
+     */
+    public static long negateExact(long a) {
+        if (a == Long.MIN_VALUE) {
+            throw new ArithmeticException("long overflow");
+        }
+
+        return -a;
+    }
+
+    /**
+     * Returns the value of the {@code long} argument;
+     * throwing an exception if the value overflows an {@code int}.
+     *
+     * @param value the long value
+     * @return the argument as an int
+     * @throws ArithmeticException if the {@code argument} overflows an int
+     * @since 1.8
+     */
+    public static int toIntExact(long value) {
+        if ((int)value != value) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return (int)value;
+    }
+
+    /**
+     * Returns the largest (closest to positive infinity)
+     * {@code int} value that is less than or equal to the algebraic quotient.
+     * There is one special case, if the dividend is the
+     * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
+     * then integer overflow occurs and
+     * the result is equal to the {@code Integer.MIN_VALUE}.
+     * <p>
+     * Normal integer division operates under the round to zero rounding mode
+     * (truncation).  This operation instead acts under the round toward
+     * negative infinity (floor) rounding mode.
+     * The floor rounding mode gives different results than truncation
+     * when the exact result is negative.
+     * <ul>
+     *   <li>If the signs of the arguments are the same, the results of
+     *       {@code floorDiv} and the {@code /} operator are the same.  <br>
+     *       For example, {@code floorDiv(4, 3) == 1} and {@code (4 / 3) == 1}.</li>
+     *   <li>If the signs of the arguments are different,  the quotient is negative and
+     *       {@code floorDiv} returns the integer less than or equal to the quotient
+     *       and the {@code /} operator returns the integer closest to zero.<br>
+     *       For example, {@code floorDiv(-4, 3) == -2},
+     *       whereas {@code (-4 / 3) == -1}.
+     *   </li>
+     * </ul>
+     * <p>
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the largest (closest to positive infinity)
+     * {@code int} value that is less than or equal to the algebraic quotient.
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see #floorMod(int, int)
+     * @see #floor(double)
+     * @since 1.8
+     */
+    public static int floorDiv(int x, int y) {
+        int r = x / y;
+        // if the signs are different and modulo not zero, round down
+        if ((x ^ y) < 0 && (r * y != x)) {
+            r--;
+        }
+        return r;
+    }
+
+    /**
+     * Returns the largest (closest to positive infinity)
+     * {@code long} value that is less than or equal to the algebraic quotient.
+     * There is one special case, if the dividend is the
+     * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
+     * then integer overflow occurs and
+     * the result is equal to the {@code Long.MIN_VALUE}.
+     * <p>
+     * Normal integer division operates under the round to zero rounding mode
+     * (truncation).  This operation instead acts under the round toward
+     * negative infinity (floor) rounding mode.
+     * The floor rounding mode gives different results than truncation
+     * when the exact result is negative.
+     * <p>
+     * For examples, see {@link #floorDiv(int, int)}.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the largest (closest to positive infinity)
+     * {@code long} value that is less than or equal to the algebraic quotient.
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see #floorMod(long, long)
+     * @see #floor(double)
+     * @since 1.8
+     */
+    public static long floorDiv(long x, long y) {
+        long r = x / y;
+        // if the signs are different and modulo not zero, round down
+        if ((x ^ y) < 0 && (r * y != x)) {
+            r--;
+        }
+        return r;
+    }
+
+    /**
+     * Returns the floor modulus of the {@code int} arguments.
+     * <p>
+     * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+     * has the same sign as the divisor {@code y}, and
+     * is in the range of {@code -abs(y) < r < +abs(y)}.
+     *
+     * <p>
+     * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+     * <ul>
+     *   <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+     * </ul>
+     * <p>
+     * The difference in values between {@code floorMod} and
+     * the {@code %} operator is due to the difference between
+     * {@code floorDiv} that returns the integer less than or equal to the quotient
+     * and the {@code /} operator that returns the integer closest to zero.
+     * <p>
+     * Examples:
+     * <ul>
+     *   <li>If the signs of the arguments are the same, the results
+     *       of {@code floorMod} and the {@code %} operator are the same.  <br>
+     *       <ul>
+     *       <li>{@code floorMod(4, 3) == 1}; &nbsp; and {@code (4 % 3) == 1}</li>
+     *       </ul>
+     *   <li>If the signs of the arguments are different, the results differ from the {@code %} operator.<br>
+     *      <ul>
+     *      <li>{@code floorMod(+4, -3) == -2}; &nbsp; and {@code (+4 % -3) == +1} </li>
+     *      <li>{@code floorMod(-4, +3) == +2}; &nbsp; and {@code (-4 % +3) == -1} </li>
+     *      <li>{@code floorMod(-4, -3) == -1}; &nbsp; and {@code (-4 % -3) == -1 } </li>
+     *      </ul>
+     *   </li>
+     * </ul>
+     * <p>
+     * If the signs of arguments are unknown and a positive modulus
+     * is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see #floorDiv(int, int)
+     * @since 1.8
+     */
+    public static int floorMod(int x, int y) {
+        int r = x - floorDiv(x, y) * y;
+        return r;
+    }
+
+    /**
+     * Returns the floor modulus of the {@code long} arguments.
+     * <p>
+     * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+     * has the same sign as the divisor {@code y}, and
+     * is in the range of {@code -abs(y) < r < +abs(y)}.
+     *
+     * <p>
+     * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+     * <ul>
+     *   <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+     * </ul>
+     * <p>
+     * For examples, see {@link #floorMod(int, int)}.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see #floorDiv(long, long)
+     * @since 1.8
+     */
+    public static long floorMod(long x, long y) {
+        return x - floorDiv(x, y) * y;
+    }
+
+    /**
      * Returns the absolute value of an {@code int} value.
      * If the argument is not negative, the argument is returned.
      * If the argument is negative, the negation of the argument is returned.
@@ -1462,7 +1855,79 @@
     public static float nextUp(float f) {
         return sun.misc.FpUtils.nextUp(f);
     }
+    /**
+     * Returns the floating-point value adjacent to {@code d} in
+     * the direction of negative infinity.  This method is
+     * semantically equivalent to {@code nextAfter(d,
+     * Double.NEGATIVE_INFINITY)}; however, a
+     * {@code nextDown} implementation may run faster than its
+     * equivalent {@code nextAfter} call.
+     *
+     * <p>Special Cases:
+     * <ul>
+     * <li> If the argument is NaN, the result is NaN.
+     *
+     * <li> If the argument is negative infinity, the result is
+     * negative infinity.
+     *
+     * <li> If the argument is zero, the result is
+     * {@code -Double.MIN_VALUE}
+     *
+     * </ul>
+     *
+     * @param d  starting floating-point value
+     * @return The adjacent floating-point value closer to negative
+     * infinity.
+     * @since 1.8
+     */
+    public static double nextDown(double d) {
+        if (Double.isNaN(d) || d == Double.NEGATIVE_INFINITY)
+            return d;
+        else {
+            if (d == 0.0)
+                return -Double.MIN_VALUE;
+            else
+                return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
+                                               ((d > 0.0d)?-1L:+1L));
+        }
+    }
 
+    /**
+     * Returns the floating-point value adjacent to {@code f} in
+     * the direction of negative infinity.  This method is
+     * semantically equivalent to {@code nextAfter(f,
+     * Float.NEGATIVE_INFINITY)}; however, a
+     * {@code nextDown} implementation may run faster than its
+     * equivalent {@code nextAfter} call.
+     *
+     * <p>Special Cases:
+     * <ul>
+     * <li> If the argument is NaN, the result is NaN.
+     *
+     * <li> If the argument is negative infinity, the result is
+     * negative infinity.
+     *
+     * <li> If the argument is zero, the result is
+     * {@code -Float.MIN_VALUE}
+     *
+     * </ul>
+     *
+     * @param f  starting floating-point value
+     * @return The adjacent floating-point value closer to negative
+     * infinity.
+     * @since 1.8
+     */
+    public static float nextDown(float f) {
+        if (Float.isNaN(f) || f == Float.NEGATIVE_INFINITY)
+            return f;
+        else {
+            if (f == 0.0f)
+                return -Float.MIN_VALUE;
+            else
+                return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
+                                            ((f > 0.0f)?-1:+1));
+        }
+    }
 
     /**
      * Return {@code d} &times;
diff --git a/ojluni/src/main/java/java/lang/Package.java b/ojluni/src/main/java/java/lang/Package.java
index 984317b..a4777c5 100755
--- a/ojluni/src/main/java/java/lang/Package.java
+++ b/ojluni/src/main/java/java/lang/Package.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 package java.lang;
 
+import java.lang.reflect.AnnotatedElement;
 import java.io.InputStream;
 import java.util.Enumeration;
 
@@ -48,12 +49,11 @@
 import java.util.HashMap;
 import java.util.Iterator;
 
-import java.lang.annotation.Annotation;
 import sun.net.www.ParseUtil;
 import sun.reflect.CallerSensitive;
 import dalvik.system.VMStack;
 
-import libcore.reflect.AnnotatedElements;
+import java.lang.annotation.Annotation;
 
 /**
  * {@code Package} objects contain version information
@@ -357,17 +357,25 @@
      * @return the string representation of the package.
      */
     public String toString() {
-        String spec = specTitle;
-        String ver =  specVersion;
-        if (spec != null && spec.length() > 0)
-            spec = ", " + spec;
-        else
-            spec = "";
-        if (ver != null && ver.length() > 0)
-            ver = ", version " + ver;
-        else
-            ver = "";
-        return "package " + pkgName + spec + ver;
+        // Android changed: Several apps try to parse the output of toString(). This is a really
+        // bad idea - especially when there's a Package.getName() function as well as a
+        // Class.getName() function that can be used instead.
+        //
+        // *** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ***
+        //
+        // String spec = specTitle;
+        // String ver =  specVersion;
+        // if (spec != null && spec.length() > 0)
+        //     spec = ", " + spec;
+        // else
+        //     spec = "";
+        // if (ver != null && ver.length() > 0)
+        //     ver = ", version " + ver;
+        // else
+        //     ver = "";
+        // return "package " + pkgName + spec + ver;
+
+        return "package " + pkgName;
     }
 
     private Class<?> getPackageInfo() {
@@ -393,11 +401,11 @@
 
     /**
      * @throws NullPointerException {@inheritDoc}
-     * @since 1.5
+     * @since 1.8
      */
-    public boolean isAnnotationPresent(
-        Class<? extends Annotation> annotationClass) {
-        return getPackageInfo().isAnnotationPresent(annotationClass);
+    @Override
+    public  <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
+        return getPackageInfo().getAnnotationsByType(annotationClass);
     }
 
     /**
@@ -408,6 +416,24 @@
     }
 
     /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    @Override
+    public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
+        return getPackageInfo().getDeclaredAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    @Override
+    public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
+        return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
+    }
+
+    /**
      * @since 1.5
      */
     public Annotation[] getDeclaredAnnotations()  {
@@ -415,32 +441,6 @@
     }
 
     /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
-      return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
-      return AnnotatedElements.getAnnotationsByType(this, annotationClass);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
-      return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
-    }
-    /**
      * Construct a package instance with the specified version
      * information.
      * @param pkgName the name of the package
diff --git a/ojluni/src/main/java/java/lang/StrictMath.java b/ojluni/src/main/java/java/lang/StrictMath.java
index 23978ea..3023fc0 100755
--- a/ojluni/src/main/java/java/lang/StrictMath.java
+++ b/ojluni/src/main/java/java/lang/StrictMath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -696,6 +696,211 @@
     }
 
     /**
+     * Returns the sum of its arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#addExact(int,int)
+     * @since 1.8
+     */
+    public static int addExact(int x, int y) {
+        return Math.addExact(x, y);
+    }
+
+    /**
+     * Returns the sum of its arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#addExact(long,long)
+     * @since 1.8
+     */
+    public static long addExact(long x, long y) {
+        return Math.addExact(x, y);
+    }
+
+    /**
+     * Returns the difference of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value to subtract from the first
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#subtractExact(int,int)
+     * @since 1.8
+     */
+    public static int subtractExact(int x, int y) {
+        return Math.subtractExact(x, y);
+    }
+
+    /**
+     * Returns the difference of the arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value to subtract from the first
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#subtractExact(long,long)
+     * @since 1.8
+     */
+    public static long subtractExact(long x, long y) {
+        return Math.subtractExact(x, y);
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#multiplyExact(int,int)
+     * @since 1.8
+     */
+    public static int multiplyExact(int x, int y) {
+        return Math.multiplyExact(x, y);
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#multiplyExact(long,long)
+     * @since 1.8
+     */
+    public static long multiplyExact(long x, long y) {
+        return Math.multiplyExact(x, y);
+    }
+
+    /**
+     * Returns the value of the {@code long} argument;
+     * throwing an exception if the value overflows an {@code int}.
+     *
+     * @param value the long value
+     * @return the argument as an int
+     * @throws ArithmeticException if the {@code argument} overflows an int
+     * @see Math#toIntExact(long)
+     * @since 1.8
+     */
+    public static int toIntExact(long value) {
+        return Math.toIntExact(value);
+    }
+
+    /**
+     * Returns the largest (closest to positive infinity)
+     * {@code int} value that is less than or equal to the algebraic quotient.
+     * There is one special case, if the dividend is the
+     * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
+     * then integer overflow occurs and
+     * the result is equal to the {@code Integer.MIN_VALUE}.
+     * <p>
+     * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
+     * a comparison to the integer division {@code /} operator.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the largest (closest to positive infinity)
+     * {@code int} value that is less than or equal to the algebraic quotient.
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see Math#floorDiv(int, int)
+     * @see Math#floor(double)
+     * @since 1.8
+     */
+    public static int floorDiv(int x, int y) {
+        return Math.floorDiv(x, y);
+    }
+
+    /**
+     * Returns the largest (closest to positive infinity)
+     * {@code long} value that is less than or equal to the algebraic quotient.
+     * There is one special case, if the dividend is the
+     * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
+     * then integer overflow occurs and
+     * the result is equal to the {@code Long.MIN_VALUE}.
+     * <p>
+     * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
+     * a comparison to the integer division {@code /} operator.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the largest (closest to positive infinity)
+     * {@code long} value that is less than or equal to the algebraic quotient.
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see Math#floorDiv(long, long)
+     * @see Math#floor(double)
+     * @since 1.8
+     */
+    public static long floorDiv(long x, long y) {
+        return Math.floorDiv(x, y);
+    }
+
+    /**
+     * Returns the floor modulus of the {@code int} arguments.
+     * <p>
+     * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+     * has the same sign as the divisor {@code y}, and
+     * is in the range of {@code -abs(y) < r < +abs(y)}.
+     * <p>
+     * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+     * <ul>
+     *   <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+     * </ul>
+     * <p>
+     * See {@link Math#floorMod(int, int) Math.floorMod} for examples and
+     * a comparison to the {@code %} operator.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see Math#floorMod(int, int)
+     * @see StrictMath#floorDiv(int, int)
+     * @since 1.8
+     */
+    public static int floorMod(int x, int y) {
+        return Math.floorMod(x , y);
+    }
+    /**
+     * Returns the floor modulus of the {@code long} arguments.
+     * <p>
+     * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+     * has the same sign as the divisor {@code y}, and
+     * is in the range of {@code -abs(y) < r < +abs(y)}.
+     * <p>
+     * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+     * <ul>
+     *   <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+     * </ul>
+     * <p>
+     * See {@link Math#floorMod(int, int) Math.floorMod} for examples and
+     * a comparison to the {@code %} operator.
+     *
+     * @param x the dividend
+     * @param y the divisor
+     * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+     * @throws ArithmeticException if the divisor {@code y} is zero
+     * @see Math#floorMod(long, long)
+     * @see StrictMath#floorDiv(long, long)
+     * @since 1.8
+     */
+    public static long floorMod(long x, long y) {
+        return Math.floorMod(x, y);
+    }
+
+    /**
      * Returns the absolute value of an {@code int} value..
      * If the argument is not negative, the argument is returned.
      * If the argument is negative, the negation of the argument is returned.
@@ -1397,6 +1602,63 @@
         return sun.misc.FpUtils.nextUp(f);
     }
 
+    /**
+     * Returns the floating-point value adjacent to {@code d} in
+     * the direction of negative infinity.  This method is
+     * semantically equivalent to {@code nextAfter(d,
+     * Double.NEGATIVE_INFINITY)}; however, a
+     * {@code nextDown} implementation may run faster than its
+     * equivalent {@code nextAfter} call.
+     *
+     * <p>Special Cases:
+     * <ul>
+     * <li> If the argument is NaN, the result is NaN.
+     *
+     * <li> If the argument is negative infinity, the result is
+     * negative infinity.
+     *
+     * <li> If the argument is zero, the result is
+     * {@code -Double.MIN_VALUE}
+     *
+     * </ul>
+     *
+     * @param d  starting floating-point value
+     * @return The adjacent floating-point value closer to negative
+     * infinity.
+     * @since 1.8
+     */
+    public static double nextDown(double d) {
+        return Math.nextDown(d);
+    }
+
+    /**
+     * Returns the floating-point value adjacent to {@code f} in
+     * the direction of negative infinity.  This method is
+     * semantically equivalent to {@code nextAfter(f,
+     * Float.NEGATIVE_INFINITY)}; however, a
+     * {@code nextDown} implementation may run faster than its
+     * equivalent {@code nextAfter} call.
+     *
+     * <p>Special Cases:
+     * <ul>
+     * <li> If the argument is NaN, the result is NaN.
+     *
+     * <li> If the argument is negative infinity, the result is
+     * negative infinity.
+     *
+     * <li> If the argument is zero, the result is
+     * {@code -Float.MIN_VALUE}
+     *
+     * </ul>
+     *
+     * @param f  starting floating-point value
+     * @return The adjacent floating-point value closer to negative
+     * infinity.
+     * @since 1.8
+     */
+    public static float nextDown(float f) {
+        return Math.nextDown(f);
+    }
 
     /**
      * Return {@code d} &times;
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 5023da8..8a83df9 100755
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -37,6 +37,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+
+import libcore.util.CharsetUtils;
 import libcore.util.EmptyArray;
 
 /**
@@ -857,7 +859,21 @@
      * @since  1.6
      */
     public byte[] getBytes(Charset charset) {
-        if (charset == null) throw new NullPointerException();
+        if (charset == null) {
+            throw new NullPointerException("charset == null");
+        }
+
+        final String name = charset.name();
+        if ("UTF-8".equals(name)) {
+            return CharsetUtils.toUtf8Bytes(this, 0, count);
+        } else if ("ISO-8859-1".equals(name)) {
+            return CharsetUtils.toIsoLatin1Bytes(this, 0, count);
+        } else if ("US-ASCII".equals(name)) {
+            return CharsetUtils.toAsciiBytes(this, 0, count);
+        } else if ("UTF-16BE".equals(name)) {
+            return CharsetUtils.toBigEndianUtf16Bytes(this, 0, count);
+        }
+
         return StringCoding.encode(charset, this);
     }
 
@@ -1595,11 +1611,7 @@
      * is the string being searched for.
      *
      * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
      * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
      * @param   fromIndex    the index to begin searching from.
      */
     static int indexOf(String source,
@@ -1998,29 +2010,18 @@
      *          occurrence of <code>oldChar</code> with <code>newChar</code>.
      */
     public String replace(char oldChar, char newChar) {
+        String replaced = this;
         if (oldChar != newChar) {
-            int len = count;
-            int i = -1;
-
-            while (++i < len) {
+            for (int i = 0; i < count; ++i) {
                 if (charAt(i) == oldChar) {
-                    break;
+                    if (replaced == this) {
+                        replaced = StringFactory.newStringFromString(this);
+                    }
+                    replaced.setCharAt(i, newChar);
                 }
             }
-            if (i < len) {
-                char buf[] = new char[len];
-                for (int j = 0; j < i; j++) {
-                    buf[j] = charAt(j);
-                }
-                while (i < len) {
-                    char c = charAt(i);
-                    buf[i] = (c == oldChar) ? newChar : c;
-                    i++;
-                }
-                return StringFactory.newStringFromChars(buf);
-            }
         }
-        return this;
+        return replaced;
     }
 
     /**
@@ -2167,8 +2168,60 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
-                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
+        if (target == null) {
+            throw new NullPointerException("target == null");
+        }
+
+        if (replacement == null) {
+            throw new NullPointerException("replacement == null");
+        }
+
+        String replacementStr = replacement.toString();
+        String targetStr = target.toString();
+
+        // Special case when target == "". This is a pretty nonsensical transformation and nobody
+        // should be hitting this.
+        //
+        // See commit 870b23b3febc85 and http://code.google.com/p/android/issues/detail?id=8807
+        // An empty target is inserted at the start of the string, the end of the string and
+        // between all characters.
+        if (targetStr.isEmpty()) {
+            // Note that overallocates by |replacement.size()| if |this| is the empty string, but
+            // that should be a rare case within an already nonsensical case.
+            StringBuilder sb = new StringBuilder(replacementStr.length() * (count + 2) + count);
+            sb.append(replacementStr);
+            for (int i = 0; i < count; ++i) {
+                sb.append(charAt(i));
+                sb.append(replacementStr);
+            }
+
+            return sb.toString();
+        }
+
+        // This is the "regular" case.
+        int lastMatch = 0;
+        StringBuilder sb = null;
+        for (;;) {
+            int currentMatch = indexOf(this, targetStr, lastMatch);
+            if (currentMatch == -1) {
+                break;
+            }
+
+            if (sb == null) {
+                sb = new StringBuilder(count);
+            }
+
+            sb.append(this, lastMatch, currentMatch);
+            sb.append(replacementStr);
+            lastMatch = currentMatch + targetStr.count;
+        }
+
+        if (sb != null) {
+            sb.append(this, lastMatch, count);
+            return sb.toString();
+        } else {
+            return this;
+        }
     }
 
     /**
@@ -2252,61 +2305,12 @@
      * @spec JSR-51
      */
     public String[] split(String regex, int limit) {
-        /* fastpath if the regex is a
-         (1)one-char String and this character is not one of the
-            RegEx's meta characters ".$|()[{^?*+\\", or
-         (2)two-char String and the first char is the backslash and
-            the second is not the ascii digit or ascii letter.
-         */
-        char ch = 0;
-        if (((regex.count == 1 &&
-             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
-             (regex.length() == 2 &&
-              regex.charAt(0) == '\\' &&
-              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
-              ((ch-'a')|('z'-ch)) < 0 &&
-              ((ch-'A')|('Z'-ch)) < 0)) &&
-            (ch < Character.MIN_HIGH_SURROGATE ||
-             ch > Character.MAX_LOW_SURROGATE))
-        {
-            int off = 0;
-            int next = 0;
-
-            int sepCount = 0;
-            while (sepCount != limit-1 && (next = indexOf(ch, off)) != -1) {
-              sepCount += 1;
-              off = next + 1;
-            }
-            // If no match was found, return this
-            if (off == 0) {
-                return new String[]{this};
-            }
-
-            int end = count;
-
-            // Remove trailing separators
-            if (limit == 0 && off == end) {
-                if (sepCount == end) {
-                    return EmptyArray.STRING;
-                }
-                while (charAt(off - 1) == ch) {
-                    --off;
-                }
-                sepCount -= count - off;
-                end = off;
-            }
-
-            off = 0;
-            String[] result = new String[sepCount + 1];
-            for (int i = 0;i < sepCount; i++) {
-                next = indexOf(ch, off);
-                result[i] = substring(off, next);
-                off = next + 1;
-            }
-
-            result[sepCount] = substring(off, end);
-            return result;
+        // Try fast splitting without allocating Pattern object
+        String[] fast = Pattern.fastSplit(regex, this, limit);
+        if (fast != null) {
+            return fast;
         }
+
         return Pattern.compile(regex).split(this, limit);
     }
 
@@ -2838,74 +2842,4 @@
      *          guaranteed to be from a pool of unique strings.
      */
     public native String intern();
-
-    /**
-     * Seed value used for each alternative hash calculated.
-     */
-    private static int HASHING_SEED;
-
-    private static int getHashingSeed() {
-        long nanos = System.nanoTime();
-        long now = System.currentTimeMillis();
-        int SEED_MATERIAL[] = {
-                System.identityHashCode(String.class),
-                System.identityHashCode(System.class),
-                (int) (nanos >>> 32),
-                (int) nanos,
-                (int) (now >>> 32),
-                (int) now,
-                (int) (System.nanoTime() >>> 2)
-        };
-
-        // Use murmur3 to scramble the seeding material.
-        // Inline implementation to avoid loading classes
-        int h1 = 0;
-
-        // body
-        for (int k1 : SEED_MATERIAL) {
-            k1 *= 0xcc9e2d51;
-            k1 = (k1 << 15) | (k1 >>> 17);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = (h1 << 13) | (h1 >>> 19);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail (always empty, as body is always 32-bit chunks)
-
-        // finalization
-
-        h1 ^= SEED_MATERIAL.length * 4;
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        HASHING_SEED = h1;
-        return HASHING_SEED;
-    }
-
-    /**
-     * Cached value of the alternative hashing algorithm result
-     */
-    // TODO(narayan): This adds a 4 byte overhead to all string objects. Is it
-    // worth the trouble ? hash32() below has been changed not to cache the calculated
-    // hash. This is likely to be expensive and needs further analysis.
-    //
-    // private transient int hash32 = 0;
-
-    /**
-     * Calculates a 32-bit hash value for this string.
-     *
-     * @return a 32-bit hash value for this string.
-     */
-    int hash32() {
-        char[] value = new char[count];
-        getChars(0, count, value, 0);
-        return sun.misc.Hashing.murmur3_32(getHashingSeed(), value, 0, count);
-    }
 }
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index bd00e50..03b6bd2 100755
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -938,19 +938,10 @@
         VMRuntime runtime = VMRuntime.getRuntime();
         Properties p = new Properties();
 
-        String projectUrl = "http://www.android.com/";
-        String projectName = "The Android Project";
-
+        // Set non-static properties.
         p.put("java.boot.class.path", runtime.bootClassPath());
         p.put("java.class.path", runtime.classPath());
 
-        // None of these four are meaningful on Android, but these keys are guaranteed
-        // to be present for System.getProperty. For java.class.version, we use the maximum
-        // class file version that dx currently supports.
-        p.put("java.class.version", "50.0");
-        p.put("java.compiler", "");
-        p.put("java.ext.dirs", "");
-
         // TODO: does this make any sense? Should we just leave java.home unset?
         String javaHome = getenv("JAVA_HOME");
         if (javaHome == null) {
@@ -958,25 +949,8 @@
         }
         p.put("java.home", javaHome);
 
-        p.put("java.specification.name", "Dalvik Core Library");
-        p.put("java.specification.vendor", projectName);
-        p.put("java.specification.version", "0.9");
-
-        p.put("java.vendor", projectName);
-        p.put("java.vendor.url", projectUrl);
-        p.put("java.vm.name", "Dalvik");
-        p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification");
-        p.put("java.vm.specification.vendor", projectName);
-        p.put("java.vm.specification.version", "0.9");
-        p.put("java.vm.vendor", projectName);
         p.put("java.vm.version", runtime.vmVersion());
 
-        p.put("java.vm.vendor.url", projectUrl);
-
-        p.put("java.net.preferIPv6Addresses", "false");
-
-        p.put("file.encoding", "UTF-8");
-
         try {
             StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid());
             p.put("user.name", passwd.pw_name);
@@ -986,7 +960,11 @@
 
         StructUtsname info = Libcore.os.uname();
         p.put("os.arch", info.machine);
-        p.put("os.name", info.sysname);
+        if (p.get("os.name") != null && !p.get("os.name").equals(info.sysname)) {
+            logE("Wrong compile-time assumption for os.name: " + p.get("os.name") + " vs " +
+                    info.sysname);
+            p.put("os.name", info.sysname);
+        }
         p.put("os.version", info.release);
 
         // Undocumented Android-only properties.
@@ -1003,24 +981,24 @@
         parsePropertyAssignments(p, specialProperties());
 
         // Override built-in properties with settings from the command line.
+        // Note: it is not possible to override hardcoded values.
         parsePropertyAssignments(p, runtime.properties());
 
-        if (p.containsKey("file.separator")) {
-            logE("Ignoring command line argument: -Dfile.separator");
-        }
 
-        if (p.containsKey("line.separator")) {
-            logE("Ignoring command line argument: -Dline.separator");
+        // Set static hardcoded properties.
+        // These come last, as they must be guaranteed to agree with what a backend compiler
+        // may assume when compiling the boot image on Android.
+        for (String[] pair : AndroidHardcodedSystemProperties.STATIC_PROPERTIES) {
+            if (p.containsKey(pair[0])) {
+                logE("Ignoring command line argument: -D" + pair[0]);
+            }
+            if (pair[1] == null) {
+                p.remove(pair[0]);
+            } else {
+                p.put(pair[0], pair[1]);
+            }
         }
 
-        if (p.containsKey("path.separator")) {
-            logE("Ignoring command line argument: -Dpath.separator");
-        }
-
-        p.put("file.separator", "/");
-        p.put("line.separator", "\n");
-        p.put("path.separator", ":");
-
         return p;
     }
 
@@ -1094,92 +1072,54 @@
 
     /**
      * Determines the current system properties.
-     * <p>
-     * First, if there is a security manager, its
-     * <code>checkPropertiesAccess</code> method is called with no
-     * arguments. This may result in a security exception.
-     * <p>
-     * The current set of system properties for use by the
-     * {@link #getProperty(String)} method is returned as a
-     * <code>Properties</code> object. If there is no current set of
-     * system properties, a set of system properties is first created and
-     * initialized. This set of system properties always includes values
-     * for the following keys:
-     * <table summary="Shows property keys and associated values">
-     * <tr><th>Key</th>
-     *     <th>Description of Associated Value</th></tr>
-     * <tr><td><code>java.version</code></td>
-     *     <td>Java Runtime Environment version</td></tr>
-     * <tr><td><code>java.vendor</code></td>
-     *     <td>Java Runtime Environment vendor</td></tr
-     * <tr><td><code>java.vendor.url</code></td>
-     *     <td>Java vendor URL</td></tr>
-     * <tr><td><code>java.home</code></td>
-     *     <td>Java installation directory</td></tr>
-     * <tr><td><code>java.vm.specification.version</code></td>
-     *     <td>Java Virtual Machine specification version</td></tr>
-     * <tr><td><code>java.vm.specification.vendor</code></td>
-     *     <td>Java Virtual Machine specification vendor</td></tr>
-     * <tr><td><code>java.vm.specification.name</code></td>
-     *     <td>Java Virtual Machine specification name</td></tr>
-     * <tr><td><code>java.vm.version</code></td>
-     *     <td>Java Virtual Machine implementation version</td></tr>
-     * <tr><td><code>java.vm.vendor</code></td>
-     *     <td>Java Virtual Machine implementation vendor</td></tr>
-     * <tr><td><code>java.vm.name</code></td>
-     *     <td>Java Virtual Machine implementation name</td></tr>
-     * <tr><td><code>java.specification.version</code></td>
-     *     <td>Java Runtime Environment specification  version</td></tr>
-     * <tr><td><code>java.specification.vendor</code></td>
-     *     <td>Java Runtime Environment specification  vendor</td></tr>
-     * <tr><td><code>java.specification.name</code></td>
-     *     <td>Java Runtime Environment specification  name</td></tr>
-     * <tr><td><code>java.class.version</code></td>
-     *     <td>Java class format version number</td></tr>
-     * <tr><td><code>java.class.path</code></td>
-     *     <td>Java class path</td></tr>
-     * <tr><td><code>java.library.path</code></td>
-     *     <td>List of paths to search when loading libraries</td></tr>
-     * <tr><td><code>java.io.tmpdir</code></td>
-     *     <td>Default temp file path</td></tr>
-     * <tr><td><code>java.compiler</code></td>
-     *     <td>Name of JIT compiler to use</td></tr>
-     * <tr><td><code>java.ext.dirs</code></td>
-     *     <td>Path of extension directory or directories</td></tr>
-     * <tr><td><code>os.name</code></td>
-     *     <td>Operating system name</td></tr>
-     * <tr><td><code>os.arch</code></td>
-     *     <td>Operating system architecture</td></tr>
-     * <tr><td><code>os.version</code></td>
-     *     <td>Operating system version</td></tr>
-     * <tr><td><code>file.separator</code></td>
-     *     <td>File separator ("/" on UNIX)</td></tr>
-     * <tr><td><code>path.separator</code></td>
-     *     <td>Path separator (":" on UNIX)</td></tr>
-     * <tr><td><code>line.separator</code></td>
-     *     <td>Line separator ("\n" on UNIX)</td></tr>
-     * <tr><td><code>user.name</code></td>
-     *     <td>User's account name</td></tr>
-     * <tr><td><code>user.home</code></td>
-     *     <td>User's home directory</td></tr>
-     * <tr><td><code>user.dir</code></td>
-     *     <td>User's current working directory</td></tr>
+     *
+     *
+     * <p>The following properties are always provided by the Dalvik VM:</p>
+     * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+     * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+     *     <td><b>Name</b></td>        <td><b>Meaning</b></td>                    <td><b>Example</b></td></tr>
+     * <tr><td>file.separator</td>     <td>{@link java.io.File#separator}</td>    <td>{@code /}</td></tr>
+     *
+     * <tr><td>java.class.path</td>    <td>System class path</td>                 <td>{@code .}</td></tr>
+     * <tr><td>java.class.version</td> <td>(Not useful on Android)</td>           <td>{@code 50.0}</td></tr>
+     * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
+     * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
+     * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
+     * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
+     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /vendor/lib:/system/lib}</td></tr>
+     * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
+     * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
+     * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
+     *
+     * <tr><td>java.specification.version</td>    <td>VM libraries version</td>        <td>{@code 0.9}</td></tr>
+     * <tr><td>java.specification.vendor</td>     <td>VM libraries vendor</td>         <td>{@code The Android Project}</td></tr>
+     * <tr><td>java.specification.name</td>       <td>VM libraries name</td>           <td>{@code Dalvik Core Library}</td></tr>
+     * <tr><td>java.vm.version</td>               <td>VM implementation version</td>   <td>{@code 1.2.0}</td></tr>
+     * <tr><td>java.vm.vendor</td>                <td>VM implementation vendor</td>    <td>{@code The Android Project}</td></tr>
+     * <tr><td>java.vm.name</td>                  <td>VM implementation name</td>      <td>{@code Dalvik}</td></tr>
+     * <tr><td>java.vm.specification.version</td> <td>VM specification version</td>    <td>{@code 0.9}</td></tr>
+     * <tr><td>java.vm.specification.vendor</td>  <td>VM specification vendor</td>     <td>{@code The Android Project}</td></tr>
+     * <tr><td>java.vm.specification.name</td>    <td>VM specification name</td>       <td>{@code Dalvik Virtual Machine Specification}</td></tr>
+     *
+     * <tr><td>line.separator</td>     <td>The system line separator</td>         <td>{@code \n}</td></tr>
+     *
+     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
+     * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
+     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
+     *
+     * <tr><td>path.separator</td>     <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
+     *
+     * <tr><td>user.dir</td>           <td>Base of non-absolute paths</td>        <td>{@code /}</td></tr>
+     * <tr><td>user.home</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
+     * <tr><td>user.name</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
+     *
      * </table>
      * <p>
      * Multiple paths in a system property value are separated by the path
      * separator character of the platform.
-     * <p>
-     * Note that even if the security manager does not permit the
-     * <code>getProperties</code> operation, it may choose to permit the
-     * {@link #getProperty(String)} operation.
      *
      * @return     the system properties
-     * @exception  SecurityException  if a security manager exists and its
-     *             <code>checkPropertiesAccess</code> method doesn't allow access
-     *              to the system properties.
      * @see        #setProperties
-     * @see        java.lang.SecurityException
-     * @see        java.lang.SecurityManager#checkPropertiesAccess()
      * @see        java.util.Properties
      */
     public static Properties getProperties() {
@@ -1220,11 +1160,7 @@
 
     /**
      * Gets the system property indicated by the specified key.
-     * <p>
-     * First, if there is a security manager, its
-     * <code>checkPropertyAccess</code> method is called with the key as
-     * its argument. This may result in a SecurityException.
-     * <p>
+     *
      * If there is no current set of system properties, a set of system
      * properties is first created and initialized in the same manner as
      * for the <code>getProperties</code> method.
@@ -1233,15 +1169,10 @@
      * @return     the string value of the system property,
      *             or <code>null</code> if there is no property with that key.
      *
-     * @exception  SecurityException  if a security manager exists and its
-     *             <code>checkPropertyAccess</code> method doesn't allow
-     *              access to the specified system property.
      * @exception  NullPointerException if <code>key</code> is
      *             <code>null</code>.
      * @exception  IllegalArgumentException if <code>key</code> is empty.
      * @see        #setProperty
-     * @see        java.lang.SecurityException
-     * @see        java.lang.SecurityManager#checkPropertyAccess(java.lang.String)
      * @see        java.lang.System#getProperties()
      */
     public static String getProperty(String key) {
@@ -1266,14 +1197,10 @@
      * @return     the string value of the system property,
      *             or the default value if there is no property with that key.
      *
-     * @exception  SecurityException  if a security manager exists and its
-     *             <code>checkPropertyAccess</code> method doesn't allow
-     *             access to the specified system property.
      * @exception  NullPointerException if <code>key</code> is
      *             <code>null</code>.
      * @exception  IllegalArgumentException if <code>key</code> is empty.
      * @see        #setProperty
-     * @see        java.lang.SecurityManager#checkPropertyAccess(java.lang.String)
      * @see        java.lang.System#getProperties()
      */
     public static String getProperty(String key, String def) {
@@ -1284,31 +1211,18 @@
 
     /**
      * Sets the system property indicated by the specified key.
-     * <p>
-     * First, if a security manager exists, its
-     * <code>SecurityManager.checkPermission</code> method
-     * is called with a <code>PropertyPermission(key, "write")</code>
-     * permission. This may result in a SecurityException being thrown.
-     * If no exception is thrown, the specified property is set to the given
-     * value.
-     * <p>
      *
      * @param      key   the name of the system property.
      * @param      value the value of the system property.
      * @return     the previous value of the system property,
      *             or <code>null</code> if it did not have one.
      *
-     * @exception  SecurityException  if a security manager exists and its
-     *             <code>checkPermission</code> method doesn't allow
-     *             setting of the specified property.
      * @exception  NullPointerException if <code>key</code> or
      *             <code>value</code> is <code>null</code>.
      * @exception  IllegalArgumentException if <code>key</code> is empty.
      * @see        #getProperty
      * @see        java.lang.System#getProperty(java.lang.String)
      * @see        java.lang.System#getProperty(java.lang.String, java.lang.String)
-     * @see        java.util.PropertyPermission
-     * @see        SecurityManager#checkPermission
      * @since      1.2
      */
     public static String setProperty(String key, String value) {
@@ -1319,29 +1233,17 @@
 
     /**
      * Removes the system property indicated by the specified key.
-     * <p>
-     * First, if a security manager exists, its
-     * <code>SecurityManager.checkPermission</code> method
-     * is called with a <code>PropertyPermission(key, "write")</code>
-     * permission. This may result in a SecurityException being thrown.
-     * If no exception is thrown, the specified property is removed.
-     * <p>
      *
      * @param      key   the name of the system property to be removed.
      * @return     the previous string value of the system property,
      *             or <code>null</code> if there was no property with that key.
      *
-     * @exception  SecurityException  if a security manager exists and its
-     *             <code>checkPropertyAccess</code> method doesn't allow
-     *              access to the specified system property.
      * @exception  NullPointerException if <code>key</code> is
      *             <code>null</code>.
      * @exception  IllegalArgumentException if <code>key</code> is empty.
      * @see        #getProperty
      * @see        #setProperty
      * @see        java.util.Properties
-     * @see        java.lang.SecurityException
-     * @see        java.lang.SecurityManager#checkPropertiesAccess()
      * @since 1.5
      */
     public static String clearProperty(String key) {
diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java
index c14022b..1436dd4 100755
--- a/ojluni/src/main/java/java/lang/Thread.java
+++ b/ojluni/src/main/java/java/lang/Thread.java
@@ -395,53 +395,6 @@
      *        zero to indicate that this parameter is to be ignored.
      */
     private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
-        // Android changed : Reimplemented.
-        /*
-        if (name == null) {
-            throw new NullPointerException("name cannot be null");
-        }
-
-        Thread parent = currentThread();
-        SecurityManager security = System.getSecurityManager();
-        if (g == null) {
-            // Determine if it's an applet or not
-
-            // If there is a security manager, ask the security manager what to do.
-            if (security != null) {
-                g = security.getThreadGroup();
-            }
-
-            // If the security doesn't have a strong opinion of the matter
-            // use the parent thread group.
-            if (g == null) {
-                g = parent.getThreadGroup();
-            }
-        }
-
-        // checkAccess regardless of whether or not threadgroup is explicitly passed in.
-        g.checkAccess();
-
-        // Do we have the required permissions?
-        if (security != null) {
-            if (isCCLOverridden(getClass())) {
-                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
-            }
-        }
-        if (g == null) {
-          g = parent.getThreadGroup();
-        }
-        g.checkAccess();
-        this.daemon = parent.isDaemon();
-        this.priority = parent.getPriority();
-        this.name = name.toCharArray();
-        if (security == null || isCCLOverridden(parent.getClass()))
-            this.contextClassLoader = parent.getContextClassLoader();
-        else
-            this.contextClassLoader = parent.contextClassLoader;
-        tid = nextThreadID();
-        */
-        // ----- END android -----
-
         Thread parent = currentThread();
         if (g == null) {
             g = parent.getThreadGroup();
@@ -574,7 +527,12 @@
         if (name == null) {
             name = "Thread-" + nextThreadNum();
         }
-        setName(name);
+
+        // NOTE: Resist the temptation to call setName() here. This constructor is only called
+        // by the runtime to construct peers for threads that have attached via JNI and it's
+        // undesirable to clobber their natively set name.
+        this.name = name;
+
         this.priority = priority;
         this.daemon = daemon;
         init2(currentThread());
diff --git a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
index 7295c6f..1fbf178 100755
--- a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -174,15 +174,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
-     * @since 1.5
-     */
-    public boolean isAnnotationPresent(
-        Class<? extends Annotation> annotationClass) {
-        return getAnnotation(annotationClass) != null;
-    }
-
-    /**
      * @since 1.5
      */
     public Annotation[] getAnnotations() {
@@ -195,31 +186,4 @@
     public Annotation[] getDeclaredAnnotations()  {
         throw new AssertionError("All subclasses should override this method");
     }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
-      return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
-      return AnnotatedElements.getAnnotationsByType(this, annotationClass);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    public <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
-      return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
-    }
 }
diff --git a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
index 724b70b..9d2158c 100755
--- a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -27,7 +27,7 @@
 package java.lang.reflect;
 
 import java.lang.annotation.Annotation;
-// import libcore.reflect.AnnotatedElements;
+import libcore.reflect.AnnotatedElements;
 
 /**
  * Represents an annotated element of the program currently running in this
@@ -73,8 +73,9 @@
      * @throws NullPointerException if the given annotation class is null
      * @since 1.5
      */
-     /*default*/ boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
-     // { return getAnnotation(annotationClass) != null; }
+     default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+         return getAnnotation(annotationClass) != null;
+     }
 
    /**
      * Returns this element's annotation for the specified type if
@@ -119,8 +120,9 @@
      *
      * @since 1.8
      */
-    /*default*/ <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass);
-    // { return AnnotatedElements.getDeclaredAnnotation(this, annotationClass); }
+    default <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
+        return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
+    }
 
     /**
      * Returns a directly or indirectly present list of annotations on {@code this} element,
@@ -128,8 +130,9 @@
      *
      * @since 1.8
      */
-    /*default*/ <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
-    // { return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass); }
+    default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+        return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
+    }
 
     /**
      * Returns an associated list of annotations on {@code this} element,
@@ -137,6 +140,7 @@
      *
      * @since 1.8
      */
-    /*default*/ <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
-    // { return AnnotatedElements.getAnnotationsByType(this, annotationClass); }
+    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+        return AnnotatedElements.getAnnotationsByType(this, annotationClass);
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/reflect/Constructor.java b/ojluni/src/main/java/java/lang/reflect/Constructor.java
index 9632f54..9742f0c 100755
--- a/ojluni/src/main/java/java/lang/reflect/Constructor.java
+++ b/ojluni/src/main/java/java/lang/reflect/Constructor.java
@@ -29,7 +29,6 @@
 import sun.reflect.CallerSensitive;
 import java.util.Comparator;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.Types;
 
 import java.lang.annotation.Annotation;
diff --git a/ojluni/src/main/java/java/lang/reflect/Field.java b/ojluni/src/main/java/java/lang/reflect/Field.java
index 28cc6d8..315b1ed 100755
--- a/ojluni/src/main/java/java/lang/reflect/Field.java
+++ b/ojluni/src/main/java/java/lang/reflect/Field.java
@@ -31,7 +31,6 @@
 import java.lang.annotation.Annotation;
 import java.util.Map;
 import com.android.dex.Dex;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.GenericSignatureParser;
 import java.util.List;
 
@@ -181,7 +180,7 @@
         }
         StringBuilder result = new StringBuilder();
         for (String s : annotation) {
-          result.append(s);
+            result.append(s);
         }
         return result.toString();
     }
diff --git a/ojluni/src/main/java/java/lang/reflect/Method.java b/ojluni/src/main/java/java/lang/reflect/Method.java
index d29e3e8..8ee7bd5 100755
--- a/ojluni/src/main/java/java/lang/reflect/Method.java
+++ b/ojluni/src/main/java/java/lang/reflect/Method.java
@@ -32,7 +32,6 @@
 import com.android.dex.Dex;
 import java.util.Comparator;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.Types;
 
 /**
@@ -194,14 +193,6 @@
         return super.getParameterTypes();
     }
 
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return isAnnotationPresentNative(annotationType);
-    }
-    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
-
     /**
      * Returns an array of {@code Type} objects that represent the formal
      * parameter types, in declaration order, of the method represented by
@@ -556,11 +547,6 @@
     }
 
     /**
-     * @since 1.5
-     */
-    @Override public native Annotation[] getDeclaredAnnotations();
-
-    /**
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
diff --git a/ojluni/src/main/java/java/net/HttpURLConnection.java b/ojluni/src/main/java/java/net/HttpURLConnection.java
index f88e9ef..9217aff 100755
--- a/ojluni/src/main/java/java/net/HttpURLConnection.java
+++ b/ojluni/src/main/java/java/net/HttpURLConnection.java
@@ -36,22 +36,241 @@
  * details.
  * <p>
  *
- * Each HttpURLConnection instance is used to make a single request
- * but the underlying network connection to the HTTP server may be
- * transparently shared by other instances. Calling the close() methods
- * on the InputStream or OutputStream of an HttpURLConnection
- * after a request may free network resources associated with this
- * instance but has no effect on any shared persistent connection.
- * Calling the disconnect() method may close the underlying socket
- * if a persistent connection is otherwise idle at that time.
+ * <p>Uses of this class follow a pattern:
+ * <ol>
+ *   <li>Obtain a new {@code HttpURLConnection} by calling {@link
+ *       URL#openConnection() URL.openConnection()} and casting the result to
+ *       {@code HttpURLConnection}.
+ *   <li>Prepare the request. The primary property of a request is its URI.
+ *       Request headers may also include metadata such as credentials, preferred
+ *       content types, and session cookies.
+ *   <li>Optionally upload a request body. Instances must be configured with
+ *       {@link #setDoOutput(boolean) setDoOutput(true)} if they include a
+ *       request body. Transmit data by writing to the stream returned by {@link
+ *       #getOutputStream()}.
+ *   <li>Read the response. Response headers typically include metadata such as
+ *       the response body's content type and length, modified dates and session
+ *       cookies. The response body may be read from the stream returned by {@link
+ *       #getInputStream()}. If the response has no body, that method returns an
+ *       empty stream.
+ *   <li>Disconnect. Once the response body has been read, the {@code
+ *       HttpURLConnection} should be closed by calling {@link #disconnect()}.
+ *       Disconnecting releases the resources held by a connection so they may
+ *       be closed or reused.
+ * </ol>
  *
- * <P>The HTTP protocol handler has a few settings that can be accessed through
- * System Properties. This covers
- * <a href="doc-files/net-properties.html#Proxies">Proxy settings</a> as well as
- * <a href="doc-files/net-properties.html#MiscHTTP"> various other settings</a>.
- * </P>
+ * <p>For example, to retrieve the webpage at {@code http://www.android.com/}:
+ * <pre>   {@code
+ *   URL url = new URL("http://www.android.com/");
+ *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ *   try {
+ *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
+ *     readStream(in);
+ *   } finally {
+ *     urlConnection.disconnect();
+ *   }
+ * }</pre>
  *
- * @see     java.net.HttpURLConnection#disconnect()
+ * <h3>Secure Communication with HTTPS</h3>
+ * Calling {@link URL#openConnection()} on a URL with the "https"
+ * scheme will return an {@code HttpsURLConnection}, which allows for
+ * overriding the default {@link javax.net.ssl.HostnameVerifier
+ * HostnameVerifier} and {@link javax.net.ssl.SSLSocketFactory
+ * SSLSocketFactory}. An application-supplied {@code SSLSocketFactory}
+ * created from an {@link javax.net.ssl.SSLContext SSLContext} can
+ * provide a custom {@link javax.net.ssl.X509TrustManager
+ * X509TrustManager} for verifying certificate chains and a custom
+ * {@link javax.net.ssl.X509KeyManager X509KeyManager} for supplying
+ * client certificates. See {@link javax.net.ssl.HttpsURLConnection
+ * HttpsURLConnection} for more details.
+ *
+ * <h3>Response Handling</h3>
+ * {@code HttpURLConnection} will follow up to five HTTP redirects. It will
+ * follow redirects from one origin server to another. This implementation
+ * doesn't follow redirects from HTTPS to HTTP or vice versa.
+ *
+ * <p>If the HTTP response indicates that an error occurred, {@link
+ * #getInputStream()} will throw an {@link IOException}. Use {@link
+ * #getErrorStream()} to read the error response. The headers can be read in
+ * the normal way using {@link #getHeaderFields()},
+ *
+ * <h3>Posting Content</h3>
+ * To upload data to a web server, configure the connection for output using
+ * {@link #setDoOutput(boolean) setDoOutput(true)}.
+ *
+ * <p>For best performance, you should call either {@link
+ * #setFixedLengthStreamingMode(int)} when the body length is known in advance,
+ * or {@link #setChunkedStreamingMode(int)} when it is not. Otherwise {@code
+ * HttpURLConnection} will be forced to buffer the complete request body in
+ * memory before it is transmitted, wasting (and possibly exhausting) heap and
+ * increasing latency.
+ *
+ * <p>For example, to perform an upload: <pre>   {@code
+ *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ *   try {
+ *     urlConnection.setDoOutput(true);
+ *     urlConnection.setChunkedStreamingMode(0);
+ *
+ *     OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
+ *     writeStream(out);
+ *
+ *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
+ *     readStream(in);
+ *   } finally {
+ *     urlConnection.disconnect();
+ *   }
+ * }</pre>
+ *
+ * <h3>Performance</h3>
+ * The input and output streams returned by this class are <strong>not
+ * buffered</strong>. Most callers should wrap the returned streams with {@link
+ * java.io.BufferedInputStream BufferedInputStream} or {@link
+ * java.io.BufferedOutputStream BufferedOutputStream}. Callers that do only bulk
+ * reads or writes may omit buffering.
+ *
+ * <p>When transferring large amounts of data to or from a server, use streams
+ * to limit how much data is in memory at once. Unless you need the entire
+ * body to be in memory at once, process it as a stream (rather than storing
+ * the complete body as a single byte array or string).
+ *
+ * <p>To reduce latency, this class may reuse the same underlying {@code Socket}
+ * for multiple request/response pairs. As a result, HTTP connections may be
+ * held open longer than necessary. Calls to {@link #disconnect()} may return
+ * the socket to a pool of connected sockets. This behavior can be disabled by
+ * setting the {@code http.keepAlive} system property to {@code false} before
+ * issuing any HTTP requests. The {@code http.maxConnections} property may be
+ * used to control how many idle connections to each server will be held.
+ *
+ * <p>By default, this implementation of {@code HttpURLConnection} requests that
+ * servers use gzip compression and it automatically decompresses the data for
+ * callers of {@link #getInputStream()}. The Content-Encoding and Content-Length
+ * response headers are cleared in this case. Gzip compression can be disabled by
+ * setting the acceptable encodings in the request header: <pre>   {@code
+ *   urlConnection.setRequestProperty("Accept-Encoding", "identity");
+ * }</pre>
+ *
+ * <p>Setting the Accept-Encoding request header explicitly disables automatic
+ * decompression and leaves the response headers intact; callers must handle
+ * decompression as needed, according to the Content-Encoding header of the
+ * response.
+ *
+ * <p>{@link #getContentLength()} returns the number of bytes transmitted and
+ * cannot be used to predict how many bytes can be read from
+ * {@link #getInputStream()} for compressed streams. Instead, read that stream
+ * until it is exhausted, i.e. when {@link InputStream#read} returns -1.
+ *
+ * <h3>Handling Network Sign-On</h3>
+ * Some Wi-Fi networks block Internet access until the user clicks through a
+ * sign-on page. Such sign-on pages are typically presented by using HTTP
+ * redirects. You can use {@link #getURL()} to test if your connection has been
+ * unexpectedly redirected. This check is not valid until <strong>after</strong>
+ * the response headers have been received, which you can trigger by calling
+ * {@link #getHeaderFields()} or {@link #getInputStream()}. For example, to
+ * check that a response was not redirected to an unexpected host:
+ * <pre>   {@code
+ *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ *   try {
+ *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
+ *     if (!url.getHost().equals(urlConnection.getURL().getHost())) {
+ *       // we were redirected! Kick the user out to the browser to sign on?
+ *     }
+ *     ...
+ *   } finally {
+ *     urlConnection.disconnect();
+ *   }
+ * }</pre>
+ *
+ * <h3>HTTP Authentication</h3>
+ * {@code HttpURLConnection} supports <a
+ * href="http://www.ietf.org/rfc/rfc2617">HTTP basic authentication</a>. Use
+ * {@link Authenticator} to set the VM-wide authentication handler:
+ * <pre>   {@code
+ *   Authenticator.setDefault(new Authenticator() {
+ *     protected PasswordAuthentication getPasswordAuthentication() {
+ *       return new PasswordAuthentication(username, password.toCharArray());
+ *     }
+ *   });
+ * }</pre>
+ * Unless paired with HTTPS, this is <strong>not</strong> a secure mechanism for
+ * user authentication. In particular, the username, password, request and
+ * response are all transmitted over the network without encryption.
+ *
+ * <h3>Sessions with Cookies</h3>
+ * To establish and maintain a potentially long-lived session between client
+ * and server, {@code HttpURLConnection} includes an extensible cookie manager.
+ * Enable VM-wide cookie management using {@link CookieHandler} and {@link
+ * CookieManager}: <pre>   {@code
+ *   CookieManager cookieManager = new CookieManager();
+ *   CookieHandler.setDefault(cookieManager);
+ * }</pre>
+ * By default, {@code CookieManager} accepts cookies from the <a
+ * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin
+ * server</a> only. Two other policies are included: {@link
+ * CookiePolicy#ACCEPT_ALL} and {@link CookiePolicy#ACCEPT_NONE}. Implement
+ * {@link CookiePolicy} to define a custom policy.
+ *
+ * <p>The default {@code CookieManager} keeps all accepted cookies in memory. It
+ * will forget these cookies when the VM exits. Implement {@link CookieStore} to
+ * define a custom cookie store.
+ *
+ * <p>In addition to the cookies set by HTTP responses, you may set cookies
+ * programmatically. To be included in HTTP request headers, cookies must have
+ * the domain and path properties set.
+ *
+ * <p>By default, new instances of {@code HttpCookie} work only with servers
+ * that support <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>
+ * cookies. Many web servers support only the older specification, <a
+ * href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a>. For compatibility
+ * with the most web servers, set the cookie version to 0.
+ *
+ * <p>For example, to receive {@code www.twitter.com} in French: <pre>   {@code
+ *   HttpCookie cookie = new HttpCookie("lang", "fr");
+ *   cookie.setDomain("twitter.com");
+ *   cookie.setPath("/");
+ *   cookie.setVersion(0);
+ *   cookieManager.getCookieStore().add(new URI("http://twitter.com/"), cookie);
+ * }</pre>
+ *
+ * <h3>HTTP Methods</h3>
+ * <p>{@code HttpURLConnection} uses the {@code GET} method by default. It will
+ * use {@code POST} if {@link #setDoOutput setDoOutput(true)} has been called.
+ * Other HTTP methods ({@code OPTIONS}, {@code HEAD}, {@code PUT}, {@code
+ * DELETE} and {@code TRACE}) can be used with {@link #setRequestMethod}.
+ *
+ * <h3>Proxies</h3>
+ * By default, this class will connect directly to the <a
+ * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin
+ * server</a>. It can also connect via an {@link Proxy.Type#HTTP HTTP} or {@link
+ * Proxy.Type#SOCKS SOCKS} proxy. To use a proxy, use {@link
+ * URL#openConnection(Proxy) URL.openConnection(Proxy)} when creating the
+ * connection.
+ *
+ * <h3>IPv6 Support</h3>
+ * <p>This class includes transparent support for IPv6. For hosts with both IPv4
+ * and IPv6 addresses, it will attempt to connect to each of a host's addresses
+ * until a connection is established.
+ *
+ * <h3>Response Caching</h3>
+ * Android 4.0 (Ice Cream Sandwich, API level 15) includes a response cache. See
+ * {@code android.net.http.HttpResponseCache} for instructions on enabling HTTP
+ * caching in your application.
+ *
+ * <h3>Avoiding Bugs In Earlier Releases</h3>
+ * Prior to Android 2.2 (Froyo), this class had some frustrating bugs. In
+ * particular, calling {@code close()} on a readable {@code InputStream} could
+ * <a href="http://code.google.com/p/android/issues/detail?id=2939">poison the
+ * connection pool</a>. Work around this by disabling connection pooling:
+ * <pre>   {@code
+ * private void disableConnectionReuseIfNecessary() {
+ *   // Work around pre-Froyo bugs in HTTP connection reuse.
+ *   if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
+ *     System.setProperty("http.keepAlive", "false");
+ *   }
+ * }}</pre>
+ *
+ * <p>Each instance of {@code HttpURLConnection} may be used for one
+ * request/response pair. Instances of this class are not thread safe.
+ *
  * @since JDK1.1
  */
 abstract public class HttpURLConnection extends URLConnection {
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index a46223d..f66b68d 100755
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -171,7 +171,7 @@
 
     /** @hide */
     public static final InetAddress ANY =
-            new Inet6Address(null, new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
+            new Inet6Address("::", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
 
     /** @hide */
     public static final InetAddress LOOPBACK = new Inet6Address("localhost",
diff --git a/ojluni/src/main/java/java/nio/Buffer.java b/ojluni/src/main/java/java/nio/Buffer.java
index 48b46dc..a7416ba 100755
--- a/ojluni/src/main/java/java/nio/Buffer.java
+++ b/ojluni/src/main/java/java/nio/Buffer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 package java.nio;
 
+import java.util.Spliterator;
 
 /**
  * A container for data of a specific primitive type.
@@ -173,6 +174,13 @@
 
 public abstract class Buffer {
 
+    /**
+     * The characteristics of Spliterators that traverse and split elements
+     * maintained in Buffers.
+     */
+    static final int SPLITERATOR_CHARACTERISTICS =
+        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
+
     // Invariants: mark <= position <= limit <= capacity
     private int mark = -1;
     int position = 0;
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
index 0defd57..1e30eb4 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -110,6 +110,10 @@
         return this;
     }
 
+    char getUnchecked(int i) {
+        return bb.getCharUnchecked(ix(i));
+    }
+
     public CharBuffer put(char x) {
         put(nextPutIndex(), x);
         return this;
diff --git a/ojluni/src/main/java/java/nio/CharBuffer.java b/ojluni/src/main/java/java/nio/CharBuffer.java
index 68685ce..8a5c64f 100644
--- a/ojluni/src/main/java/java/nio/CharBuffer.java
+++ b/ojluni/src/main/java/java/nio/CharBuffer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,9 @@
 
 
 import java.io.IOException;
+import java.util.Spliterator;
+import java.util.stream.StreamSupport;
+import java.util.stream.IntStream;
 
 
 /**
@@ -377,6 +380,17 @@
     public abstract char get(int index);
 
     /**
+     * Absolute <i>get</i> method.  Reads the char at the given
+     * index without any validation of the index.
+     *
+     * @param  index
+     *         The index from which the char will be read
+     *
+     * @return  The char at the given index
+     */
+    abstract char getUnchecked(int index);   // package-private
+
+    /**
      * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> Writes the given char into this buffer at the given
@@ -1049,5 +1063,10 @@
      */
     public abstract ByteOrder order();
 
-
+    @Override
+    public IntStream chars() {
+        CharBuffer self = this;
+        return StreamSupport.intStream(() -> new CharBufferSpliterator(self),
+            Buffer.SPLITERATOR_CHARACTERISTICS, false);
+    }
 }
diff --git a/ojluni/src/main/java/java/nio/CharBufferSpliterator.java b/ojluni/src/main/java/java/nio/CharBufferSpliterator.java
new file mode 100644
index 0000000..5b3977a
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/CharBufferSpliterator.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+
+/**
+ * A Spliterator.OfInt for sources that traverse and split elements
+ * maintained in a CharBuffer.
+ *
+ * @implNote
+ * The implementation is based on the code for the Array-based spliterators.
+ */
+class CharBufferSpliterator implements Spliterator.OfInt {
+    private final CharBuffer buffer;
+    private int index;   // current index, modified on advance/split
+    private final int limit;
+
+    CharBufferSpliterator(CharBuffer buffer) {
+        this(buffer, buffer.position(), buffer.limit());
+    }
+
+    CharBufferSpliterator(CharBuffer buffer, int origin, int limit) {
+        assert origin <= limit;
+        this.buffer = buffer;
+        this.index = (origin <= limit) ? origin : limit;
+        this.limit = limit;
+    }
+
+    @Override
+    public OfInt trySplit() {
+        int lo = index, mid = (lo + limit) >>> 1;
+        return (lo >= mid)
+               ? null
+               : new CharBufferSpliterator(buffer, lo, index = mid);
+    }
+
+    @Override
+    public void forEachRemaining(IntConsumer action) {
+        if (action == null)
+            throw new NullPointerException();
+        CharBuffer cb = buffer;
+        int i = index;
+        int hi = limit;
+        index = hi;
+        while (i < hi) {
+            action.accept(cb.getUnchecked(i++));
+        }
+    }
+
+    @Override
+    public boolean tryAdvance(IntConsumer action) {
+        if (action == null)
+            throw new NullPointerException();
+        if (index >= 0 && index < limit) {
+            action.accept(buffer.getUnchecked(index++));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public long estimateSize() {
+        return (long)(limit - index);
+    }
+
+    @Override
+    public int characteristics() {
+        return Buffer.SPLITERATOR_CHARACTERISTICS;
+    }
+}
diff --git a/ojluni/src/main/java/java/nio/HeapCharBuffer.java b/ojluni/src/main/java/java/nio/HeapCharBuffer.java
index 7957e70..f67c91f 100644
--- a/ojluni/src/main/java/java/nio/HeapCharBuffer.java
+++ b/ojluni/src/main/java/java/nio/HeapCharBuffer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -115,6 +115,10 @@
         return hb[ix(checkIndex(i))];
     }
 
+    char getUnchecked(int i) {
+        return hb[ix(i)];
+    }
+
     public CharBuffer get(char[] dst, int offset, int length) {
         checkBounds(offset, length, dst.length);
         if (length > remaining())
diff --git a/ojluni/src/main/java/java/nio/StringCharBuffer.java b/ojluni/src/main/java/java/nio/StringCharBuffer.java
index 8dbd53b..6654c18 100755
--- a/ojluni/src/main/java/java/nio/StringCharBuffer.java
+++ b/ojluni/src/main/java/java/nio/StringCharBuffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,6 +76,10 @@
         return str.charAt(checkIndex(index) + offset);
     }
 
+    char getUnchecked(int index) {
+        return str.charAt(index + offset);
+    }
+
     // ## Override bulk get methods for better performance
 
     public final CharBuffer put(char c) {
diff --git a/ojluni/src/main/java/java/nio/channels/AcceptPendingException.java b/ojluni/src/main/java/java/nio/channels/AcceptPendingException.java
new file mode 100644
index 0000000..dc357f0
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AcceptPendingException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Unchecked exception thrown when an attempt is made to initiate an accept
+ * operation on a channel and a previous accept operation has not completed.
+ *
+ * @since 1.7
+ */
+
+public class AcceptPendingException
+    extends IllegalStateException
+{
+
+    private static final long serialVersionUID = 2721339977965416421L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public AcceptPendingException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/AsynchronousByteChannel.java b/ojluni/src/main/java/java/nio/channels/AsynchronousByteChannel.java
new file mode 100755
index 0000000..9fdf753
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AsynchronousByteChannel.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.Future;
+
+/**
+ * An asynchronous channel that can read and write bytes.
+ *
+ * <p> Some channels may not allow more than one read or write to be outstanding
+ * at any given time. If a thread invokes a read method before a previous read
+ * operation has completed then a {@link ReadPendingException} will be thrown.
+ * Similarly, if a write method is invoked before a previous write has completed
+ * then {@link WritePendingException} is thrown. Whether or not other kinds of
+ * I/O operations may proceed concurrently with a read operation depends upon
+ * the type of the channel.
+ *
+ * <p> Note that {@link java.nio.ByteBuffer ByteBuffers} are not safe for use by
+ * multiple concurrent threads. When a read or write operation is initiated then
+ * care must be taken to ensure that the buffer is not accessed until the
+ * operation completes.
+ *
+ * @see Channels#newInputStream(AsynchronousByteChannel)
+ * @see Channels#newOutputStream(AsynchronousByteChannel)
+ *
+ * @since 1.7
+ */
+
+public interface AsynchronousByteChannel
+    extends AsynchronousChannel
+{
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the read
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes read or {@code -1} if no bytes could be
+     * read because the channel has reached end-of-stream.
+     *
+     * <p> The read operation may read up to <i>r</i> bytes from the channel,
+     * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+     * {@code dst.remaining()} at the time that the read is attempted. Where
+     * <i>r</i> is 0, the read operation completes immediately with a result of
+     * {@code 0} without initiating an I/O operation.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * This byte sequence will be transferred into the buffer so that the first
+     * byte in the sequence is at index <i>p</i> and the last byte is at index
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>,
+     * where <i>p</i> is the buffer's position at the moment the read is
+     * performed. Upon completion the buffer's position will be equal to
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+     *
+     * <p> Buffers are not safe for use by multiple concurrent threads so care
+     * should be taken to not access the buffer until the operation has
+     * completed.
+     *
+     * <p> This method may be invoked at any time. Some channel types may not
+     * allow more than one read to be outstanding at any given time. If a thread
+     * initiates a read operation before a previous read operation has
+     * completed then a {@link ReadPendingException} will be thrown.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The completion handler
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If the channel does not allow more than one read to be outstanding
+     *          and a previous read has not completed
+     * @throws  ShutdownChannelGroupException
+     *          If the channel is associated with a {@link AsynchronousChannelGroup
+     *          group} that has terminated
+     */
+    <A> void read(ByteBuffer dst,
+                  A attachment,
+                  CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The method
+     * behaves in exactly the same manner as the {@link
+     * #read(ByteBuffer,Object,CompletionHandler)
+     * read(ByteBuffer,Object,CompletionHandler)} method except that instead
+     * of specifying a completion handler, this method returns a {@code Future}
+     * representing the pending result. The {@code Future}'s {@link Future#get()
+     * get} method returns the number of bytes read or {@code -1} if no bytes
+     * could be read because the channel has reached end-of-stream.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     *
+     * @return  A Future representing the result of the operation
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If the channel does not allow more than one read to be outstanding
+     *          and a previous read has not completed
+     */
+    Future<Integer> read(ByteBuffer dst);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the write
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes written.
+     *
+     * <p> The write operation may write up to <i>r</i> bytes to the channel,
+     * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+     * {@code src.remaining()} at the time that the write is attempted. Where
+     * <i>r</i> is 0, the write operation completes immediately with a result of
+     * {@code 0} without initiating an I/O operation.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * This byte sequence will be transferred from the buffer starting at index
+     * <i>p</i>, where <i>p</i> is the buffer's position at the moment the
+     * write is performed; the index of the last byte written will be
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>.
+     * Upon completion the buffer's position will be equal to
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+     *
+     * <p> Buffers are not safe for use by multiple concurrent threads so care
+     * should be taken to not access the buffer until the operation has
+     * completed.
+     *
+     * <p> This method may be invoked at any time. Some channel types may not
+     * allow more than one write to be outstanding at any given time. If a thread
+     * initiates a write operation before a previous write operation has
+     * completed then a {@link WritePendingException} will be thrown.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The completion handler object
+     *
+     * @throws  WritePendingException
+     *          If the channel does not allow more than one write to be outstanding
+     *          and a previous write has not completed
+     * @throws  ShutdownChannelGroupException
+     *          If the channel is associated with a {@link AsynchronousChannelGroup
+     *          group} that has terminated
+     */
+    <A> void write(ByteBuffer src,
+                   A attachment,
+                   CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The method
+     * behaves in exactly the same manner as the {@link
+     * #write(ByteBuffer,Object,CompletionHandler)
+     * write(ByteBuffer,Object,CompletionHandler)} method except that instead
+     * of specifying a completion handler, this method returns a {@code Future}
+     * representing the pending result. The {@code Future}'s {@link Future#get()
+     * get} method returns the number of bytes written.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     *
+     * @return A Future representing the result of the operation
+     *
+     * @throws  WritePendingException
+     *          If the channel does not allow more than one write to be outstanding
+     *          and a previous write has not completed
+     */
+    Future<Integer> write(ByteBuffer src);
+}
diff --git a/ojluni/src/main/java/java/nio/channels/AsynchronousChannel.java b/ojluni/src/main/java/java/nio/channels/AsynchronousChannel.java
new file mode 100755
index 0000000..5aa9fe2
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AsynchronousChannel.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.util.concurrent.Future;  // javadoc
+
+/**
+ * A channel that supports asynchronous I/O operations. Asynchronous I/O
+ * operations will usually take one of two forms:
+ *
+ * <ol>
+ * <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li>
+ * <li><pre>void <em>operation</em>(<em>...</em> A attachment, {@link
+ *   CompletionHandler}&lt;V,? super A&gt; handler)</pre></li>
+ * </ol>
+ *
+ * where <i>operation</i> is the name of the I/O operation (read or write for
+ * example), <i>V</i> is the result type of the I/O operation, and <i>A</i> is
+ * the type of an object attached to the I/O operation to provide context when
+ * consuming the result. The attachment is important for cases where a
+ * <em>state-less</em> {@code CompletionHandler} is used to consume the result
+ * of many I/O operations.
+ *
+ * <p> In the first form, the methods defined by the {@link Future Future}
+ * interface may be used to check if the operation has completed, wait for its
+ * completion, and to retrieve the result. In the second form, a {@link
+ * CompletionHandler} is invoked to consume the result of the I/O operation when
+ * it completes or fails.
+ *
+ * <p> A channel that implements this interface is <em>asynchronously
+ * closeable</em>: If an I/O operation is outstanding on the channel and the
+ * channel's {@link #close close} method is invoked, then the I/O operation
+ * fails with the exception {@link AsynchronousCloseException}.
+ *
+ * <p> Asynchronous channels are safe for use by multiple concurrent threads.
+ * Some channel implementations may support concurrent reading and writing, but
+ * may not allow more than one read and one write operation to be outstanding at
+ * any given time.
+ *
+ * <h4>Cancellation</h4>
+ *
+ * <p> The {@code Future} interface defines the {@link Future#cancel cancel}
+ * method to cancel execution. This causes all threads waiting on the result of
+ * the I/O operation to throw {@link java.util.concurrent.CancellationException}.
+ * Whether the underlying I/O operation can be cancelled is highly implementation
+ * specific and therefore not specified. Where cancellation leaves the channel,
+ * or the entity to which it is connected, in an inconsistent state, then the
+ * channel is put into an implementation specific <em>error state</em> that
+ * prevents further attempts to initiate I/O operations that are <i>similar</i>
+ * to the operation that was cancelled. For example, if a read operation is
+ * cancelled but the implementation cannot guarantee that bytes have not been
+ * read from the channel then it puts the channel into an error state; further
+ * attempts to initiate a {@code read} operation cause an unspecified runtime
+ * exception to be thrown. Similarly, if a write operation is cancelled but the
+ * implementation cannot guarantee that bytes have not been written to the
+ * channel then subsequent attempts to initiate a {@code write} will fail with
+ * an unspecified runtime exception.
+ *
+ * <p> Where the {@link Future#cancel cancel} method is invoked with the {@code
+ * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
+ * may be interrupted by closing the channel. In that case all threads waiting
+ * on the result of the I/O operation throw {@code CancellationException} and
+ * any other I/O operations outstanding on the channel complete with the
+ * exception {@link AsynchronousCloseException}.
+ *
+ * <p> Where the {@code cancel} method is invoked to cancel read or write
+ * operations then it is recommended that all buffers used in the I/O operations
+ * be discarded or care taken to ensure that the buffers are not accessed while
+ * the channel remains open.
+ *
+ *  @since 1.7
+ */
+
+public interface AsynchronousChannel
+    extends Channel
+{
+    /**
+     * Closes this channel.
+     *
+     * <p> Any outstanding asynchronous operations upon this channel will
+     * complete with the exception {@link AsynchronousCloseException}. After a
+     * channel is closed, further attempts to initiate asynchronous I/O
+     * operations complete immediately with cause {@link ClosedChannelException}.
+     *
+     * <p>  This method otherwise behaves exactly as specified by the {@link
+     * Channel} interface.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    @Override
+    void close() throws IOException;
+}
diff --git a/ojluni/src/main/java/java/nio/channels/AsynchronousChannelGroup.java b/ojluni/src/main/java/java/nio/channels/AsynchronousChannelGroup.java
new file mode 100755
index 0000000..2eb4b52
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AsynchronousChannelGroup.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A grouping of asynchronous channels for the purpose of resource sharing.
+ *
+ * <p> An asynchronous channel group encapsulates the mechanics required to
+ * handle the completion of I/O operations initiated by {@link AsynchronousChannel
+ * asynchronous channels} that are bound to the group. A group has an associated
+ * thread pool to which tasks are submitted to handle I/O events and dispatch to
+ * {@link CompletionHandler completion-handlers} that consume the result of
+ * asynchronous operations performed on channels in the group. In addition to
+ * handling I/O events, the pooled threads may also execute other tasks required
+ * to support the execution of asynchronous I/O operations.
+ *
+ * <p> An asynchronous channel group is created by invoking the {@link
+ * #withFixedThreadPool withFixedThreadPool} or {@link #withCachedThreadPool
+ * withCachedThreadPool} methods defined here. Channels are bound to a group by
+ * specifying the group when constructing the channel. The associated thread
+ * pool is <em>owned</em> by the group; termination of the group results in the
+ * shutdown of the associated thread pool.
+ *
+ * <p> In addition to groups created explicitly, the Java virtual machine
+ * maintains a system-wide <em>default group</em> that is constructed
+ * automatically. Asynchronous channels that do not specify a group at
+ * construction time are bound to the default group. The default group has an
+ * associated thread pool that creates new threads as needed. The default group
+ * may be configured by means of system properties defined in the table below.
+ * Where the {@link java.util.concurrent.ThreadFactory ThreadFactory} for the
+ * default group is not configured then the pooled threads of the default group
+ * are {@link Thread#isDaemon daemon} threads.
+ *
+ * <table border>
+ *   <tr>
+ *     <th>System property</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *   <tr>
+ *     <td> {@code java.nio.channels.DefaultThreadPool.threadFactory} </td>
+ *     <td> The value of this property is taken to be the fully-qualified name
+ *     of a concrete {@link java.util.concurrent.ThreadFactory ThreadFactory}
+ *     class. The class is loaded using the system class loader and instantiated.
+ *     The factory's {@link java.util.concurrent.ThreadFactory#newThread
+ *     newThread} method is invoked to create each thread for the default
+ *     group's thread pool. If the process to load and instantiate the value
+ *     of the property fails then an unspecified error is thrown during the
+ *     construction of the default group. </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@code java.nio.channels.DefaultThreadPool.initialSize} </td>
+ *     <td> The value of the {@code initialSize} parameter for the default
+ *     group (see {@link #withCachedThreadPool withCachedThreadPool}).
+ *     The value of the property is taken to be the {@code String}
+ *     representation of an {@code Integer} that is the initial size parameter.
+ *     If the value cannot be parsed as an {@code Integer} it causes an
+ *     unspecified error to be thrown during the construction of the default
+ *     group. </td>
+ *   </tr>
+ * </table>
+ *
+ * <a name="threading"><h4>Threading</h4></a>
+ *
+ * <p> The completion handler for an I/O operation initiated on a channel bound
+ * to a group is guaranteed to be invoked by one of the pooled threads in the
+ * group. This ensures that the completion handler is run by a thread with the
+ * expected <em>identity</em>.
+ *
+ * <p> Where an I/O operation completes immediately, and the initiating thread
+ * is one of the pooled threads in the group then the completion handler may
+ * be invoked directly by the initiating thread. To avoid stack overflow, an
+ * implementation may impose a limit as to the number of activations on the
+ * thread stack. Some I/O operations may prohibit invoking the completion
+ * handler directly by the initiating thread (see {@link
+ * AsynchronousServerSocketChannel#accept(Object,CompletionHandler) accept}).
+ *
+ * <a name="shutdown"><h4>Shutdown and Termination</h4></a>
+ *
+ * <p> The {@link #shutdown() shutdown} method is used to initiate an <em>orderly
+ * shutdown</em> of a group. An orderly shutdown marks the group as shutdown;
+ * further attempts to construct a channel that binds to the group will throw
+ * {@link ShutdownChannelGroupException}. Whether or not a group is shutdown can
+ * be tested using the {@link #isShutdown() isShutdown} method. Once shutdown,
+ * the group <em>terminates</em> when all asynchronous channels that are bound to
+ * the group are closed, all actively executing completion handlers have run to
+ * completion, and resources used by the group are released. No attempt is made
+ * to stop or interrupt threads that are executing completion handlers. The
+ * {@link #isTerminated() isTerminated} method is used to test if the group has
+ * terminated, and the {@link #awaitTermination awaitTermination} method can be
+ * used to block until the group has terminated.
+ *
+ * <p> The {@link #shutdownNow() shutdownNow} method can be used to initiate a
+ * <em>forceful shutdown</em> of the group. In addition to the actions performed
+ * by an orderly shutdown, the {@code shutdownNow} method closes all open channels
+ * in the group as if by invoking the {@link AsynchronousChannel#close close}
+ * method.
+ *
+ * @since 1.7
+ *
+ * @see AsynchronousSocketChannel#open(AsynchronousChannelGroup)
+ * @see AsynchronousServerSocketChannel#open(AsynchronousChannelGroup)
+ */
+
+public abstract class AsynchronousChannelGroup {
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initialize a new instance of this class.
+     *
+     * @param   provider
+     *          The asynchronous channel provider for this group
+     */
+    protected AsynchronousChannelGroup(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel group.
+     *
+     * @return  The provider that created this channel group
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Creates an asynchronous channel group with a fixed thread pool.
+     *
+     * <p> The resulting asynchronous channel group reuses a fixed number of
+     * threads. At any point, at most {@code nThreads} threads will be active
+     * processing tasks that are submitted to handle I/O events and dispatch
+     * completion results for operations initiated on asynchronous channels in
+     * the group.
+     *
+     * <p> The group is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousChannelGroup(int,ThreadFactory)
+     * openAsynchronousChannelGroup(int,ThreadFactory)} method of the system-wide
+     * default {@link AsynchronousChannelProvider} object.
+     *
+     * @param   nThreads
+     *          The number of threads in the pool
+     * @param   threadFactory
+     *          The factory to use when creating new threads
+     *
+     * @return  A new asynchronous channel group
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code nThreads <= 0}
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,
+                                                               ThreadFactory threadFactory)
+        throws IOException
+    {
+        return AsynchronousChannelProvider.provider()
+            .openAsynchronousChannelGroup(nThreads, threadFactory);
+    }
+
+    /**
+     * Creates an asynchronous channel group with a given thread pool that
+     * creates new threads as needed.
+     *
+     * <p> The {@code executor} parameter is an {@code ExecutorService} that
+     * creates new threads as needed to execute tasks that are submitted to
+     * handle I/O events and dispatch completion results for operations initiated
+     * on asynchronous channels in the group. It may reuse previously constructed
+     * threads when they are available.
+     *
+     * <p> The {@code initialSize} parameter may be used by the implementation
+     * as a <em>hint</em> as to the initial number of tasks it may submit. For
+     * example, it may be used to indictae the initial number of threads that
+     * wait on I/O events.
+     *
+     * <p> The executor is intended to be used exclusively by the resulting
+     * asynchronous channel group. Termination of the group results in the
+     * orderly  {@link ExecutorService#shutdown shutdown} of the executor
+     * service. Shutting down the executor service by other means results in
+     * unspecified behavior.
+     *
+     * <p> The group is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousChannelGroup(ExecutorService,int)
+     * openAsynchronousChannelGroup(ExecutorService,int)} method of the system-wide
+     * default {@link AsynchronousChannelProvider} object.
+     *
+     * @param   executor
+     *          The thread pool for the resulting group
+     * @param   initialSize
+     *          A value {@code >=0} or a negative value for implementation
+     *          specific default
+     *
+     * @return  A new asynchronous channel group
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see java.util.concurrent.Executors#newCachedThreadPool
+     */
+    public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,
+                                                                int initialSize)
+        throws IOException
+    {
+        return AsynchronousChannelProvider.provider()
+            .openAsynchronousChannelGroup(executor, initialSize);
+    }
+
+    /**
+     * Creates an asynchronous channel group with a given thread pool.
+     *
+     * <p> The {@code executor} parameter is an {@code ExecutorService} that
+     * executes tasks submitted to dispatch completion results for operations
+     * initiated on asynchronous channels in the group.
+     *
+     * <p> Care should be taken when configuring the executor service. It
+     * should support <em>direct handoff</em> or <em>unbounded queuing</em> of
+     * submitted tasks, and the thread that invokes the {@link
+     * ExecutorService#execute execute} method should never invoke the task
+     * directly. An implementation may mandate additional constraints.
+     *
+     * <p> The executor is intended to be used exclusively by the resulting
+     * asynchronous channel group. Termination of the group results in the
+     * orderly  {@link ExecutorService#shutdown shutdown} of the executor
+     * service. Shutting down the executor service by other means results in
+     * unspecified behavior.
+     *
+     * <p> The group is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousChannelGroup(ExecutorService,int)
+     * openAsynchronousChannelGroup(ExecutorService,int)} method of the system-wide
+     * default {@link AsynchronousChannelProvider} object with an {@code
+     * initialSize} of {@code 0}.
+     *
+     * @param   executor
+     *          The thread pool for the resulting group
+     *
+     * @return  A new asynchronous channel group
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousChannelGroup withThreadPool(ExecutorService executor)
+        throws IOException
+    {
+        return AsynchronousChannelProvider.provider()
+            .openAsynchronousChannelGroup(executor, 0);
+    }
+
+    /**
+     * Tells whether or not this asynchronous channel group is shutdown.
+     *
+     * @return  {@code true} if this asynchronous channel group is shutdown or
+     *          has been marked for shutdown.
+     */
+    public abstract boolean isShutdown();
+
+    /**
+     * Tells whether or not this group has terminated.
+     *
+     * <p> Where this method returns {@code true}, then the associated thread
+     * pool has also {@link ExecutorService#isTerminated terminated}.
+     *
+     * @return  {@code true} if this group has terminated
+     */
+    public abstract boolean isTerminated();
+
+    /**
+     * Initiates an orderly shutdown of the group.
+     *
+     * <p> This method marks the group as shutdown. Further attempts to construct
+     * channel that binds to this group will throw {@link ShutdownChannelGroupException}.
+     * The group terminates when all asynchronous channels in the group are
+     * closed, all actively executing completion handlers have run to completion,
+     * and all resources have been released. This method has no effect if the
+     * group is already shutdown.
+     */
+    public abstract void shutdown();
+
+    /**
+     * Shuts down the group and closes all open channels in the group.
+     *
+     * <p> In addition to the actions performed by the {@link #shutdown() shutdown}
+     * method, this method invokes the {@link AsynchronousChannel#close close}
+     * method on all open channels in the group. This method does not attempt to
+     * stop or interrupt threads that are executing completion handlers. The
+     * group terminates when all actively executing completion handlers have run
+     * to completion and all resources have been released. This method may be
+     * invoked at any time. If some other thread has already invoked it, then
+     * another invocation will block until the first invocation is complete,
+     * after which it will return without effect.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract void shutdownNow() throws IOException;
+
+    /**
+     * Awaits termination of the group.
+
+     * <p> This method blocks until the group has terminated, or the timeout
+     * occurs, or the current thread is interrupted, whichever happens first.
+     *
+     * @param   timeout
+     *          The maximum time to wait, or zero or less to not wait
+     * @param   unit
+     *          The time unit of the timeout argument
+     *
+     * @return  {@code true} if the group has terminated; {@code false} if the
+     *          timeout elapsed before termination
+     *
+     * @throws  InterruptedException
+     *          If interrupted while waiting
+     */
+    public abstract boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException;
+}
diff --git a/ojluni/src/main/java/java/nio/channels/AsynchronousServerSocketChannel.java b/ojluni/src/main/java/java/nio/channels/AsynchronousServerSocketChannel.java
new file mode 100755
index 0000000..1b5a67f
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AsynchronousServerSocketChannel.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.util.concurrent.Future;
+import java.io.IOException;
+
+/**
+ * An asynchronous channel for stream-oriented listening sockets.
+ *
+ * <p> An asynchronous server-socket channel is created by invoking the
+ * {@link #open open} method of this class.
+ * A newly-created asynchronous server-socket channel is open but not yet bound.
+ * It can be bound to a local address and configured to listen for connections
+ * by invoking the {@link #bind(SocketAddress,int) bind} method. Once bound,
+ * the {@link #accept(Object,CompletionHandler) accept} method
+ * is used to initiate the accepting of connections to the channel's socket.
+ * An attempt to invoke the <tt>accept</tt> method on an unbound channel will
+ * cause a {@link NotYetBoundException} to be thrown.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads
+ * though at most one accept operation can be outstanding at any time.
+ * If a thread initiates an accept operation before a previous accept operation
+ * has completed then an {@link AcceptPendingException} will be thrown.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Channels of this type support the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *  final AsynchronousServerSocketChannel listener =
+ *      AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
+ *
+ *  listener.accept(null, new CompletionHandler&lt;AsynchronousSocketChannel,Void&gt;() {
+ *      public void completed(AsynchronousSocketChannel ch, Void att) {
+ *          // accept the next connection
+ *          listener.accept(null, this);
+ *
+ *          // handle this connection
+ *          handle(ch);
+ *      }
+ *      public void failed(Throwable exc, Void att) {
+ *          ...
+ *      }
+ *  });
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousServerSocketChannel
+    implements AsynchronousChannel, NetworkChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousServerSocketChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousServerSocketChannel
+     * openAsynchronousServerSocketChannel} method on the {@link
+     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
+     * the given group. If the group parameter is <tt>null</tt> then the
+     * resulting channel is created by the system-wide default provider, and
+     * bound to the <em>default group</em>.
+     *
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or <tt>null</tt> for the default group
+     *
+     * @return  A new asynchronous server socket channel
+     *
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousServerSocketChannel open(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousServerSocketChannel(group);
+    }
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * <p> This method returns an asynchronous server socket channel that is
+     * bound to the <em>default group</em>. This method is equivalent to evaluating
+     * the expression:
+     * <blockquote><pre>
+     * open((AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous server socket channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousServerSocketChannel open()
+        throws IOException
+    {
+        return open(null);
+    }
+
+    /**
+     * Binds the channel's socket to a local address and configures the socket to
+     * listen for connections.
+     *
+     * <p> An invocation of this method is equivalent to the following:
+     * <blockquote><pre>
+     * bind(local, 0);
+     * </pre></blockquote>
+     *
+     * @param   local
+     *          The local address to bind the socket, or <tt>null</tt> to bind
+     *          to an automatically assigned socket address
+     *
+     * @return  This channel
+     *
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  SecurityException                   {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     */
+    public final AsynchronousServerSocketChannel bind(SocketAddress local)
+        throws IOException
+    {
+        return bind(local, 0);
+    }
+
+    /**
+     * Binds the channel's socket to a local address and configures the socket to
+     * listen for connections.
+     *
+     * <p> This method is used to establish an association between the socket and
+     * a local address. Once an association is established then the socket remains
+     * bound until the associated channel is closed.
+     *
+     * <p> The {@code backlog} parameter is the maximum number of pending
+     * connections on the socket. Its exact semantics are implementation specific.
+     * In particular, an implementation may impose a maximum length or may choose
+     * to ignore the parameter altogther. If the {@code backlog} parameter has
+     * the value {@code 0}, or a negative value, then an implementation specific
+     * default is used.
+     *
+     * @param   local
+     *          The local address to bind the socket, or {@code null} to bind
+     *          to an automatically assigned socket address
+     * @param   backlog
+     *          The maximum number of pending connections
+     *
+     * @return  This channel
+     *
+     * @throws  AlreadyBoundException
+     *          If the socket is already bound
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given address is not supported
+     * @throws  SecurityException
+     *          If a security manager has been installed and its {@link
+     *          SecurityManager#checkListen checkListen} method denies the operation
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+    public abstract <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Accepts a connection.
+     *
+     * <p> This method initiates an asynchronous operation to accept a
+     * connection made to this channel's socket. The {@code handler} parameter is
+     * a completion handler that is invoked when a connection is accepted (or
+     * the operation fails). The result passed to the completion handler is
+     * the {@link AsynchronousSocketChannel} to the new connection.
+     *
+     * <p> When a new connection is accepted then the resulting {@code
+     * AsynchronousSocketChannel} will be bound to the same {@link
+     * AsynchronousChannelGroup} as this channel. If the group is {@link
+     * AsynchronousChannelGroup#isShutdown shutdown} and a connection is accepted,
+     * then the connection is closed, and the operation completes with an {@code
+     * IOException} and cause {@link ShutdownChannelGroupException}.
+     *
+     * <p> To allow for concurrent handling of new connections, the completion
+     * handler is not invoked directly by the initiating thread when a new
+     * connection is accepted immediately (see <a
+     * href="AsynchronousChannelGroup.html#threading">Threading<a>).
+     *
+     * <p> If a security manager has been installed then it verifies that the
+     * address and port number of the connection's remote endpoint are permitted
+     * by the security manager's {@link SecurityManager#checkAccept checkAccept}
+     * method. The permission check is performed with privileges that are restricted
+     * by the calling context of this method. If the permission check fails then
+     * the connection is closed and the operation completes with a {@link
+     * SecurityException}.
+     *
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  AcceptPendingException
+     *          If an accept operation is already in progress on this channel
+     * @throws  NotYetBoundException
+     *          If this channel's socket has not yet been bound
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    public abstract <A> void accept(A attachment,
+                                    CompletionHandler<AsynchronousSocketChannel,? super A> handler);
+
+    /**
+     * Accepts a connection.
+     *
+     * <p> This method initiates an asynchronous operation to accept a
+     * connection made to this channel's socket. The method behaves in exactly
+     * the same manner as the {@link #accept(Object, CompletionHandler)} method
+     * except that instead of specifying a completion handler, this method
+     * returns a {@code Future} representing the pending result. The {@code
+     * Future}'s {@link Future#get() get} method returns the {@link
+     * AsynchronousSocketChannel} to the new connection on successful completion.
+     *
+     * @return  a {@code Future} object representing the pending result
+     *
+     * @throws  AcceptPendingException
+     *          If an accept operation is already in progress on this channel
+     * @throws  NotYetBoundException
+     *          If this channel's socket has not yet been bound
+     */
+    public abstract Future<AsynchronousSocketChannel> accept();
+}
diff --git a/ojluni/src/main/java/java/nio/channels/AsynchronousSocketChannel.java b/ojluni/src/main/java/java/nio/channels/AsynchronousSocketChannel.java
new file mode 100755
index 0000000..d78800b
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/AsynchronousSocketChannel.java
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * An asynchronous channel for stream-oriented connecting sockets.
+ *
+ * <p> Asynchronous socket channels are created in one of two ways. A newly-created
+ * {@code AsynchronousSocketChannel} is created by invoking one of the {@link
+ * #open open} methods defined by this class. A newly-created channel is open but
+ * not yet connected. A connected {@code AsynchronousSocketChannel} is created
+ * when a connection is made to the socket of an {@link AsynchronousServerSocketChannel}.
+ * It is not possible to create an asynchronous socket channel for an arbitrary,
+ * pre-existing {@link java.net.Socket socket}.
+ *
+ * <p> A newly-created channel is connected by invoking its {@link #connect connect}
+ * method; once connected, a channel remains connected until it is closed.  Whether
+ * or not a socket channel is connected may be determined by invoking its {@link
+ * #getRemoteAddress getRemoteAddress} method. An attempt to invoke an I/O
+ * operation upon an unconnected channel will cause a {@link NotYetConnectedException}
+ * to be thrown.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads.
+ * They support concurrent reading and writing, though at most one read operation
+ * and one write operation can be outstanding at any time.
+ * If a thread initiates a read operation before a previous read operation has
+ * completed then a {@link ReadPendingException} will be thrown. Similarly, an
+ * attempt to initiate a write operation before a previous write has completed
+ * will throw a {@link WritePendingException}.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Asynchronous socket channels support the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_SNDBUF SO_SNDBUF} </td>
+ *     <td> The size of the socket send buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_KEEPALIVE SO_KEEPALIVE} </td>
+ *     <td> Keep connection alive </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOptions#TCP_NODELAY TCP_NODELAY} </td>
+ *     <td> Disable the Nagle algorithm </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <h4>Timeouts</h4>
+ *
+ * <p> The {@link #read(ByteBuffer,long,TimeUnit,Object,CompletionHandler) read}
+ * and {@link #write(ByteBuffer,long,TimeUnit,Object,CompletionHandler) write}
+ * methods defined by this class allow a timeout to be specified when initiating
+ * a read or write operation. If the timeout elapses before an operation completes
+ * then the operation completes with the exception {@link
+ * InterruptedByTimeoutException}. A timeout may leave the channel, or the
+ * underlying connection, in an inconsistent state. Where the implementation
+ * cannot guarantee that bytes have not been read from the channel then it puts
+ * the channel into an implementation specific <em>error state</em>. A subsequent
+ * attempt to initiate a {@code read} operation causes an unspecified runtime
+ * exception to be thrown. Similarly if a {@code write} operation times out and
+ * the implementation cannot guarantee bytes have not been written to the
+ * channel then further attempts to {@code write} to the channel cause an
+ * unspecified runtime exception to be thrown. When a timeout elapses then the
+ * state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O
+ * operation is not defined. Buffers should be discarded or at least care must
+ * be taken to ensure that the buffers are not accessed while the channel remains
+ * open. All methods that accept timeout parameters treat values less than or
+ * equal to zero to mean that the I/O operation does not timeout.
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousSocketChannel
+    implements AsynchronousByteChannel, NetworkChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousSocketChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousSocketChannel
+     * openAsynchronousSocketChannel} method on the {@link
+     * AsynchronousChannelProvider} that created the group. If the group parameter
+     * is {@code null} then the resulting channel is created by the system-wide
+     * default provider, and bound to the <em>default group</em>.
+     *
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or {@code null} for the default group
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousSocketChannel(group);
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> This method returns an asynchronous socket channel that is bound to
+     * the <em>default group</em>.This method is equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * open((AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open()
+        throws IOException
+    {
+        return open(null);
+    }
+
+
+    // -- socket options and related --
+
+    /**
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     */
+    @Override
+    public abstract AsynchronousSocketChannel bind(SocketAddress local)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+    @Override
+    public abstract <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Shutdown the connection for reading without closing the channel.
+     *
+     * <p> Once shutdown for reading then further reads on the channel will
+     * return {@code -1}, the end-of-stream indication. If the input side of the
+     * connection is already shutdown then invoking this method has no effect.
+     * The effect on an outstanding read operation is system dependent and
+     * therefore not specified. The effect, if any, when there is data in the
+     * socket receive buffer that has not been read, or data arrives subsequently,
+     * is also system dependent.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownInput() throws IOException;
+
+    /**
+     * Shutdown the connection for writing without closing the channel.
+     *
+     * <p> Once shutdown for writing then further attempts to write to the
+     * channel will throw {@link ClosedChannelException}. If the output side of
+     * the connection is already shutdown then invoking this method has no
+     * effect. The effect on an outstanding write operation is system dependent
+     * and therefore not specified.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownOutput() throws IOException;
+
+    // -- state --
+
+    /**
+     * Returns the remote address to which this channel's socket is connected.
+     *
+     * <p> Where the channel is bound and connected to an Internet Protocol
+     * socket address then the return value from this method is of type {@link
+     * java.net.InetSocketAddress}.
+     *
+     * @return  The remote address; {@code null} if the channel's socket is not
+     *          connected
+     *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract SocketAddress getRemoteAddress() throws IOException;
+
+    // -- asynchronous operations --
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method initiates an operation to connect this channel. The
+     * {@code handler} parameter is a completion handler that is invoked when
+     * the connection is successfully established or connection cannot be
+     * established. If the connection cannot be established then the channel is
+     * closed.
+     *
+     * <p> This method performs exactly the same security checks as the {@link
+     * java.net.Socket} class.  That is, if a security manager has been
+     * installed then this method verifies that its {@link
+     * java.lang.SecurityManager#checkConnect checkConnect} method permits
+     * connecting to the address and port number of the given remote endpoint.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     *
+     * @see #getRemoteAddress
+     */
+    public abstract <A> void connect(SocketAddress remote,
+                                     A attachment,
+                                     CompletionHandler<Void,? super A> handler);
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method initiates an operation to connect this channel. This
+     * method behaves in exactly the same manner as the {@link
+     * #connect(SocketAddress, Object, CompletionHandler)} method except that
+     * instead of specifying a completion handler, this method returns a {@code
+     * Future} representing the pending result. The {@code Future}'s {@link
+     * Future#get() get} method returns {@code null} on successful completion.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     */
+    public abstract Future<Void> connect(SocketAddress remote);
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates an asynchronous read operation to read a
+     * sequence of bytes from this channel into the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the read
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes read or {@code -1} if no bytes could be
+     * read because the channel has reached end-of-stream.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffer, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   timeout
+     *          The maximum time for the I/O operation to complete
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    public abstract <A> void read(ByteBuffer dst,
+                                  long timeout,
+                                  TimeUnit unit,
+                                  A attachment,
+                                  CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    @Override
+    public final <A> void read(ByteBuffer dst,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
+    {
+        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+    @Override
+    public abstract Future<Integer> read(ByteBuffer dst);
+
+    /**
+     * Reads a sequence of bytes from this channel into a subsequence of the
+     * given buffers. This operation, sometimes called a <em>scattering read</em>,
+     * is often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body. The {@code handler} parameter is a completion
+     * handler that is invoked when the read operation completes (or fails). The
+     * result passed to the completion handler is the number of bytes read or
+     * {@code -1} if no bytes could be read because the channel has reached
+     * end-of-stream.
+     *
+     * <p> This method initiates a read of up to <i>r</i> bytes from this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * dsts[offset].remaining()
+     *     + dsts[offset+1].remaining()
+     *     + ... + dsts[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the read is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>dsts[offset].remaining()</tt> bytes of this sequence
+     * are transferred into buffer <tt>dsts[offset]</tt>, up to the next
+     * <tt>dsts[offset+1].remaining()</tt> bytes are transferred into buffer
+     * <tt>dsts[offset+1]</tt>, and so forth, until the entire byte sequence
+     * is transferred into the given buffers.  As many bytes as possible are
+     * transferred into each buffer, hence the final position of each updated
+     * buffer, except the last updated buffer, is guaranteed to be equal to
+     * that buffer's limit. The underlying operating system may impose a limit
+     * on the number of buffers that may be used in an I/O operation. Where the
+     * number of buffers (with bytes remaining), exceeds this limit, then the
+     * I/O operation is performed with the maximum number of buffers allowed by
+     * the operating system.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffers, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   dsts
+     *          The buffers into which bytes are to be transferred
+     * @param   offset
+     *          The offset within the buffer array of the first buffer into which
+     *          bytes are to be transferred; must be non-negative and no larger than
+     *          {@code dsts.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code dsts.length - offset}
+     * @param   timeout
+     *          The maximum time for the I/O operation to complete
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  IllegalArgumentException
+     *          If the buffer is read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    public abstract <A> void read(ByteBuffer[] dsts,
+                                  int offset,
+                                  int length,
+                                  long timeout,
+                                  TimeUnit unit,
+                                  A attachment,
+                                  CompletionHandler<Long,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates an asynchronous write operation to write a
+     * sequence of bytes to this channel from the given buffer. The {@code
+     * handler} parameter is a completion handler that is invoked when the write
+     * operation completes (or fails). The result passed to the completion
+     * handler is the number of bytes written.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffer, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     * @param   timeout
+     *          The maximum time for the I/O operation to complete
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    public abstract <A> void write(ByteBuffer src,
+                                   long timeout,
+                                   TimeUnit unit,
+                                   A attachment,
+                                   CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  WritePendingException          {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    @Override
+    public final <A> void write(ByteBuffer src,
+                                A attachment,
+                                CompletionHandler<Integer,? super A> handler)
+
+    {
+        write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  WritePendingException       {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+    @Override
+    public abstract Future<Integer> write(ByteBuffer src);
+
+    /**
+     * Writes a sequence of bytes to this channel from a subsequence of the given
+     * buffers. This operation, sometimes called a <em>gathering write</em>, is
+     * often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body. The {@code handler} parameter is a completion
+     * handler that is invoked when the write operation completes (or fails).
+     * The result passed to the completion handler is the number of bytes written.
+     *
+     * <p> This method initiates a write of up to <i>r</i> bytes to this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * srcs[offset].remaining()
+     *     + srcs[offset+1].remaining()
+     *     + ... + srcs[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the write is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>srcs[offset].remaining()</tt> bytes of this sequence
+     * are written from buffer <tt>srcs[offset]</tt>, up to the next
+     * <tt>srcs[offset+1].remaining()</tt> bytes are written from buffer
+     * <tt>srcs[offset+1]</tt>, and so forth, until the entire byte sequence is
+     * written.  As many bytes as possible are written from each buffer, hence
+     * the final position of each updated buffer, except the last updated
+     * buffer, is guaranteed to be equal to that buffer's limit. The underlying
+     * operating system may impose a limit on the number of buffers that may be
+     * used in an I/O operation. Where the number of buffers (with bytes
+     * remaining), exceeds this limit, then the I/O operation is performed with
+     * the maximum number of buffers allowed by the operating system.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffers, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   srcs
+     *          The buffers from which bytes are to be retrieved
+     * @param   offset
+     *          The offset within the buffer array of the first buffer from which
+     *          bytes are to be retrieved; must be non-negative and no larger
+     *          than {@code srcs.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code srcs.length - offset}
+     * @param   timeout
+     *          The maximum time for the I/O operation to complete
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group has terminated
+     */
+    public abstract <A> void write(ByteBuffer[] srcs,
+                                   int offset,
+                                   int length,
+                                   long timeout,
+                                   TimeUnit unit,
+                                   A attachment,
+                                   CompletionHandler<Long,? super A> handler);
+}
diff --git a/ojluni/src/main/java/java/nio/channels/Channels.java b/ojluni/src/main/java/java/nio/channels/Channels.java
index 204eafd..f27f0ab 100755
--- a/ojluni/src/main/java/java/nio/channels/Channels.java
+++ b/ojluni/src/main/java/java/nio/channels/Channels.java
@@ -181,6 +181,155 @@
 
             };
     }
+
+    /**
+     * Constructs a stream that reads bytes from the given channel.
+     *
+     * <p> The stream will not be buffered, and it will not support the {@link
+     * InputStream#mark mark} or {@link InputStream#reset reset} methods.  The
+     * stream will be safe for access by multiple concurrent threads.  Closing
+     * the stream will in turn cause the channel to be closed.  </p>
+     *
+     * @param  ch
+     *         The channel from which bytes will be read
+     *
+     * @return  A new input stream
+     *
+     * @since 1.7
+     */
+    public static InputStream newInputStream(final AsynchronousByteChannel ch) {
+        checkNotNull(ch, "ch");
+        return new InputStream() {
+
+            private ByteBuffer bb = null;
+            private byte[] bs = null;           // Invoker's previous array
+            private byte[] b1 = null;
+
+            @Override
+            public synchronized int read() throws IOException {
+                if (b1 == null)
+                    b1 = new byte[1];
+                int n = this.read(b1);
+                if (n == 1)
+                    return b1[0] & 0xff;
+                return -1;
+            }
+
+            @Override
+            public synchronized int read(byte[] bs, int off, int len)
+                throws IOException
+            {
+                if ((off < 0) || (off > bs.length) || (len < 0) ||
+                    ((off + len) > bs.length) || ((off + len) < 0)) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0)
+                    return 0;
+
+                ByteBuffer bb = ((this.bs == bs)
+                                 ? this.bb
+                                 : ByteBuffer.wrap(bs));
+                bb.position(off);
+                bb.limit(Math.min(off + len, bb.capacity()));
+                this.bb = bb;
+                this.bs = bs;
+
+                boolean interrupted = false;
+                try {
+                    for (;;) {
+                        try {
+                            return ch.read(bb).get();
+                        } catch (ExecutionException ee) {
+                            throw new IOException(ee.getCause());
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
+                        }
+                    }
+                } finally {
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
+                }
+            }
+
+            @Override
+            public void close() throws IOException {
+                ch.close();
+            }
+        };
+    }
+
+    /**
+     * Constructs a stream that writes bytes to the given channel.
+     *
+     * <p> The stream will not be buffered. The stream will be safe for access
+     * by multiple concurrent threads.  Closing the stream will in turn cause
+     * the channel to be closed.  </p>
+     *
+     * @param  ch
+     *         The channel to which bytes will be written
+     *
+     * @return  A new output stream
+     *
+     * @since 1.7
+     */
+    public static OutputStream newOutputStream(final AsynchronousByteChannel ch) {
+        checkNotNull(ch, "ch");
+        return new OutputStream() {
+
+            private ByteBuffer bb = null;
+            private byte[] bs = null;   // Invoker's previous array
+            private byte[] b1 = null;
+
+            @Override
+            public synchronized void write(int b) throws IOException {
+               if (b1 == null)
+                    b1 = new byte[1];
+                b1[0] = (byte)b;
+                this.write(b1);
+            }
+
+            @Override
+            public synchronized void write(byte[] bs, int off, int len)
+                throws IOException
+            {
+                if ((off < 0) || (off > bs.length) || (len < 0) ||
+                    ((off + len) > bs.length) || ((off + len) < 0)) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0) {
+                    return;
+                }
+                ByteBuffer bb = ((this.bs == bs)
+                                 ? this.bb
+                                 : ByteBuffer.wrap(bs));
+                bb.limit(Math.min(off + len, bb.capacity()));
+                bb.position(off);
+                this.bb = bb;
+                this.bs = bs;
+
+                boolean interrupted = false;
+                try {
+                    while (bb.remaining() > 0) {
+                        try {
+                            ch.write(bb).get();
+                        } catch (ExecutionException ee) {
+                            throw new IOException(ee.getCause());
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
+                        }
+                    }
+                } finally {
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
+                }
+            }
+
+            @Override
+            public void close() throws IOException {
+                ch.close();
+            }
+        };
+    }
+
+
     // -- Channels from streams --
 
     /**
diff --git a/ojluni/src/main/java/java/nio/channels/CompletionHandler.java b/ojluni/src/main/java/java/nio/channels/CompletionHandler.java
new file mode 100755
index 0000000..2574dbf
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/CompletionHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+/**
+ * A handler for consuming the result of an asynchronous I/O operation.
+ *
+ * <p> The asynchronous channels defined in this package allow a completion
+ * handler to be specified to consume the result of an asynchronous operation.
+ * The {@link #completed completed} method is invoked when the I/O operation
+ * completes successfully. The {@link #failed failed} method is invoked if the
+ * I/O operations fails. The implementations of these methods should complete
+ * in a timely manner so as to avoid keeping the invoking thread from dispatching
+ * to other completion handlers.
+ *
+ * @param   <V>     The result type of the I/O operation
+ * @param   <A>     The type of the object attached to the I/O operation
+ *
+ * @since 1.7
+ */
+
+public interface CompletionHandler<V,A> {
+
+    /**
+     * Invoked when an operation has completed.
+     *
+     * @param   result
+     *          The result of the I/O operation.
+     * @param   attachment
+     *          The object attached to the I/O operation when it was initiated.
+     */
+    void completed(V result, A attachment);
+
+    /**
+     * Invoked when an operation fails.
+     *
+     * @param   exc
+     *          The exception to indicate why the I/O operation failed
+     * @param   attachment
+     *          The object attached to the I/O operation when it was initiated.
+     */
+    void failed(Throwable exc, A attachment);
+}
diff --git a/ojluni/src/main/java/java/nio/channels/DatagramChannel.java b/ojluni/src/main/java/java/nio/channels/DatagramChannel.java
index 3e49074..f4a6110 100755
--- a/ojluni/src/main/java/java/nio/channels/DatagramChannel.java
+++ b/ojluni/src/main/java/java/nio/channels/DatagramChannel.java
@@ -112,7 +112,7 @@
 
 public abstract class DatagramChannel
     extends AbstractSelectableChannel
-    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
+    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
 {
 
     /**
diff --git a/ojluni/src/main/java/java/nio/channels/IllegalChannelGroupException.java b/ojluni/src/main/java/java/nio/channels/IllegalChannelGroupException.java
new file mode 100644
index 0000000..dd47105
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/IllegalChannelGroupException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Unchecked exception thrown when an attempt is made to open a channel
+ * in a group that was not created by the same provider. 
+ *
+ * @since 1.7
+ */
+
+public class IllegalChannelGroupException
+    extends IllegalArgumentException
+{
+
+    private static final long serialVersionUID = -2495041211157744253L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public IllegalChannelGroupException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/InterruptedByTimeoutException.java b/ojluni/src/main/java/java/nio/channels/InterruptedByTimeoutException.java
new file mode 100644
index 0000000..ae2018d
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/InterruptedByTimeoutException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Checked exception received by a thread when a timeout elapses before an
+ * asynchronous operation completes.
+ *
+ * @since 1.7
+ */
+
+public class InterruptedByTimeoutException
+    extends java.io.IOException
+{
+
+    private static final long serialVersionUID = -4268008601014042947L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public InterruptedByTimeoutException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/MembershipKey.java b/ojluni/src/main/java/java/nio/channels/MembershipKey.java
new file mode 100755
index 0000000..ea7536a
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/MembershipKey.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+
+/**
+ * A token representing the membership of an Internet Protocol (IP) multicast
+ * group.
+ *
+ * <p> A membership key may represent a membership to receive all datagrams sent
+ * to the group, or it may be <em>source-specific</em>, meaning that it
+ * represents a membership that receives only datagrams from a specific source
+ * address. Whether or not a membership key is source-specific may be determined
+ * by invoking its {@link #sourceAddress() sourceAddress} method.
+ *
+ * <p> A membership key is valid upon creation and remains valid until the
+ * membership is dropped by invoking the {@link #drop() drop} method, or
+ * the channel is closed. The validity of the membership key may be tested
+ * by invoking its {@link #isValid() isValid} method.
+ *
+ * <p> Where a membership key is not source-specific and the underlying operation
+ * system supports source filtering, then the {@link #block block} and {@link
+ * #unblock unblock} methods can be used to block or unblock multicast datagrams
+ * from particular source addresses.
+ *
+ * @see MulticastChannel
+ *
+ * @since 1.7
+ */
+public abstract class MembershipKey {
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected MembershipKey() {
+    }
+
+    /**
+     * Tells whether or not this membership is valid.
+     *
+     * <p> A multicast group membership is valid upon creation and remains
+     * valid until the membership is dropped by invoking the {@link #drop() drop}
+     * method, or the channel is closed.
+     *
+     * @return  {@code true} if this membership key is valid, {@code false}
+     *          otherwise
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Drop membership.
+     *
+     * <p> If the membership key represents a membership to receive all datagrams
+     * then the membership is dropped and the channel will no longer receive any
+     * datagrams sent to the group. If the membership key is source-specific
+     * then the channel will no longer receive datagrams sent to the group from
+     * that source address.
+     *
+     * <p> After membership is dropped it may still be possible to receive
+     * datagrams sent to the group. This can arise when datagrams are waiting to
+     * be received in the socket's receive buffer. After membership is dropped
+     * then the channel may {@link MulticastChannel#join join} the group again
+     * in which case a new membership key is returned.
+     *
+     * <p> Upon return, this membership object will be {@link #isValid() invalid}.
+     * If the multicast group membership is already invalid then invoking this
+     * method has no effect. Once a multicast group membership is invalid,
+     * it remains invalid forever.
+     */
+    public abstract void drop();
+
+    /**
+     * Block multicast datagrams from the given source address.
+     *
+     * <p> If this membership key is not source-specific, and the underlying
+     * operating system supports source filtering, then this method blocks
+     * multicast datagrams from the given source address. If the given source
+     * address is already blocked then this method has no effect.
+     * After a source address is blocked it may still be possible to receive
+     * datagams from that source. This can arise when datagrams are waiting to
+     * be received in the socket's receive buffer.
+     *
+     * @param   source
+     *          The source address to block
+     *
+     * @return  This membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code source} parameter is not a unicast address or
+     *          is not the same address type as the multicast group
+     * @throws  IllegalStateException
+     *          If this membership key is source-specific or is no longer valid
+     * @throws  UnsupportedOperationException
+     *          If the underlying operating system does not support source
+     *          filtering
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract MembershipKey block(InetAddress source) throws IOException;
+
+    /**
+     * Unblock multicast datagrams from the given source address that was
+     * previously blocked using the {@link #block(InetAddress) block} method.
+     *
+     * @param   source
+     *          The source address to unblock
+     *
+     * @return  This membership key
+     *
+     * @throws  IllegalStateException
+     *          If the given source address is not currently blocked or the
+     *          membership key is no longer valid
+     */
+    public abstract MembershipKey unblock(InetAddress source);
+
+    /**
+     * Returns the channel for which this membership key was created. This
+     * method will continue to return the channel even after the membership
+     * becomes {@link #isValid invalid}.
+     *
+     * @return  the channel
+     */
+    public abstract MulticastChannel channel();
+
+    /**
+     * Returns the multicast group for which this membership key was created.
+     * This method will continue to return the group even after the membership
+     * becomes {@link #isValid invalid}.
+     *
+     * @return  the multicast group
+     */
+    public abstract InetAddress group();
+
+    /**
+     * Returns the network interface for which this membership key was created.
+     * This method will continue to return the network interface even after the
+     * membership becomes {@link #isValid invalid}.
+     *
+     * @return  the network interface
+     */
+    public abstract NetworkInterface networkInterface();
+
+    /**
+     * Returns the source address if this membership key is source-specific,
+     * or {@code null} if this membership is not source-specific.
+     *
+     * @return  The source address if this membership key is source-specific,
+     *          otherwise {@code null}
+     */
+    public abstract InetAddress sourceAddress();
+}
diff --git a/ojluni/src/main/java/java/nio/channels/MulticastChannel.java b/ojluni/src/main/java/java/nio/channels/MulticastChannel.java
new file mode 100755
index 0000000..5b61f77
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/MulticastChannel.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+import java.net.ProtocolFamily;             // javadoc
+import java.net.StandardProtocolFamily;     // javadoc
+import java.net.StandardSocketOptions;      // javadoc
+
+/**
+ * A network channel that supports Internet Protocol (IP) multicasting.
+ *
+ * <p> IP multicasting is the transmission of IP datagrams to members of
+ * a <em>group</em> that is zero or more hosts identified by a single destination
+ * address.
+ *
+ * <p> In the case of a channel to an {@link StandardProtocolFamily#INET IPv4} socket,
+ * the underlying operating system supports <a href="http://www.ietf.org/rfc/rfc2236.txt">
+ * <i>RFC&nbsp;2236: Internet Group Management Protocol, Version 2 (IGMPv2)</i></a>.
+ * It may optionally support source filtering as specified by <a
+ * href="http://www.ietf.org/rfc/rfc3376.txt"> <i>RFC&nbsp;3376: Internet Group
+ * Management Protocol, Version 3 (IGMPv3)</i></a>.
+ * For channels to an {@link StandardProtocolFamily#INET6 IPv6} socket, the equivalent
+ * standards are <a href="http://www.ietf.org/rfc/rfc2710.txt"> <i>RFC&nbsp;2710:
+ * Multicast Listener Discovery (MLD) for IPv6</i></a> and <a
+ * href="http://www.ietf.org/rfc/rfc3810.txt"> <i>RFC&nbsp;3810: Multicast Listener
+ * Discovery Version 2 (MLDv2) for IPv6</i></a>.
+ *
+ * <p> The {@link #join(InetAddress,NetworkInterface)} method is used to
+ * join a group and receive all multicast datagrams sent to the group. A channel
+ * may join several multicast groups and may join the same group on several
+ * {@link NetworkInterface interfaces}. Membership is dropped by invoking the {@link
+ * MembershipKey#drop drop} method on the returned {@link MembershipKey}. If the
+ * underlying platform supports source filtering then the {@link MembershipKey#block
+ * block} and {@link MembershipKey#unblock unblock} methods can be used to block or
+ * unblock multicast datagrams from particular source addresses.
+ *
+ * <p> The {@link #join(InetAddress,NetworkInterface,InetAddress)} method
+ * is used to begin receiving datagrams sent to a group whose source address matches
+ * a given source address. This method throws {@link UnsupportedOperationException}
+ * if the underlying platform does not support source filtering.  Membership is
+ * <em>cumulative</em> and this method may be invoked again with the same group
+ * and interface to allow receiving datagrams from other source addresses. The
+ * method returns a {@link MembershipKey} that represents membership to receive
+ * datagrams from the given source address. Invoking the key's {@link
+ * MembershipKey#drop drop} method drops membership so that datagrams from the
+ * source address can no longer be received.
+ *
+ * <h4>Platform dependencies</h4>
+ *
+ * The multicast implementation is intended to map directly to the native
+ * multicasting facility. Consequently, the following items should be considered
+ * when developing an application that receives IP multicast datagrams:
+ *
+ * <ol>
+ *
+ * <li><p> The creation of the channel should specify the {@link ProtocolFamily}
+ * that corresponds to the address type of the multicast groups that the channel
+ * will join. There is no guarantee that a channel to a socket in one protocol
+ * family can join and receive multicast datagrams when the address of the
+ * multicast group corresponds to another protocol family. For example, it is
+ * implementation specific if a channel to an {@link StandardProtocolFamily#INET6 IPv6}
+ * socket can join an {@link StandardProtocolFamily#INET IPv4} multicast group and receive
+ * multicast datagrams sent to the group. </p></li>
+ *
+ * <li><p> The channel's socket should be bound to the {@link
+ * InetAddress#isAnyLocalAddress wildcard} address. If the socket is bound to
+ * a specific address, rather than the wildcard address then it is implementation
+ * specific if multicast datagrams are received by the socket. </p></li>
+ *
+ * <li><p> The {@link StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} option should be
+ * enabled prior to {@link NetworkChannel#bind binding} the socket. This is
+ * required to allow multiple members of the group to bind to the same
+ * address. </p></li>
+ *
+ * </ol>
+ *
+ * <p> <b>Usage Example:</b>
+ * <pre>
+ *     // join multicast group on this interface, and also use this
+ *     // interface for outgoing multicast datagrams
+ *     NetworkInterface ni = NetworkInterface.getByName("hme0");
+ *
+ *     DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
+ *         .setOption(StandardSocketOptions.SO_REUSEADDR, true)
+ *         .bind(new InetSocketAddress(5000))
+ *         .setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
+ *
+ *     InetAddress group = InetAddress.getByName("225.4.5.6");
+ *
+ *     MembershipKey key = dc.join(group, ni);
+ * </pre>
+ *
+ * @since 1.7
+ */
+
+public interface MulticastChannel
+    extends NetworkChannel
+{
+    /**
+     * Closes this channel.
+     *
+     * <p> If the channel is a member of a multicast group then the membership
+     * is {@link MembershipKey#drop dropped}. Upon return, the {@link
+     * MembershipKey membership-key} will be {@link MembershipKey#isValid
+     * invalid}.
+     *
+     * <p> This method otherwise behaves exactly as specified by the {@link
+     * Channel} interface.
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    @Override void close() throws IOException;
+
+    /**
+     * Joins a multicast group to begin receiving all datagrams sent to the group,
+     * returning a membership key.
+     *
+     * <p> If this channel is currently a member of the group on the given
+     * interface to receive all datagrams then the membership key, representing
+     * that membership, is returned. Otherwise this channel joins the group and
+     * the resulting new membership key is returned. The resulting membership key
+     * is not {@link MembershipKey#sourceAddress source-specific}.
+     *
+     * <p> A multicast channel may join several multicast groups, including
+     * the same group on more than one interface. An implementation may impose a
+     * limit on the number of groups that may be joined at the same time.
+     *
+     * @param   group
+     *          The multicast address to join
+     * @param   interf
+     *          The network interface on which to join the group
+     *
+     * @return  The membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the group parameter is not a {@link InetAddress#isMulticastAddress
+     *          multicast} address, or the group parameter is an address type
+     *          that is not supported by this channel
+     * @throws  IllegalStateException
+     *          If the channel already has source-specific membership of the
+     *          group on the interface
+     * @throws  UnsupportedOperationException
+     *          If the channel's socket is not an Internet Protocol socket
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set, and its
+     *          {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
+     *          method denies access to the multiast group
+     */
+    MembershipKey join(InetAddress group, NetworkInterface interf)
+        throws IOException;
+
+    /**
+     * Joins a multicast group to begin receiving datagrams sent to the group
+     * from a given source address.
+     *
+     * <p> If this channel is currently a member of the group on the given
+     * interface to receive datagrams from the given source address then the
+     * membership key, representing that membership, is returned. Otherwise this
+     * channel joins the group and the resulting new membership key is returned.
+     * The resulting membership key is {@link MembershipKey#sourceAddress
+     * source-specific}.
+     *
+     * <p> Membership is <em>cumulative</em> and this method may be invoked
+     * again with the same group and interface to allow receiving datagrams sent
+     * by other source addresses to the group.
+     *
+     * @param   group
+     *          The multicast address to join
+     * @param   interf
+     *          The network interface on which to join the group
+     * @param   source
+     *          The source address
+     *
+     * @return  The membership key
+     *
+     * @throws  IllegalArgumentException
+     *          If the group parameter is not a {@link
+     *          InetAddress#isMulticastAddress multicast} address, the
+     *          source parameter is not a unicast address, the group
+     *          parameter is an address type that is not supported by this channel,
+     *          or the source parameter is not the same address type as the group
+     * @throws  IllegalStateException
+     *          If the channel is currently a member of the group on the given
+     *          interface to receive all datagrams
+     * @throws  UnsupportedOperationException
+     *          If the channel's socket is not an Internet Protocol socket or
+     *          source filtering is not supported
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     * @throws  SecurityException
+     *          If a security manager is set, and its
+     *          {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
+     *          method denies access to the multiast group
+     */
+    MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
+        throws IOException;
+}
diff --git a/ojluni/src/main/java/java/nio/channels/ReadPendingException.java b/ojluni/src/main/java/java/nio/channels/ReadPendingException.java
new file mode 100644
index 0000000..770c9de
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/ReadPendingException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Unchecked exception thrown when an attempt is made to read from an
+ * asynchronous socket channel and a previous read has not completed.
+ *
+ * @since 1.7
+ */
+
+public class ReadPendingException
+    extends IllegalStateException
+{
+
+    private static final long serialVersionUID = 1986315242191227217L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ReadPendingException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java b/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
index 127fb5b..63ed42f 100755
--- a/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
+++ b/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
@@ -138,7 +138,7 @@
      * @return  This channel
      *
      * @throws  AlreadyBoundException               {@inheritDoc}
-     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  UnresolvedAddressException
      * @throws  ClosedChannelException              {@inheritDoc}
      * @throws  IOException                         {@inheritDoc}
      * @throws  SecurityException
diff --git a/ojluni/src/main/java/java/nio/channels/ShutdownChannelGroupException.java b/ojluni/src/main/java/java/nio/channels/ShutdownChannelGroupException.java
new file mode 100644
index 0000000..b4e4b7d
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/ShutdownChannelGroupException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Unchecked exception thrown when an attempt is made to construct a channel in 
+ * a group that is shutdown or the completion handler for an I/O operation 
+ * cannot be invoked because the channel group has terminated.
+ *
+ * @since 1.7
+ */
+
+public class ShutdownChannelGroupException
+    extends IllegalStateException
+{
+
+    private static final long serialVersionUID = -3903801676350154157L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public ShutdownChannelGroupException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/WritePendingException.java b/ojluni/src/main/java/java/nio/channels/WritePendingException.java
new file mode 100644
index 0000000..8957702
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/WritePendingException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// -- This file was mechanically generated: Do not edit! -- //
+
+package java.nio.channels;
+
+
+/**
+ * Unchecked exception thrown when an attempt is made to write to an
+ * asynchronous socket channel and a previous write has not completed.
+ *
+ * @since 1.7
+ */
+
+public class WritePendingException
+    extends IllegalStateException
+{
+
+    private static final long serialVersionUID = 7031871839266032276L;
+
+    /**
+     * Constructs an instance of this class.
+     */
+    public WritePendingException() { }
+
+}
diff --git a/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java b/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java
new file mode 100755
index 0000000..827a2c5
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.channels.spi;
+
+import java.nio.channels.*;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+import java.util.ServiceConfigurationError;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Service-provider class for asynchronous channels.
+ *
+ * <p> An asynchronous channel provider is a concrete subclass of this class that
+ * has a zero-argument constructor and implements the abstract methods specified
+ * below.  A given invocation of the Java virtual machine maintains a single
+ * system-wide default provider instance, which is returned by the {@link
+ * #provider() provider} method.  The first invocation of that method will locate
+ * the default provider as specified below.
+ *
+ * <p> All of the methods in this class are safe for use by multiple concurrent
+ * threads.  </p>
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousChannelProvider {
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(new RuntimePermission("asynchronousChannelProvider"));
+        return null;
+    }
+    private AsynchronousChannelProvider(Void ignore) { }
+
+    /**
+     * Initializes a new instance of this class.
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed and it denies
+     *          {@link RuntimePermission}<tt>("asynchronousChannelProvider")</tt>
+     */
+    protected AsynchronousChannelProvider() {
+        this(checkPermission());
+    }
+
+    // lazy initialization of default provider
+    private static class ProviderHolder {
+        static final AsynchronousChannelProvider provider = load();
+
+        private static AsynchronousChannelProvider load() {
+            return AccessController
+                .doPrivileged(new PrivilegedAction<AsynchronousChannelProvider>() {
+                    public AsynchronousChannelProvider run() {
+                        AsynchronousChannelProvider p;
+                        p = loadProviderFromProperty();
+                        if (p != null)
+                            return p;
+                        p = loadProviderAsService();
+                        if (p != null)
+                            return p;
+                        return sun.nio.ch.DefaultAsynchronousChannelProvider.create();
+                    }});
+        }
+
+        private static AsynchronousChannelProvider loadProviderFromProperty() {
+            String cn = System.getProperty("java.nio.channels.spi.AsynchronousChannelProvider");
+            if (cn == null)
+                return null;
+            try {
+                Class<?> c = Class.forName(cn, true,
+                                           ClassLoader.getSystemClassLoader());
+                return (AsynchronousChannelProvider)c.newInstance();
+            } catch (ClassNotFoundException x) {
+                throw new ServiceConfigurationError(null, x);
+            } catch (IllegalAccessException x) {
+                throw new ServiceConfigurationError(null, x);
+            } catch (InstantiationException x) {
+                throw new ServiceConfigurationError(null, x);
+            } catch (SecurityException x) {
+                throw new ServiceConfigurationError(null, x);
+            }
+        }
+
+        private static AsynchronousChannelProvider loadProviderAsService() {
+            ServiceLoader<AsynchronousChannelProvider> sl =
+                ServiceLoader.load(AsynchronousChannelProvider.class,
+                                   ClassLoader.getSystemClassLoader());
+            Iterator<AsynchronousChannelProvider> i = sl.iterator();
+            for (;;) {
+                try {
+                    return (i.hasNext()) ? i.next() : null;
+                } catch (ServiceConfigurationError sce) {
+                    if (sce.getCause() instanceof SecurityException) {
+                        // Ignore the security exception, try the next provider
+                        continue;
+                    }
+                    throw sce;
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the system-wide default asynchronous channel provider for this
+     * invocation of the Java virtual machine.
+     *
+     * <p> The first invocation of this method locates the default provider
+     * object as follows: </p>
+     *
+     * <ol>
+     *
+     *   <li><p> If the system property
+     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> is defined
+     *   then it is taken to be the fully-qualified name of a concrete provider class.
+     *   The class is loaded and instantiated; if this process fails then an
+     *   unspecified error is thrown.  </p></li>
+     *
+     *   <li><p> If a provider class has been installed in a jar file that is
+     *   visible to the system class loader, and that jar file contains a
+     *   provider-configuration file named
+     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> in the resource
+     *   directory <tt>META-INF/services</tt>, then the first class name
+     *   specified in that file is taken.  The class is loaded and
+     *   instantiated; if this process fails then an unspecified error is
+     *   thrown.  </p></li>
+     *
+     *   <li><p> Finally, if no provider has been specified by any of the above
+     *   means then the system-default provider class is instantiated and the
+     *   result is returned.  </p></li>
+     *
+     * </ol>
+     *
+     * <p> Subsequent invocations of this method return the provider that was
+     * returned by the first invocation.  </p>
+     *
+     * @return  The system-wide default AsynchronousChannel provider
+     */
+    public static AsynchronousChannelProvider provider() {
+        return ProviderHolder.provider;
+    }
+
+    /**
+     * Constructs a new asynchronous channel group with a fixed thread pool.
+     *
+     * @param   nThreads
+     *          The number of threads in the pool
+     * @param   threadFactory
+     *          The factory to use when creating new threads
+     *
+     * @throws  IllegalArgumentException
+     *          If {@code nThreads <= 0}
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see AsynchronousChannelGroup#withFixedThreadPool
+     */
+    public abstract AsynchronousChannelGroup
+        openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) throws IOException;
+
+    /**
+     * Constructs a new asynchronous channel group with the given thread pool.
+     *
+     * @param   executor
+     *          The thread pool
+     * @param   initialSize
+     *          A value {@code >=0} or a negative value for implementation
+     *          specific default
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @see AsynchronousChannelGroup#withCachedThreadPool
+     */
+    public abstract AsynchronousChannelGroup
+        openAsynchronousChannelGroup(ExecutorService executor, int initialSize) throws IOException;
+
+    /**
+     * Opens an asynchronous server-socket channel.
+     *
+     * @param   group
+     *          The group to which the channel is bound, or {@code null} to
+     *          bind to the default group
+     *
+     * @return  The new channel
+     *
+     * @throws  IllegalChannelGroupException
+     *          If the provider that created the group differs from this provider
+     * @throws  ShutdownChannelGroupException
+     *          The group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
+        (AsynchronousChannelGroup group) throws IOException;
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * @param   group
+     *          The group to which the channel is bound, or {@code null} to
+     *          bind to the default group
+     *
+     * @return  The new channel
+     *
+     * @throws  IllegalChannelGroupException
+     *          If the provider that created the group differs from this provider
+     * @throws  ShutdownChannelGroupException
+     *          The group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
+        (AsynchronousChannelGroup group) throws IOException;
+}
diff --git a/ojluni/src/main/java/java/security/Key.java b/ojluni/src/main/java/java/security/Key.java
index 2df0f3e..9322710 100755
--- a/ojluni/src/main/java/java/security/Key.java
+++ b/ojluni/src/main/java/java/security/Key.java
@@ -83,7 +83,7 @@
  * <p> A Key should use KeyRep as its serialized representation.
  * Note that a serialized Key may contain sensitive information
  * which should not be exposed in untrusted environments.  See the
- * <a href="../../../platform/serialization/spec/security.html">
+ * <a href="{@docRoot}/../platform/serialization/spec/security.html">
  * Security Appendix</a>
  * of the Serialization Specification for more information.
  *
diff --git a/ojluni/src/main/java/java/security/KeyRep.java b/ojluni/src/main/java/java/security/KeyRep.java
index b7d94f1..20e3e2f 100755
--- a/ojluni/src/main/java/java/security/KeyRep.java
+++ b/ojluni/src/main/java/java/security/KeyRep.java
@@ -41,7 +41,7 @@
  *
  * Note that a serialized Key may contain sensitive information
  * which should not be exposed in untrusted environments.  See the
- * <a href="../../../platform/serialization/spec/security.html">
+ * <a href="{@docRoot}/../platform/serialization/spec/security.html">
  * Security Appendix</a>
  * of the Serialization Specification for more information.
  *
diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java
index 6493f29..75cbeb8 100755
--- a/ojluni/src/main/java/java/security/Provider.java
+++ b/ojluni/src/main/java/java/security/Provider.java
@@ -627,7 +627,7 @@
             if (typeAndAlg == null) {
                 return;
             }
-            String type = getEngineName(typeAndAlg[0]);
+            String type = typeAndAlg[0];
             String aliasAlg = typeAndAlg[1].intern();
             ServiceKey key = new ServiceKey(type, stdAlg, true);
             Service s = legacyMap.get(key);
@@ -647,7 +647,7 @@
             int i = typeAndAlg[1].indexOf(' ');
             if (i == -1) {
                 // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA");
-                String type = getEngineName(typeAndAlg[0]);
+                String type = typeAndAlg[0];
                 String stdAlg = typeAndAlg[1].intern();
                 String className = value;
                 ServiceKey key = new ServiceKey(type, stdAlg, true);
@@ -662,7 +662,7 @@
             } else { // attribute
                 // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
                 String attributeValue = value;
-                String type = getEngineName(typeAndAlg[0]);
+                String type = typeAndAlg[0];
                 String attributeString = typeAndAlg[1];
                 String stdAlg = attributeString.substring(0, i).intern();
                 String attributeName = attributeString.substring(i + 1);
@@ -766,7 +766,7 @@
      * it is replaced by the new service.
      * This method also places information about this service
      * in the provider's Hashtable values in the format described in the
-     * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
+     * <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
      * Java Cryptography Architecture API Specification &amp; Reference </a>.
      *
      * <p>Also, if there is a security manager, its
@@ -974,8 +974,10 @@
 
     private static void addEngine(String name, boolean sp, String paramName) {
         EngineDescription ed = new EngineDescription(name, sp, paramName);
-        // also index by canonical name to avoid toLowerCase() for some lookups
-        knownEngines.put(name.toLowerCase(ENGLISH), ed);
+        // NOTE: The original OpenJDK code supported case-insensitive lookups on the list
+        // of known engines.
+        //
+        // knownEngines.put(name.toLowerCase(ENGLISH), ed);
         knownEngines.put(name, ed);
     }
 
@@ -1026,17 +1028,6 @@
                             "java.lang.Object");
     }
 
-    // get the "standard" (mixed-case) engine name for arbitary case engine name
-    // if there is no known engine by that name, return s
-    private static String getEngineName(String s) {
-        // try original case first, usually correct
-        EngineDescription e = knownEngines.get(s);
-        if (e == null) {
-            e = knownEngines.get(s.toLowerCase(ENGLISH));
-        }
-        return (e == null) ? s : e.name;
-    }
-
     /**
      * The description of a security service. It encapsulates the properties
      * of a service and contains a factory method to obtain new implementation
@@ -1054,7 +1045,7 @@
      * suitable services and instantes them. The valid arguments to those
      * methods depend on the type of service. For the service types defined
      * within Java SE, see the
-     * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
+     * <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
      * Java Cryptography Architecture API Specification &amp; Reference </a>
      * for the valid values.
      * Note that components outside of Java SE can define additional types of
@@ -1140,7 +1131,8 @@
                 throw new NullPointerException();
             }
             this.provider = provider;
-            this.type = getEngineName(type);
+            // Android-changed.
+            this.type = type;
             this.algorithm = algorithm;
             this.className = className;
             if (aliases == null) {
@@ -1230,7 +1222,7 @@
          * instantiation in a different way.
          * For details and the values of constructorParameter that are
          * valid for the various types of services see the
-         * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
+         * <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
          * Java Cryptography Architecture API Specification &amp;
          * Reference</a>.
          *
@@ -1367,7 +1359,7 @@
          *
          * <p>For details and the values of parameter that are valid for the
          * various types of services see the top of this class and the
-         * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
+         * <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
          * Java Cryptography Architecture API Specification &amp;
          * Reference</a>.
          * Security providers can override it to implement their own test.
@@ -1530,5 +1522,4 @@
     public boolean isRegistered() {
         return registered;
     }
-
 }
diff --git a/ojluni/src/main/java/java/security/Security.java b/ojluni/src/main/java/java/security/Security.java
index 9b8cba9..b7f7ca9 100755
--- a/ojluni/src/main/java/java/security/Security.java
+++ b/ojluni/src/main/java/java/security/Security.java
@@ -59,19 +59,26 @@
     static {
         props = new Properties();
         boolean loadedProps = false;
-        Reader input = null;
+        InputStream is = null;
         try {
-            input = getSecurityPropertiesReader();
-            props.load(input);
-            loadedProps = true;
-        } catch (Exception ex) {
+            /*
+             * Android keeps the property file in a jar resource.
+             */
+            InputStream propStream = Security.class.getResourceAsStream("security.properties");
+            if (propStream == null) {
+                System.logE("Could not find 'security.properties'.");
+            } else {
+                is  = new BufferedInputStream(propStream);
+                props.load(is);
+                loadedProps = true;
+            }
+        } catch (IOException ex) {
             System.logE("Could not load 'security.properties'", ex);
         } finally {
-            if (input != null) {
+            if (is != null) {
                 try {
-                    input.close();
-                } catch (IOException ignored) {
-                }
+                    is.close();
+                } catch (IOException ignored) {}
             }
         }
 
@@ -80,13 +87,6 @@
         }
     }
 
-    // Do not refactor or change this name. The runtime provides a cutout for this method
-    // to let this class be compile time initializable.
-    private static Reader getSecurityPropertiesReader() throws Exception {
-        InputStream configStream = Security.class.getResourceAsStream("security.properties");
-        return new InputStreamReader(new BufferedInputStream(configStream), "ISO-8859-1");
-    }
-
     /*
      * Initialize to default values, if <java.home>/lib/java.security
      * is not found.
@@ -953,7 +953,7 @@
      * an empty Set if there is no provider that supports the
      * specified service or if serviceName is null. For a complete list
      * of Java cryptographic services, please see the
-     * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">Java
+     * <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">Java
      * Cryptography Architecture API Specification &amp; Reference</a>.
      * Note: the returned set is immutable.
      *
diff --git a/ojluni/src/main/java/java/sql/DriverManager.java b/ojluni/src/main/java/java/sql/DriverManager.java
index 0968db9..d1a9054 100755
--- a/ojluni/src/main/java/java/sql/DriverManager.java
+++ b/ojluni/src/main/java/java/sql/DriverManager.java
@@ -53,7 +53,7 @@
  * </pre>
  *<P> The <code>DriverManager</code> methods <code>getConnection</code> and
  * <code>getDrivers</code> have been enhanced to support the Java Standard Edition
- * <a href="../../../technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must
+ * <a href="{@docRoot}/../technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must
  * include the file <code>META-INF/services/java.sql.Driver</code>. This file contains the name of the JDBC drivers
  * implementation of <code>java.sql.Driver</code>.  For example, to load the <code>my.sql.Driver</code> class,
  * the <code>META-INF/services/java.sql.Driver</code> file would contain the entry:
diff --git a/ojluni/src/main/java/java/sql/package.html b/ojluni/src/main/java/java/sql/package.html
index 65d906b..673aa07 100755
--- a/ojluni/src/main/java/java/sql/package.html
+++ b/ojluni/src/main/java/java/sql/package.html
@@ -310,7 +310,7 @@
 <h2>Related Documentation</h2>
 
 <ul>
-  <li><a href="../../../technotes/guides/jdbc/getstart/GettingStartedTOC.fm.html">Getting Started</a>--overviews of the major interfaces
+  <li><a href="{@docRoot}/../technotes/guides/jdbc/getstart/GettingStartedTOC.fm.html">Getting Started</a>--overviews of the major interfaces
 <P>
   <li><a href="http://java.sun.com/docs/books/tutorial/jdbc">Chapters on the JDBC 
      API</a>--from the online version of <i>The Java Tutorial Continued</i>
diff --git a/ojluni/src/main/java/java/text/ChoiceFormat.java b/ojluni/src/main/java/java/text/ChoiceFormat.java
index f513cd9..ccbd24f 100755
--- a/ojluni/src/main/java/java/text/ChoiceFormat.java
+++ b/ojluni/src/main/java/java/text/ChoiceFormat.java
@@ -208,7 +208,7 @@
                     } else if (tempBuffer.equals("-\u221E")) {
                         startValue = Double.NEGATIVE_INFINITY;
                     } else {
-                        startValue = Double.valueOf(segments[0].toString()).doubleValue();
+                        startValue = Double.parseDouble(segments[0].toString());
                     }
                 } catch (Exception e) {
                     throw new IllegalArgumentException();
diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java
index b8eade3..bcc9e8b 100755
--- a/ojluni/src/main/java/java/text/DecimalFormat.java
+++ b/ojluni/src/main/java/java/text/DecimalFormat.java
@@ -465,10 +465,7 @@
     private void init(String pattern) {
         this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
                 symbols.getIcuDecimalFormatSymbols());
-        maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
-        minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
-        maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
-        minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
+        updateFieldsFromIcu();
     }
 
     /**
@@ -1169,6 +1166,12 @@
     }
 
     private void updateFieldsFromIcu() {
+        // Imitate behaviour of ICU4C NumberFormat that Android used up to M.
+        // If the pattern doesn't enforce a different value (some exponential
+        // patterns do), then set the maximum integer digits to 2 billion.
+        if (icuDecimalFormat.getMaximumIntegerDigits() == DOUBLE_INTEGER_DIGITS) {
+            icuDecimalFormat.setMaximumIntegerDigits(2000000000);
+        }
         maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
         minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
         maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index 6274b45..1fbe710 100755
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,11 +28,16 @@
 
 import java.lang.reflect.*;
 import java.util.concurrent.ForkJoinPool;
+import java.util.function.BinaryOperator;
 import java.util.function.Consumer;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.IntBinaryOperator;
 import java.util.function.IntFunction;
 import java.util.function.IntToDoubleFunction;
 import java.util.function.IntToLongFunction;
 import java.util.function.IntUnaryOperator;
+import java.util.function.LongBinaryOperator;
+import java.util.function.UnaryOperator;
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
@@ -1594,6 +1599,194 @@
         }
     }
 
+
+    // Parallel prefix
+
+    /**
+     * Cumulates, in parallel, each element of the given array in place,
+     * using the supplied function. For example if the array initially
+     * holds {@code [2, 1, 0, 3]} and the operation performs addition,
+     * then upon return the array holds {@code [2, 3, 3, 6]}.
+     * Parallel prefix computation is usually more efficient than
+     * sequential loops for large arrays.
+     *
+     * @param <T> the class of the objects in the array
+     * @param array the array, which is modified in-place by this method
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static <T> void parallelPrefix(T[] array, BinaryOperator<T> op) {
+        Objects.requireNonNull(op);
+        if (array.length > 0)
+            new ArrayPrefixHelpers.CumulateTask<>
+                    (null, op, array, 0, array.length).invoke();
+    }
+
+    /**
+     * Performs {@link #parallelPrefix(Object[], BinaryOperator)}
+     * for the given subrange of the array.
+     *
+     * @param <T> the class of the objects in the array
+     * @param array the array
+     * @param fromIndex the index of the first element, inclusive
+     * @param toIndex the index of the last element, exclusive
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > array.length}
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static <T> void parallelPrefix(T[] array, int fromIndex,
+                                          int toIndex, BinaryOperator<T> op) {
+        Objects.requireNonNull(op);
+        rangeCheck(array.length, fromIndex, toIndex);
+        if (fromIndex < toIndex)
+            new ArrayPrefixHelpers.CumulateTask<>
+                    (null, op, array, fromIndex, toIndex).invoke();
+    }
+
+    /**
+     * Cumulates, in parallel, each element of the given array in place,
+     * using the supplied function. For example if the array initially
+     * holds {@code [2, 1, 0, 3]} and the operation performs addition,
+     * then upon return the array holds {@code [2, 3, 3, 6]}.
+     * Parallel prefix computation is usually more efficient than
+     * sequential loops for large arrays.
+     *
+     * @param array the array, which is modified in-place by this method
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(long[] array, LongBinaryOperator op) {
+        Objects.requireNonNull(op);
+        if (array.length > 0)
+            new ArrayPrefixHelpers.LongCumulateTask
+                    (null, op, array, 0, array.length).invoke();
+    }
+
+    /**
+     * Performs {@link #parallelPrefix(long[], LongBinaryOperator)}
+     * for the given subrange of the array.
+     *
+     * @param array the array
+     * @param fromIndex the index of the first element, inclusive
+     * @param toIndex the index of the last element, exclusive
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > array.length}
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(long[] array, int fromIndex,
+                                      int toIndex, LongBinaryOperator op) {
+        Objects.requireNonNull(op);
+        rangeCheck(array.length, fromIndex, toIndex);
+        if (fromIndex < toIndex)
+            new ArrayPrefixHelpers.LongCumulateTask
+                    (null, op, array, fromIndex, toIndex).invoke();
+    }
+
+    /**
+     * Cumulates, in parallel, each element of the given array in place,
+     * using the supplied function. For example if the array initially
+     * holds {@code [2.0, 1.0, 0.0, 3.0]} and the operation performs addition,
+     * then upon return the array holds {@code [2.0, 3.0, 3.0, 6.0]}.
+     * Parallel prefix computation is usually more efficient than
+     * sequential loops for large arrays.
+     *
+     * <p> Because floating-point operations may not be strictly associative,
+     * the returned result may not be identical to the value that would be
+     * obtained if the operation was performed sequentially.
+     *
+     * @param array the array, which is modified in-place by this method
+     * @param op a side-effect-free function to perform the cumulation
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(double[] array, DoubleBinaryOperator op) {
+        Objects.requireNonNull(op);
+        if (array.length > 0)
+            new ArrayPrefixHelpers.DoubleCumulateTask
+                    (null, op, array, 0, array.length).invoke();
+    }
+
+    /**
+     * Performs {@link #parallelPrefix(double[], DoubleBinaryOperator)}
+     * for the given subrange of the array.
+     *
+     * @param array the array
+     * @param fromIndex the index of the first element, inclusive
+     * @param toIndex the index of the last element, exclusive
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > array.length}
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(double[] array, int fromIndex,
+                                      int toIndex, DoubleBinaryOperator op) {
+        Objects.requireNonNull(op);
+        rangeCheck(array.length, fromIndex, toIndex);
+        if (fromIndex < toIndex)
+            new ArrayPrefixHelpers.DoubleCumulateTask
+                    (null, op, array, fromIndex, toIndex).invoke();
+    }
+
+    /**
+     * Cumulates, in parallel, each element of the given array in place,
+     * using the supplied function. For example if the array initially
+     * holds {@code [2, 1, 0, 3]} and the operation performs addition,
+     * then upon return the array holds {@code [2, 3, 3, 6]}.
+     * Parallel prefix computation is usually more efficient than
+     * sequential loops for large arrays.
+     *
+     * @param array the array, which is modified in-place by this method
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(int[] array, IntBinaryOperator op) {
+        Objects.requireNonNull(op);
+        if (array.length > 0)
+            new ArrayPrefixHelpers.IntCumulateTask
+                    (null, op, array, 0, array.length).invoke();
+    }
+
+    /**
+     * Performs {@link #parallelPrefix(int[], IntBinaryOperator)}
+     * for the given subrange of the array.
+     *
+     * @param array the array
+     * @param fromIndex the index of the first element, inclusive
+     * @param toIndex the index of the last element, exclusive
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > array.length}
+     * @throws NullPointerException if the specified array or function is null
+     * @since 1.8
+     */
+    public static void parallelPrefix(int[] array, int fromIndex,
+                                      int toIndex, IntBinaryOperator op) {
+        Objects.requireNonNull(op);
+        rangeCheck(array.length, fromIndex, toIndex);
+        if (fromIndex < toIndex)
+            new ArrayPrefixHelpers.IntCumulateTask
+                    (null, op, array, fromIndex, toIndex).invoke();
+    }
+
     // Searching
 
     /**
@@ -3696,6 +3889,15 @@
         }
 
         @Override
+        public void replaceAll(UnaryOperator<E> operator) {
+            Objects.requireNonNull(operator);
+            E[] a = this.a;
+            for (int i = 0; i < a.length; i++) {
+                a[i] = operator.apply(a[i]);
+            }
+        }
+
+        @Override
         public Spliterator<E> spliterator() {
             return Spliterators.spliterator(a, Spliterator.ORDERED);
         }
diff --git a/ojluni/src/main/java/java/util/BitSet.java b/ojluni/src/main/java/java/util/BitSet.java
index fa0be57..3620cee 100755
--- a/ojluni/src/main/java/java/util/BitSet.java
+++ b/ojluni/src/main/java/java/util/BitSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.LongBuffer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
 
 /**
  * This class implements a vector of bits that grows as needed. Each
@@ -1188,4 +1190,48 @@
         b.append('}');
         return b.toString();
     }
+
+    /**
+     * Returns a stream of indices for which this {@code BitSet}
+     * contains a bit in the set state. The indices are returned
+     * in order, from lowest to highest. The size of the stream
+     * is the number of bits in the set state, equal to the value
+     * returned by the {@link #cardinality()} method.
+     *
+     * <p>The bit set must remain constant during the execution of the
+     * terminal stream operation.  Otherwise, the result of the terminal
+     * stream operation is undefined.
+     *
+     * @return a stream of integers representing set indices
+     * @since 1.8
+     */
+    public IntStream stream() {
+        class BitSetIterator implements PrimitiveIterator.OfInt {
+            int next = nextSetBit(0);
+
+            @Override
+            public boolean hasNext() {
+                return next != -1;
+            }
+
+            @Override
+            public int nextInt() {
+                if (next != -1) {
+                    int ret = next;
+                    next = nextSetBit(next+1);
+                    return ret;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+        }
+
+        return StreamSupport.intStream(
+                () -> Spliterators.spliterator(
+                        new BitSetIterator(), cardinality(),
+                        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED),
+                Spliterator.SIZED | Spliterator.SUBSIZED |
+                        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED,
+                false);
+    }
 }
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 6b19738..1a9f83a 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -1796,7 +1796,6 @@
 
     // Synch Wrappers
 
-    // TODO: Replace {@code stream} with {@link Stream} once we have them.
     /**
      * Returns a synchronized (thread-safe) collection backed by the specified
      * collection.  In order to guarantee serial access, it is critical that
@@ -1805,7 +1804,7 @@
      *
      * It is imperative that the user manually synchronize on the returned
      * collection when traversing it via {@link Iterator}, {@link Spliterator}
-     * or {@code Stream}:
+     * or {@link Stream}:
      * <pre>
      *  Collection c = Collections.synchronizedCollection(myCollection);
      *     ...
@@ -2884,14 +2883,6 @@
         public boolean addAll(int index, Collection<? extends E> c) {
             return list.addAll(index, checkedCopyOf(c));
         }
-        @Override
-        public void replaceAll(UnaryOperator<E> operator) {
-            list.replaceAll(operator);
-        }
-        @Override
-        public void sort(Comparator<? super E> c) {
-            list.sort(c);
-        }
         public ListIterator<E> listIterator()   { return listIterator(0); }
 
         public ListIterator<E> listIterator(final int index) {
@@ -2926,6 +2917,32 @@
         public List<E> subList(int fromIndex, int toIndex) {
             return new CheckedList<>(list.subList(fromIndex, toIndex), type);
         }
+
+        /**
+         * {@inheritDoc}
+         *
+         * @throws ClassCastException if the class of an element returned by the
+         *         operator prevents it from being added to this collection. The
+         *         exception may be thrown after some elements of the list have
+         *         already been replaced.
+         */
+        @Override
+        public void replaceAll(UnaryOperator<E> operator) {
+            Objects.requireNonNull(operator);
+
+            // Android-changed: Modified from OpenJDK 8 code because typeCheck returns void in
+            // OpenJDK 7.
+            list.replaceAll(e -> {
+                    E newValue = operator.apply(e);
+                    typeCheck(newValue);
+                    return newValue;
+            });
+        }
+
+        @Override
+        public void sort(Comparator<? super E> c) {
+            list.sort(c);
+        }
     }
 
     /**
@@ -3088,6 +3105,68 @@
             m.forEach(action);
         }
 
+        @Override
+        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+            m.replaceAll(typeCheck(function));
+        }
+
+        @Override
+        public V putIfAbsent(K key, V value) {
+            typeCheck(key, value);
+            return m.putIfAbsent(key, value);
+        }
+
+        @Override
+        public boolean remove(Object key, Object value) {
+            return m.remove(key, value);
+        }
+
+        @Override
+        public boolean replace(K key, V oldValue, V newValue) {
+            typeCheck(key, newValue);
+            return m.replace(key, oldValue, newValue);
+        }
+
+        @Override
+        public V replace(K key, V value) {
+            typeCheck(key, value);
+            return m.replace(key, value);
+        }
+
+        @Override
+        public V computeIfAbsent(K key,
+                Function<? super K, ? extends V> mappingFunction) {
+            Objects.requireNonNull(mappingFunction);
+            return m.computeIfAbsent(key, k -> {
+                V value = mappingFunction.apply(k);
+                typeCheck(k, value);
+                return value;
+            });
+        }
+
+        @Override
+        public V computeIfPresent(K key,
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            return m.computeIfPresent(key, typeCheck(remappingFunction));
+        }
+
+        @Override
+        public V compute(K key,
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            return m.compute(key, typeCheck(remappingFunction));
+        }
+
+        @Override
+        public V merge(K key, V value,
+                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+            Objects.requireNonNull(remappingFunction);
+            return m.merge(key, value, (v1, v2) -> {
+                V newValue = remappingFunction.apply(v1, v2);
+                typeCheck(null, newValue);
+                return newValue;
+            });
+        }
+
         /**
          * We need this class in addition to CheckedSet as Map.Entry permits
          * modification of the backing Map via the setValue operation.  This
diff --git a/ojluni/src/main/java/java/util/ComparableTimSort.java b/ojluni/src/main/java/java/util/ComparableTimSort.java
index e7c7ac0..36c8d90 100755
--- a/ojluni/src/main/java/java/util/ComparableTimSort.java
+++ b/ojluni/src/main/java/java/util/ComparableTimSort.java
@@ -144,10 +144,14 @@
          * large) stack lengths for smaller arrays.  The "magic numbers" in the
          * computation below must be changed if MIN_MERGE is decreased.  See
          * the MIN_MERGE declaration above for more information.
+         * The maximum value of 49 allows for an array up to length
+         * Integer.MAX_VALUE-4, if array is filled by the worst case stack size
+         * increasing scenario. More explanations are given in section 4 of:
+         * http://envisage-project.eu/wp-content/uploads/2015/02/sorting.pdf
          */
         int stackLen = (len <    120  ?  5 :
                         len <   1542  ? 10 :
-                        len < 119151  ? 24 : 40);
+                        len < 119151  ? 24 : 49);
         runBase = new int[stackLen];
         runLen = new int[stackLen];
     }
diff --git a/ojluni/src/main/java/java/util/HashMap.java b/ojluni/src/main/java/java/util/HashMap.java
index 547cb05..9403225 100755
--- a/ojluni/src/main/java/java/util/HashMap.java
+++ b/ojluni/src/main/java/java/util/HashMap.java
@@ -27,6 +27,7 @@
 package java.util;
 
 import java.io.*;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.BiConsumer;
 
@@ -133,7 +134,7 @@
     /**
      * The default initial capacity - MUST be a power of two.
      */
-    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
+    static final int DEFAULT_INITIAL_CAPACITY = 4;
 
     /**
      * The maximum capacity, used if a higher value is implicitly specified
@@ -175,7 +176,9 @@
      *
      * @serial
      */
-    final float loadFactor;
+    // Android-Note: We always use a load factor of 0.75 and ignore any explicitly
+    // selected values.
+    final float loadFactor = DEFAULT_LOAD_FACTOR;
 
     /**
      * The number of times this HashMap has been structurally modified
@@ -187,62 +190,6 @@
     transient int modCount;
 
     /**
-     * The default threshold of map capacity above which alternative hashing is
-     * used for String keys. Alternative hashing reduces the incidence of
-     * collisions due to weak hash code calculation for String keys.
-     * <p/>
-     * This value may be overridden by defining the system property
-     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
-     * forces alternative hashing to be used at all times whereas
-     * {@code -1} value ensures that alternative hashing is never used.
-     */
-    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
-
-    /**
-     * holds values which can't be initialized until after VM is booted.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                if (threshold < 0) {
-                    throw new IllegalArgumentException("value must be positive integer.");
-                }
-            } catch(IllegalArgumentException failed) {
-                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
-            }
-
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find. If 0 then
-     * alternative hashing is disabled.
-     */
-    transient int hashSeed = 0;
-
-    /**
      * Constructs an empty <tt>HashMap</tt> with the specified initial
      * capacity and load factor.
      *
@@ -255,13 +202,21 @@
         if (initialCapacity < 0)
             throw new IllegalArgumentException("Illegal initial capacity: " +
                                                initialCapacity);
-        if (initialCapacity > MAXIMUM_CAPACITY)
+        if (initialCapacity > MAXIMUM_CAPACITY) {
             initialCapacity = MAXIMUM_CAPACITY;
+        } else if (initialCapacity < DEFAULT_INITIAL_CAPACITY) {
+            initialCapacity = DEFAULT_INITIAL_CAPACITY;
+        }
+
         if (loadFactor <= 0 || Float.isNaN(loadFactor))
             throw new IllegalArgumentException("Illegal load factor: " +
                                                loadFactor);
+        // Android-Note: We always use the default load factor of 0.75f.
 
-        this.loadFactor = loadFactor;
+        // This might appear wrong but it's just awkward design. We always call
+        // inflateTable() when table == EMPTY_TABLE. That method will take "threshold"
+        // to mean "capacity" and then replace it with the real threshold (i.e, multiplied with
+        // the load factor).
         threshold = initialCapacity;
         init();
     }
@@ -330,7 +285,6 @@
 
         threshold = (int) thresholdFloat;
         table = new HashMapEntry[capacity];
-        initHashSeedAsNeeded(capacity);
     }
 
     // internal utilities
@@ -346,45 +300,6 @@
     }
 
     /**
-     * Initialize the hashing mask value. We defer initialization until we
-     * really need it.
-     */
-    final boolean initHashSeedAsNeeded(int capacity) {
-        boolean currentAltHashing = hashSeed != 0;
-        boolean useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean switching = currentAltHashing ^ useAltHashing;
-        if (switching) {
-            hashSeed = useAltHashing
-                ? sun.misc.Hashing.randomHashSeed(this)
-                : 0;
-        }
-        return switching;
-    }
-
-    /**
-     * Retrieve object hash code and applies a supplemental hash function to the
-     * result hash, which defends against poor quality hash functions.  This is
-     * critical because HashMap uses power-of-two length hash tables, that
-     * otherwise encounter collisions for hashCodes that do not differ
-     * in lower bits. Note: Null keys always map to hash 0, thus index 0.
-     */
-    final int hash(Object k) {
-        int h = hashSeed;
-        if (0 != h && k instanceof String) {
-            return sun.misc.Hashing.stringHash32((String) k);
-        }
-
-        h ^= k.hashCode();
-
-        // This function ensures that hashCodes that differ only by
-        // constant multiples at each bit position have a bounded
-        // number of collisions (approximately 8 at default load factor).
-        h ^= (h >>> 20) ^ (h >>> 12);
-        return h ^ (h >>> 7) ^ (h >>> 4);
-    }
-
-    /**
      * Returns index for hash code h.
      */
     static int indexFor(int h, int length) {
@@ -475,7 +390,7 @@
             return null;
         }
 
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         for (HashMapEntry<K,V> e = table[indexFor(hash, table.length)];
              e != null;
              e = e.next) {
@@ -505,7 +420,7 @@
         }
         if (key == null)
             return putForNullKey(value);
-        int hash = hash(key);
+        int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         for (HashMapEntry<K,V> e = table[i]; e != null; e = e.next) {
             Object k;
@@ -546,7 +461,7 @@
      * addEntry.
      */
     private void putForCreate(K key, V value) {
-        int hash = null == key ? 0 : hash(key);
+        int hash = null == key ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
 
         /**
@@ -594,7 +509,7 @@
         }
 
         HashMapEntry[] newTable = new HashMapEntry[newCapacity];
-        transfer(newTable, initHashSeedAsNeeded(newCapacity));
+        transfer(newTable);
         table = newTable;
         threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
     }
@@ -602,14 +517,11 @@
     /**
      * Transfers all entries from current table to newTable.
      */
-    void transfer(HashMapEntry[] newTable, boolean rehash) {
+    void transfer(HashMapEntry[] newTable) {
         int newCapacity = newTable.length;
         for (HashMapEntry<K,V> e : table) {
             while(null != e) {
                 HashMapEntry<K,V> next = e.next;
-                if (rehash) {
-                    e.hash = null == e.key ? 0 : hash(e.key);
-                }
                 int i = indexFor(e.hash, newCapacity);
                 e.next = newTable[i];
                 newTable[i] = e;
@@ -682,7 +594,7 @@
         if (size == 0) {
             return null;
         }
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         HashMapEntry<K,V> prev = table[i];
         HashMapEntry<K,V> e = prev;
@@ -718,7 +630,7 @@
 
         Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
         Object key = entry.getKey();
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         HashMapEntry<K,V> prev = table[i];
         HashMapEntry<K,V> e = prev;
@@ -894,7 +806,7 @@
     void addEntry(int hash, K key, V value, int bucketIndex) {
         if ((size >= threshold) && (null != table[bucketIndex])) {
             resize(2 * table.length);
-            hash = (null != key) ? hash(key) : 0;
+            hash = (null != key) ? sun.misc.Hashing.singleWordWangJenkinsHash(key) : 0;
             bucketIndex = indexFor(hash, table.length);
         }
 
@@ -1455,6 +1367,23 @@
         }
     }
 
+    @Override
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        HashMapEntry<K,V>[] tab;
+        if (function == null)
+            throw new NullPointerException();
+        if (size > 0 && (tab = table) != null) {
+            int mc = modCount;
+            for (int i = 0; i < tab.length; ++i) {
+                for (HashMapEntry<K,V> e = tab[i]; e != null; e = e.next) {
+                    e.value = function.apply(e.key, e.value);
+                }
+            }
+            if (modCount != mc)
+                throw new ConcurrentModificationException();
+        }
+    }
+
     /**
      * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
      * serialize it).
diff --git a/ojluni/src/main/java/java/util/Hashtable.java b/ojluni/src/main/java/java/util/Hashtable.java
index 8a21511..783d17b 100755
--- a/ojluni/src/main/java/java/util/Hashtable.java
+++ b/ojluni/src/main/java/java/util/Hashtable.java
@@ -168,80 +168,8 @@
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = 1421746759512286392L;
 
-    /**
-     * The default threshold of map capacity above which alternative hashing is
-     * used for String keys. Alternative hashing reduces the incidence of
-     * collisions due to weak hash code calculation for String keys.
-     * <p>
-     * This value may be overridden by defining the system property
-     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
-     * forces alternative hashing to be used at all times whereas
-     * {@code -1} value ensures that alternative hashing is never used.
-     */
-    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
-
-    /**
-     * holds values which can't be initialized until after VM is booted.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                if (threshold < 0) {
-                    throw new IllegalArgumentException("value must be positive integer.");
-                }
-            } catch(IllegalArgumentException failed) {
-                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
-            }
-
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find.
-     */
-    transient int hashSeed;
-
-    /**
-     * Initialize the hashing mask value.
-     */
-    final boolean initHashSeedAsNeeded(int capacity) {
-        boolean currentAltHashing = hashSeed != 0;
-        boolean useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean switching = currentAltHashing ^ useAltHashing;
-        if (switching) {
-            hashSeed = useAltHashing
-                ? sun.misc.Hashing.randomHashSeed(this)
-                : 0;
-        }
-        return switching;
-    }
-
-    private int hash(Object k) {
-        // hashSeed will be zero if alternative hashing is disabled.
-        return hashSeed ^ k.hashCode();
+    private static int hash(Object k) {
+        return k.hashCode();
     }
 
     /**
@@ -265,7 +193,6 @@
         this.loadFactor = loadFactor;
         table = new HashtableEntry[initialCapacity];
         threshold = (initialCapacity <= MAX_ARRAY_SIZE + 1) ? initialCapacity : MAX_ARRAY_SIZE + 1;
-        initHashSeedAsNeeded(initialCapacity);
     }
 
     /**
@@ -477,7 +404,6 @@
 
         modCount++;
         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
-        boolean rehash = initHashSeedAsNeeded(newCapacity);
 
         table = newMap;
 
@@ -486,9 +412,6 @@
                 HashtableEntry<K,V> e = old;
                 old = old.next;
 
-                if (rehash) {
-                    e.hash = hash(e.key);
-                }
                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                 e.next = newMap[index];
                 newMap[index] = e;
@@ -944,6 +867,27 @@
             }
         }
     }
+    @SuppressWarnings("unchecked")
+    @Override
+    public synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        Objects.requireNonNull(function);     // explicit check required in case
+        // table is empty.
+        final int expectedModCount = modCount;
+
+        HashtableEntry<K, V>[] tab = table;
+        for (HashtableEntry<K, V> entry : tab) {
+            while (entry != null) {
+                entry.value = Objects.requireNonNull(
+                        function.apply(entry.key, entry.value));
+                entry = entry.next;
+
+                if (expectedModCount != modCount) {
+                    throw new ConcurrentModificationException();
+                }
+            }
+        }
+    }
+
 
     // Overrides Java8 default methods(added method synchronization)
 
@@ -1065,7 +1009,6 @@
         HashtableEntry<K,V>[] newTable = new HashtableEntry[length];
         threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
         count = 0;
-        initHashSeedAsNeeded(length);
 
         // Read the number of elements and then all the key/value objects
         for (; elements > 0; elements--) {
diff --git a/ojluni/src/main/java/java/util/IdentityHashMap.java b/ojluni/src/main/java/java/util/IdentityHashMap.java
index ea1948d..b860cca 100755
--- a/ojluni/src/main/java/java/util/IdentityHashMap.java
+++ b/ojluni/src/main/java/java/util/IdentityHashMap.java
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.lang.reflect.Array;
 import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 /**
@@ -1359,6 +1360,25 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        Objects.requireNonNull(function);
+        int expectedModCount = modCount;
+
+        Object[] t = table;
+        for (int index = 0; index < t.length; index += 2) {
+            Object k = t[index];
+            if (k != null) {
+                t[index + 1] = function.apply((K) unmaskNull(k), (V) t[index + 1]);
+            }
+
+            if (modCount != expectedModCount) {
+                throw new ConcurrentModificationException();
+            }
+        }
+    }
+
     /**
      * Similar form as array-based Spliterators, but skips blank elements,
      * and guestimates size as decreasing by half per split.
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index 81b8a7a..5a35728 100755
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -26,7 +26,10 @@
 
 package java.util;
 
+import sun.misc.Hashing;
+
 import java.io.*;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.BiConsumer;
 
@@ -264,11 +267,9 @@
      * faster to iterate using our linked list.
      */
     @Override
-    void transfer(HashMapEntry[] newTable, boolean rehash) {
+    void transfer(HashMapEntry[] newTable) {
         int newCapacity = newTable.length;
         for (LinkedHashMapEntry<K,V> e = header.after; e != header; e = e.after) {
-            if (rehash)
-                e.hash = (e.key == null) ? 0 : hash(e.key);
             int index = indexFor(e.hash, newCapacity);
             e.next = newTable[index];
             newTable[index] = e;
@@ -440,13 +441,27 @@
      * removes the eldest entry if appropriate.
      */
     void addEntry(int hash, K key, V value, int bucketIndex) {
-        super.addEntry(hash, key, value, bucketIndex);
+        // Previous Android releases called removeEldestEntry() before actually
+        // inserting a value but after increasing the size.
+        // The RI is documented to call it afterwards.
+        // **** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ****
 
         // Remove eldest entry if instructed
         LinkedHashMapEntry<K,V> eldest = header.after;
-        if (removeEldestEntry(eldest)) {
-            removeEntryForKey(eldest.key);
+        if (eldest != header) {
+            boolean removeEldest;
+            size++;
+            try {
+                removeEldest = removeEldestEntry(eldest);
+            } finally {
+                size--;
+            }
+            if (removeEldest) {
+                removeEntryForKey(eldest.key);
+            }
         }
+
+        super.addEntry(hash, key, value, bucketIndex);
     }
 
     /**
@@ -473,7 +488,12 @@
         size++;
     }
 
-    /**
+    // Intentionally make this not JavaDoc, as the we don't conform to
+    // the behaviour documented here (we call removeEldestEntry before
+    // inserting the new value to be consistent with previous Android
+    // releases).
+    // **** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ****
+    /*
      * Returns <tt>true</tt> if this map should remove its eldest entry.
      * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
      * inserting a new entry into the map.  It provides the implementor
@@ -529,4 +549,15 @@
         if (modCount != mc)
             throw new ConcurrentModificationException();
     }
+
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        if (function == null)
+            throw new NullPointerException();
+        int mc = modCount;
+        // Android modified - breaks from the loop when modCount != mc
+        for (LinkedHashMapEntry<K,V> e = header.after; modCount == mc && e != header; e = e.after)
+            e.value = function.apply(e.key, e.value);
+        if (modCount != mc)
+            throw new ConcurrentModificationException();
+    }
 }
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 21576b7..5d1a775 100755
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -82,7 +82,7 @@
  * described below.
  *
  * <dl>
- *   <dt><a name="def_language"/><b>language</b></dt>
+ *   <dt><a name="def_language"></a><b>language</b></dt>
  *
  *   <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
  *   language subtags up to 8 alpha letters (for future enhancements).
@@ -100,7 +100,7 @@
  *
  *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
  *
- *   <dt><a name="def_script"/><b>script</b></dt>
+ *   <dt><a name="def_script"/></a><b>script</b></dt>
  *
  *   <dd>ISO 15924 alpha-4 script code.  You can find a full list of
  *   valid script codes in the IANA Language Subtag Registry (search
@@ -114,7 +114,7 @@
  *
  *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
  *
- *   <dt><a name="def_region"/><b>country (region)</b></dt>
+ *   <dt><a name="def_region"></a><b>country (region)</b></dt>
  *
  *   <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
  *   You can find a full list of valid country and region codes in the
@@ -128,7 +128,7 @@
  *   <dd>Example: "US" (United States), "FR" (France), "029"
  *   (Caribbean)</dd><br>
  *
- *   <dt><a name="def_variant"/><b>variant</b></dt>
+ *   <dt><a name="def_variant"></a><b>variant</b></dt>
  *
  *   <dd>Any arbitrary value used to indicate a variation of a
  *   <code>Locale</code>.  Where there are two or more variant values
@@ -159,7 +159,7 @@
  *
  *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
  *
- *   <dt><a name="def_extensions"/><b>extensions</b></dt>
+ *   <dt><a name="def_extensions"></a><b>extensions</b></dt>
  *
  *   <dd>A map from single character keys to string values, indicating
  *   extensions apart from language identification.  The extensions in
@@ -187,7 +187,7 @@
  * requirement (is well-formed), but does not validate the value
  * itself.  See {@link Builder} for details.
  *
- * <h4><a name="def_locale_extension">Unicode locale/language extension</h4>
+ * <h4><a name="def_locale_extension"></a>Unicode locale/language extension</h4>
  *
  * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
  * attributes and keywords to override or refine the default behavior
@@ -334,7 +334,7 @@
  * Clients desiring a string representation of the complete locale can
  * then always rely on <code>toLanguageTag</code> for this purpose.
  *
- * <h5><a name="special_cases_constructor"/>Special cases</h5>
+ * <h5><a name="special_cases_constructor"></a>Special cases</h5>
  *
  * <p>For compatibility reasons, two
  * non-conforming locales are treated as special cases.  These are
@@ -398,6 +398,80 @@
  * compatibility, the implementation still does not impose a length
  * constraint.
  *
+ * <a name="locale_data"></a><h4>Locale data</h4>
+ * <p>Note that locale data comes solely from ICU. User-supplied locale service providers (using
+ * the {@code java.text.spi} or {@code java.util.spi} mechanisms) are not supported.
+ *
+ * <p>Here are the versions of ICU (and the corresponding CLDR and Unicode versions) used in
+ * various Android releases:
+ * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+ * <tr><td>Android 1.5 (Cupcake)/Android 1.6 (Donut)/Android 2.0 (Eclair)</td>
+ *     <td>ICU 3.8</td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-5">CLDR 1.5</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr>
+ * <tr><td>Android 2.2 (Froyo)</td>
+ *     <td>ICU 4.2</td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-7">CLDR 1.7</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr>
+ * <tr><td>Android 2.3 (Gingerbread)/Android 3.0 (Honeycomb)</td>
+ *     <td>ICU 4.4</td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-8">CLDR 1.8</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr>
+ * <tr><td>Android 4.0 (Ice Cream Sandwich)</td>
+ *     <td><a href="http://site.icu-project.org/download/46">ICU 4.6</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-9">CLDR 1.9</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
+ * <tr><td>Android 4.1 (Jelly Bean)</td>
+ *     <td><a href="http://site.icu-project.org/download/48">ICU 4.8</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-2-0">CLDR 2.0</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
+ * <tr><td>Android 4.3 (Jelly Bean MR2)</td>
+ *     <td><a href="http://site.icu-project.org/download/50">ICU 50</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-22-1">CLDR 22.1</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
+ * <tr><td>Android 4.4 (KitKat)</td>
+ *     <td><a href="http://site.icu-project.org/download/51">ICU 51</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-23">CLDR 23</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
+ * <tr><td>Android 5.0 (Lollipop)</td>
+ *     <td><a href="http://site.icu-project.org/download/53">ICU 53</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-25">CLDR 25</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode6.3.0/">Unicode 6.3</a></td></tr>
+ * <tr><td>Android 6.0 (Marshmallow)</td>
+ *     <td><a href="http://site.icu-project.org/download/55">ICU 55.1</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-27">CLDR 27.0.1</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode7.0.0/">Unicode 7.0</a></td></tr>
+ * </table>
+ *
+ * <a name="default_locale"></a><h4>Be wary of the default locale</h3>
+ * <p>Note that there are many convenience methods that automatically use the default locale, but
+ * using them may lead to subtle bugs.
+ *
+ * <p>The default locale is appropriate for tasks that involve presenting data to the user. In
+ * this case, you want to use the user's date/time formats, number
+ * formats, rules for conversion to lowercase, and so on. In this case, it's safe to use the
+ * convenience methods.
+ *
+ * <p>The default locale is <i>not</i> appropriate for machine-readable output. The best choice
+ * there is usually {@code Locale.US}&nbsp;&ndash; this locale is guaranteed to be available on all
+ * devices, and the fact that it has no surprising special cases and is frequently used (especially
+ * for computer-computer communication) means that it tends to be the most efficient choice too.
+ *
+ * <p>A common mistake is to implicitly use the default locale when producing output meant to be
+ * machine-readable. This tends to work on the developer's test devices (especially because so many
+ * developers use en_US), but fails when run on a device whose user is in a more complex locale.
+ *
+ * <p>For example, if you're formatting integers some locales will use non-ASCII decimal
+ * digits. As another example, if you're formatting floating-point numbers some locales will use
+ * {@code ','} as the decimal point and {@code '.'} for digit grouping. That's correct for
+ * human-readable output, but likely to cause problems if presented to another
+ * computer ({@link Double#parseDouble} can't parse such a number, for example).
+ * You should also be wary of the {@link String#toLowerCase} and
+ * {@link String#toUpperCase} overloads that don't take a {@code Locale}: in Turkey, for example,
+ * the characters {@code 'i'} and {@code 'I'} won't be converted to {@code 'I'} and {@code 'i'}.
+ * This is the correct behavior for Turkish text (such as user input), but inappropriate for, say,
+ * HTTP headers.
+ *
  * @see Builder
  * @see ResourceBundle
  * @see java.text.Format
diff --git a/ojluni/src/main/java/java/util/Properties.java b/ojluni/src/main/java/java/util/Properties.java
index 112562f..d0470b2 100755
--- a/ojluni/src/main/java/java/util/Properties.java
+++ b/ojluni/src/main/java/java/util/Properties.java
@@ -106,8 +106,8 @@
  * <p>This class is thread-safe: multiple threads can share a single
  * <tt>Properties</tt> object without the need for external synchronization.
  *
- * @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
- * @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
+ * @see <a href="{@docRoot}/../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
+ * @see <a href="{@docRoot}/../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
  *
  * @author  Arthur van Hoff
  * @author  Michael McCloskey
diff --git a/ojluni/src/main/java/java/util/Random.java b/ojluni/src/main/java/java/util/Random.java
index e56051c..fb4ecfd 100755
--- a/ojluni/src/main/java/java/util/Random.java
+++ b/ojluni/src/main/java/java/util/Random.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,14 @@
 package java.util;
 import java.io.*;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.StreamSupport;
+
 import sun.misc.Unsafe;
 
 /**
@@ -81,6 +89,13 @@
     private static final long addend = 0xBL;
     private static final long mask = (1L << 48) - 1;
 
+    private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
+
+    // IllegalArgumentException messages
+    static final String BadBound = "bound must be positive";
+    static final String BadRange = "bound must be greater than origin";
+    static final String BadSize  = "size must be non-negative";
+
     /**
      * Creates a new random number generator. This constructor sets
      * the seed of the random number generator to a value very likely
@@ -218,6 +233,82 @@
     }
 
     /**
+     * The form of nextLong used by LongStream Spliterators.  If
+     * origin is greater than bound, acts as unbounded form of
+     * nextLong, else as bounded form.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final long internalNextLong(long origin, long bound) {
+        long r = nextLong();
+        if (origin < bound) {
+            long n = bound - origin, m = n - 1;
+            if ((n & m) == 0L)  // power of two
+                r = (r & m) + origin;
+            else if (n > 0L) {  // reject over-represented candidates
+                for (long u = r >>> 1;            // ensure nonnegative
+                     u + m - (r = u % n) < 0L;    // rejection check
+                     u = nextLong() >>> 1) // retry
+                    ;
+                r += origin;
+            }
+            else {              // range not representable as long
+                while (r < origin || r >= bound)
+                    r = nextLong();
+            }
+        }
+        return r;
+    }
+
+    /**
+     * The form of nextInt used by IntStream Spliterators.
+     * For the unbounded case: uses nextInt().
+     * For the bounded case with representable range: uses nextInt(int bound)
+     * For the bounded case with unrepresentable range: uses nextInt()
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final int internalNextInt(int origin, int bound) {
+        if (origin < bound) {
+            int n = bound - origin;
+            if (n > 0) {
+                return nextInt(n) + origin;
+            }
+            else {  // range not representable as int
+                int r;
+                do {
+                    r = nextInt();
+                } while (r < origin || r >= bound);
+                return r;
+            }
+        }
+        else {
+            return nextInt();
+        }
+    }
+
+    /**
+     * The form of nextDouble used by DoubleStream Spliterators.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final double internalNextDouble(double origin, double bound) {
+        double r = nextDouble();
+        if (origin < bound) {
+            r = r * (bound - origin) + origin;
+            if (r >= bound) // correct for rounding
+                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+        }
+        return r;
+    }
+
+    /**
      * Returns the next pseudorandom, uniformly distributed {@code int}
      * value from this random number generator's sequence. The general
      * contract of {@code nextInt} is that one {@code int} value is
@@ -512,6 +603,565 @@
         }
     }
 
+    // stream methods, coded in a way intended to better isolate for
+    // maintenance purposes the small differences across forms.
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code int} values.
+     *
+     * <p>A pseudorandom {@code int} value is generated as if it's the result of
+     * calling the method {@link #nextInt()}.
+     *
+     * @param streamSize the number of values to generate
+     * @return a stream of pseudorandom {@code int} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     * @since 1.8
+     */
+    public IntStream ints(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, streamSize, Integer.MAX_VALUE, 0),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code int}
+     * values.
+     *
+     * <p>A pseudorandom {@code int} value is generated as if it's the result of
+     * calling the method {@link #nextInt()}.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * ints(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code int} values
+     * @since 1.8
+     */
+    public IntStream ints() {
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number
+     * of pseudorandom {@code int} values, each conforming to the given
+     * origin (inclusive) and bound (exclusive).
+     *
+     * <p>A pseudorandom {@code int} value is generated as if it's the result of
+     * calling the following method with the origin and bound:
+     * <pre> {@code
+     * int nextInt(int origin, int bound) {
+     *   int n = bound - origin;
+     *   if (n > 0) {
+     *     return nextInt(n) + origin;
+     *   }
+     *   else {  // range not representable as int
+     *     int r;
+     *     do {
+     *       r = nextInt();
+     *     } while (r < origin || r >= bound);
+     *     return r;
+     *   }
+     * }}</pre>
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code int} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public IntStream ints(long streamSize, int randomNumberOrigin,
+                          int randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * int} values, each conforming to the given origin (inclusive) and bound
+     * (exclusive).
+     *
+     * <p>A pseudorandom {@code int} value is generated as if it's the result of
+     * calling the following method with the origin and bound:
+     * <pre> {@code
+     * int nextInt(int origin, int bound) {
+     *   int n = bound - origin;
+     *   if (n > 0) {
+     *     return nextInt(n) + origin;
+     *   }
+     *   else {  // range not representable as int
+     *     int r;
+     *     do {
+     *       r = nextInt();
+     *     } while (r < origin || r >= bound);
+     *     return r;
+     *   }
+     * }}</pre>
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code int} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code long} values.
+     *
+     * <p>A pseudorandom {@code long} value is generated as if it's the result
+     * of calling the method {@link #nextLong()}.
+     *
+     * @param streamSize the number of values to generate
+     * @return a stream of pseudorandom {@code long} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     * @since 1.8
+     */
+    public LongStream longs(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, streamSize, Long.MAX_VALUE, 0L),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code long}
+     * values.
+     *
+     * <p>A pseudorandom {@code long} value is generated as if it's the result
+     * of calling the method {@link #nextLong()}.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * longs(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code long} values
+     * @since 1.8
+     */
+    public LongStream longs() {
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code long}, each conforming to the given origin
+     * (inclusive) and bound (exclusive).
+     *
+     * <p>A pseudorandom {@code long} value is generated as if it's the result
+     * of calling the following method with the origin and bound:
+     * <pre> {@code
+     * long nextLong(long origin, long bound) {
+     *   long r = nextLong();
+     *   long n = bound - origin, m = n - 1;
+     *   if ((n & m) == 0L)  // power of two
+     *     r = (r & m) + origin;
+     *   else if (n > 0L) {  // reject over-represented candidates
+     *     for (long u = r >>> 1;            // ensure nonnegative
+     *          u + m - (r = u % n) < 0L;    // rejection check
+     *          u = nextLong() >>> 1) // retry
+     *         ;
+     *     r += origin;
+     *   }
+     *   else {              // range not representable as long
+     *     while (r < origin || r >= bound)
+     *       r = nextLong();
+     *   }
+     *   return r;
+     * }}</pre>
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code long} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public LongStream longs(long streamSize, long randomNumberOrigin,
+                            long randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * long} values, each conforming to the given origin (inclusive) and bound
+     * (exclusive).
+     *
+     * <p>A pseudorandom {@code long} value is generated as if it's the result
+     * of calling the following method with the origin and bound:
+     * <pre> {@code
+     * long nextLong(long origin, long bound) {
+     *   long r = nextLong();
+     *   long n = bound - origin, m = n - 1;
+     *   if ((n & m) == 0L)  // power of two
+     *     r = (r & m) + origin;
+     *   else if (n > 0L) {  // reject over-represented candidates
+     *     for (long u = r >>> 1;            // ensure nonnegative
+     *          u + m - (r = u % n) < 0L;    // rejection check
+     *          u = nextLong() >>> 1) // retry
+     *         ;
+     *     r += origin;
+     *   }
+     *   else {              // range not representable as long
+     *     while (r < origin || r >= bound)
+     *       r = nextLong();
+     *   }
+     *   return r;
+     * }}</pre>
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code long} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code double} values, each between zero
+     * (inclusive) and one (exclusive).
+     *
+     * <p>A pseudorandom {@code double} value is generated as if it's the result
+     * of calling the method {@link #nextDouble()}.
+     *
+     * @param streamSize the number of values to generate
+     * @return a stream of {@code double} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     * @since 1.8
+     */
+    public DoubleStream doubles(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * double} values, each between zero (inclusive) and one
+     * (exclusive).
+     *
+     * <p>A pseudorandom {@code double} value is generated as if it's the result
+     * of calling the method {@link #nextDouble()}.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * doubles(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code double} values
+     * @since 1.8
+     */
+    public DoubleStream doubles() {
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code double} values, each conforming to the given origin
+     * (inclusive) and bound (exclusive).
+     *
+     * <p>A pseudorandom {@code double} value is generated as if it's the result
+     * of calling the following method with the origin and bound:
+     * <pre> {@code
+     * double nextDouble(double origin, double bound) {
+     *   double r = nextDouble();
+     *   r = r * (bound - origin) + origin;
+     *   if (r >= bound) // correct for rounding
+     *     r = Math.nextDown(bound);
+     *   return r;
+     * }}</pre>
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code double} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
+                                double randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (!(randomNumberOrigin < randomNumberBound))
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * double} values, each conforming to the given origin (inclusive) and bound
+     * (exclusive).
+     *
+     * <p>A pseudorandom {@code double} value is generated as if it's the result
+     * of calling the following method with the origin and bound:
+     * <pre> {@code
+     * double nextDouble(double origin, double bound) {
+     *   double r = nextDouble();
+     *   r = r * (bound - origin) + origin;
+     *   if (r >= bound) // correct for rounding
+     *     r = Math.nextDown(bound);
+     *   return r;
+     * }}</pre>
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin (inclusive) of each random value
+     * @param randomNumberBound the bound (exclusive) of each random value
+     * @return a stream of pseudorandom {@code double} values,
+     *         each with the given origin (inclusive) and bound (exclusive)
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     * @since 1.8
+     */
+    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
+        if (!(randomNumberOrigin < randomNumberBound))
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Spliterator for int streams.  We multiplex the four int
+     * versions into one class by treating a bound less than origin as
+     * unbounded, and also by treating "infinite" as equivalent to
+     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
+     * approach. The long and double versions of this class are
+     * identical except for types.
+     */
+    static final class RandomIntsSpliterator implements Spliterator.OfInt {
+        final Random rng;
+        long index;
+        final long fence;
+        final int origin;
+        final int bound;
+        RandomIntsSpliterator(Random rng, long index, long fence,
+                              int origin, int bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomIntsSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomIntsSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextInt(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                int o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextInt(o, b));
+                } while (++i < f);
+            }
+        }
+    }
+
+    /**
+     * Spliterator for long streams.
+     */
+    static final class RandomLongsSpliterator implements Spliterator.OfLong {
+        final Random rng;
+        long index;
+        final long fence;
+        final long origin;
+        final long bound;
+        RandomLongsSpliterator(Random rng, long index, long fence,
+                               long origin, long bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomLongsSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomLongsSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextLong(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                long o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextLong(o, b));
+                } while (++i < f);
+            }
+        }
+
+    }
+
+    /**
+     * Spliterator for double streams.
+     */
+    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+        final Random rng;
+        long index;
+        final long fence;
+        final double origin;
+        final double bound;
+        RandomDoublesSpliterator(Random rng, long index, long fence,
+                                 double origin, double bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomDoublesSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextDouble(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                double o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextDouble(o, b));
+                } while (++i < f);
+            }
+        }
+    }
+
     /**
      * Serializable fields for Random.
      *
diff --git a/ojluni/src/main/java/java/util/ResourceBundle.java b/ojluni/src/main/java/java/util/ResourceBundle.java
index 1df01f5..f604089 100755
--- a/ojluni/src/main/java/java/util/ResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ResourceBundle.java
@@ -44,12 +44,14 @@
 import dalvik.system.VMStack;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
@@ -848,7 +850,7 @@
      * Gets a resource bundle using the specified base name, locale, and class
      * loader.
      *
-     * <p><a name="default_behavior"/>This method behaves the same as calling
+     * <p><a name="default_behavior"></a>This method behaves the same as calling
      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
      * default instance of {@link Control}. The following describes this behavior.
      *
@@ -945,7 +947,7 @@
      * <p>If still no result bundle is found, the base name alone is looked up. If
      * this still fails, a <code>MissingResourceException</code> is thrown.
      *
-     * <p><a name="parent_chain"/> Once a result resource bundle has been found,
+     * <p><a name="parent_chain"></a> Once a result resource bundle has been found,
      * its <em>parent chain</em> is instantiated.  If the result bundle already
      * has a parent (perhaps because it was returned from a cache) the chain is
      * complete.
@@ -975,7 +977,7 @@
      * path name (using "/") instead of a fully qualified class name (using
      * ".").
      *
-     * <p><a name="default_behavior_example"/>
+     * <p><a name="default_behavior_example"></a>
      * <strong>Example:</strong>
      * <p>
      * The following class and property files are provided:
@@ -2608,7 +2610,8 @@
                 }
                 if (stream != null) {
                     try {
-                        bundle = new PropertyResourceBundle(stream);
+                        bundle = new PropertyResourceBundle(
+                                new InputStreamReader(stream, StandardCharsets.UTF_8));
                     } finally {
                         stream.close();
                     }
diff --git a/ojluni/src/main/java/java/util/Spliterators.java b/ojluni/src/main/java/java/util/Spliterators.java
index 3f97a83..79c0ef3 100644
--- a/ojluni/src/main/java/java/util/Spliterators.java
+++ b/ojluni/src/main/java/java/util/Spliterators.java
@@ -384,7 +384,7 @@
      */
     private static void checkFromToBounds(int arrayLength, int origin, int fence) {
         if (origin > fence) {
-            throw new IllegalArgumentException(
+            throw new ArrayIndexOutOfBoundsException(
                     "origin(" + origin + ") > fence(" + fence + ")");
         }
         if (origin < 0) {
diff --git a/ojluni/src/main/java/java/util/TimSort.java b/ojluni/src/main/java/java/util/TimSort.java
index 9966f74..ea0d58f 100755
--- a/ojluni/src/main/java/java/util/TimSort.java
+++ b/ojluni/src/main/java/java/util/TimSort.java
@@ -174,10 +174,14 @@
          * large) stack lengths for smaller arrays.  The "magic numbers" in the
          * computation below must be changed if MIN_MERGE is decreased.  See
          * the MIN_MERGE declaration above for more information.
+         * The maximum value of 49 allows for an array up to length
+         * Integer.MAX_VALUE-4, if array is filled by the worst case stack size
+         * increasing scenario. More explanations are given in section 4 of:
+         * http://envisage-project.eu/wp-content/uploads/2015/02/sorting.pdf
          */
         int stackLen = (len <    120  ?  5 :
                         len <   1542  ? 10 :
-                        len < 119151  ? 24 : 40);
+                        len < 119151  ? 24 : 49);
         runBase = new int[stackLen];
         runLen = new int[stackLen];
     }
diff --git a/ojluni/src/main/java/java/util/TreeMap.java b/ojluni/src/main/java/java/util/TreeMap.java
index 76e9b00..5e26f0f 100755
--- a/ojluni/src/main/java/java/util/TreeMap.java
+++ b/ojluni/src/main/java/java/util/TreeMap.java
@@ -998,6 +998,27 @@
     }
 
     @Override
+    public boolean replace(K key, V oldValue, V newValue) {
+        TreeMapEntry<K,V> p = getEntry(key);
+        if (p!=null && Objects.equals(oldValue, p.value)) {
+            p.value = newValue;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public V replace(K key, V value) {
+        TreeMapEntry<K,V> p = getEntry(key);
+        if (p!=null) {
+            V oldValue = p.value;
+            p.value = value;
+            return oldValue;
+        }
+        return null;
+    }
+
+    @Override
     public void forEach(BiConsumer<? super K, ? super V> action) {
         Objects.requireNonNull(action);
         int expectedModCount = modCount;
@@ -1010,6 +1031,20 @@
         }
     }
 
+    @Override
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        Objects.requireNonNull(function);
+        int expectedModCount = modCount;
+
+        for (TreeMapEntry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
+            e.value = function.apply(e.key, e.value);
+
+            if (expectedModCount != modCount) {
+                throw new ConcurrentModificationException();
+            }
+        }
+    }
+
     // View class support
 
     class Values extends AbstractCollection<V> {
diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java
index 9edf7b7..7785e05 100755
--- a/ojluni/src/main/java/java/util/WeakHashMap.java
+++ b/ojluni/src/main/java/java/util/WeakHashMap.java
@@ -28,6 +28,7 @@
 import java.lang.ref.WeakReference;
 import java.lang.ref.ReferenceQueue;
 import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 
@@ -188,68 +189,6 @@
      */
     int modCount;
 
-    /**
-     * The default threshold of map capacity above which alternative hashing is
-     * used for String keys. Alternative hashing reduces the incidence of
-     * collisions due to weak hash code calculation for String keys.
-     * <p/>
-     * This value may be overridden by defining the system property
-     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
-     * forces alternative hashing to be used at all times whereas
-     * {@code -1} value ensures that alternative hashing is never used.
-     */
-    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
-
-    /**
-     * holds values which can't be initialized until after VM is booted.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                if (threshold < 0) {
-                    throw new IllegalArgumentException("value must be positive integer.");
-                }
-            } catch(IllegalArgumentException failed) {
-                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
-            }
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * If {@code true} then perform alternate hashing to reduce the incidence of
-     * collisions due to weak hash code calculation.
-     */
-    transient boolean useAltHashing;
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find.
-     *
-     * This hash seed is only used if {@code useAltHashing} is true.
-     */
-    transient int hashSeed;
-
     @SuppressWarnings("unchecked")
     private Entry<K,V>[] newTable(int n) {
         return (Entry<K,V>[]) new Entry[n];
@@ -280,13 +219,6 @@
         table = newTable(capacity);
         this.loadFactor = loadFactor;
         threshold = (int)(capacity * loadFactor);
-        useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        if (useAltHashing) {
-            hashSeed = sun.misc.Hashing.randomHashSeed(this);
-        } else {
-            hashSeed = 0;
-        }
     }
 
     /**
@@ -355,34 +287,6 @@
     }
 
     /**
-     * Retrieve object hash code and applies a supplemental hash function to the
-     * result hash, which defends against poor quality hash functions.  This is
-     * critical because HashMap uses power-of-two length hash tables, that
-     * otherwise encounter collisions for hashCodes that do not differ
-     * in lower bits.
-     */
-    int hash(Object k) {
-
-        int h;
-        if (useAltHashing) {
-            h = hashSeed;
-            if (k instanceof String) {
-                return sun.misc.Hashing.stringHash32((String) k);
-            } else {
-                h ^= k.hashCode();
-            }
-        } else  {
-            h = k.hashCode();
-        }
-
-        // This function ensures that hashCodes that differ only by
-        // constant multiples at each bit position have a bounded
-        // number of collisions (approximately 8 at default load factor).
-        h ^= (h >>> 20) ^ (h >>> 12);
-        return h ^ (h >>> 7) ^ (h >>> 4);
-    }
-
-    /**
      * Returns index for hash code h.
      */
     private static int indexFor(int h, int length) {
@@ -471,7 +375,7 @@
      */
     public V get(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -501,7 +405,7 @@
      */
     Entry<K,V> getEntry(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -524,7 +428,7 @@
      */
     public V put(K key, V value) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
 
@@ -568,14 +472,7 @@
         }
 
         Entry<K,V>[] newTable = newTable(newCapacity);
-        boolean oldAltHashing = useAltHashing;
-        useAltHashing |= sun.misc.VM.isBooted() &&
-                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean rehash = oldAltHashing ^ useAltHashing;
-        if (rehash) {
-            hashSeed = sun.misc.Hashing.randomHashSeed(this);
-        }
-        transfer(oldTable, newTable, rehash);
+        transfer(oldTable, newTable);
         table = newTable;
 
         /*
@@ -587,13 +484,13 @@
             threshold = (int)(newCapacity * loadFactor);
         } else {
             expungeStaleEntries();
-            transfer(newTable, oldTable, false);
+            transfer(newTable, oldTable);
             table = oldTable;
         }
     }
 
     /** Transfers all entries from src to dest tables */
-    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest, boolean rehash) {
+    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
         for (int j = 0; j < src.length; ++j) {
             Entry<K,V> e = src[j];
             src[j] = null;
@@ -605,9 +502,6 @@
                     e.value = null; //  "   "
                     size--;
                 } else {
-                    if (rehash) {
-                        e.hash = hash(key);
-                    }
                     int i = indexFor(e.hash, dest.length);
                     e.next = dest[i];
                     dest[i] = e;
@@ -676,7 +570,7 @@
      */
     public V remove(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
@@ -707,7 +601,7 @@
         Entry<K,V>[] tab = getTable();
         Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
         Object k = maskNull(entry.getKey());
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
         Entry<K,V> e = prev;
@@ -1114,6 +1008,29 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        Objects.requireNonNull(function);
+        int expectedModCount = modCount;
+
+        Entry<K, V>[] tab = getTable();
+        for (Entry<K, V> entry : tab) {
+            while (entry != null) {
+                Object key = entry.get();
+                if (key != null) {
+                    entry.value = function.apply((K)WeakHashMap.unmaskNull(key), entry.value);
+                }
+                entry = entry.next;
+
+                if (expectedModCount != modCount) {
+                    throw new ConcurrentModificationException();
+                }
+            }
+        }
+    }
+
+
     /**
      * Similar form as other hash Spliterators, but skips dead
      * elements.
diff --git a/ojluni/src/main/java/java/util/jar/Attributes.java b/ojluni/src/main/java/java/util/jar/Attributes.java
index 5fc1c91..d7f68a0 100755
--- a/ojluni/src/main/java/java/util/jar/Attributes.java
+++ b/ojluni/src/main/java/java/util/jar/Attributes.java
@@ -45,7 +45,7 @@
  * the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70
  * characters in length. Attribute values can contain any characters and
  * will be UTF8-encoded when written to the output stream.  See the
- * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a>
+ * <a href="{@docRoot}/../technotes/guides/jar/jar.html">JAR File Specification</a>
  * for more information about valid attribute names and values.
  *
  * @author  David Connelly
@@ -442,7 +442,7 @@
      * to the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed
      * 70 characters in length. Attribute values can contain any characters
      * and will be UTF8-encoded when written to the output stream.  See the
-     * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a>
+     * <a href="{@docRoot}/../technotes/guides/jar/jar.html">JAR File Specification</a>
      * for more information about valid attribute names and values.
      */
     public static class Name {
@@ -528,7 +528,7 @@
          * <code>Name</code> object for <code>Manifest-Version</code>
          * manifest attribute. This attribute indicates the version number
          * of the manifest standard to which a JAR file's manifest conforms.
-         * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest">
+         * @see <a href="{@docRoot}/../technotes/guides/jar/jar.html#JAR Manifest">
          *      Manifest and Signature Specification</a>
          */
         public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
@@ -536,7 +536,7 @@
         /**
          * <code>Name</code> object for <code>Signature-Version</code>
          * manifest attribute used when signing JAR files.
-         * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest">
+         * @see <a href="{@docRoot}/../technotes/guides/jar/jar.html#JAR Manifest">
          *      Manifest and Signature Specification</a>
          */
         public static final Name SIGNATURE_VERSION = new Name("Signature-Version");
@@ -551,7 +551,7 @@
          * <code>Name</code> object for <code>Class-Path</code>
          * manifest attribute. Bundled extensions can use this attribute
          * to find other JAR files containing needed classes.
-         * @see <a href="../../../../technotes/guides/extensions/spec.html#bundled">
+         * @see <a href="{@docRoot}/../technotes/guides/extensions/spec.html#bundled">
          *      Extensions Specification</a>
          */
         public static final Name CLASS_PATH = new Name("Class-Path");
@@ -568,7 +568,7 @@
         /**
          * <code>Name</code> object for <code>Sealed</code> manifest attribute
          * used for sealing.
-         * @see <a href="../../../../technotes/guides/extensions/spec.html#sealing">
+         * @see <a href="{@docRoot}/../technotes/guides/extensions/spec.html#sealing">
          *      Extension Sealing</a>
          */
         public static final Name SEALED = new Name("Sealed");
@@ -576,7 +576,7 @@
        /**
          * <code>Name</code> object for <code>Extension-List</code> manifest attribute
          * used for declaring dependencies on installed extensions.
-         * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
+         * @see <a href="{@docRoot}/../technotes/guides/extensions/spec.html#dependency">
          *      Installed extension dependency</a>
          */
         public static final Name EXTENSION_LIST = new Name("Extension-List");
@@ -584,7 +584,7 @@
         /**
          * <code>Name</code> object for <code>Extension-Name</code> manifest attribute
          * used for declaring dependencies on installed extensions.
-         * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
+         * @see <a href="{@docRoot}/../technotes/guides/extensions/spec.html#dependency">
          *      Installed extension dependency</a>
          */
         public static final Name EXTENSION_NAME = new Name("Extension-Name");
@@ -592,7 +592,7 @@
         /**
          * <code>Name</code> object for <code>Extension-Name</code> manifest attribute
          * used for declaring dependencies on installed extensions.
-         * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
+         * @see <a href="{@docRoot}/../technotes/guides/extensions/spec.html#dependency">
          *      Installed extension dependency</a>
          */
         public static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation");
@@ -600,7 +600,7 @@
         /**
          * <code>Name</code> object for <code>Implementation-Title</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title");
@@ -608,7 +608,7 @@
         /**
          * <code>Name</code> object for <code>Implementation-Version</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version");
@@ -616,7 +616,7 @@
         /**
          * <code>Name</code> object for <code>Implementation-Vendor</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");
@@ -624,7 +624,7 @@
         /**
          * <code>Name</code> object for <code>Implementation-Vendor-Id</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
@@ -632,7 +632,7 @@
        /**
          * <code>Name</code> object for <code>Implementation-Vendor-URL</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");
@@ -640,7 +640,7 @@
         /**
          * <code>Name</code> object for <code>Specification-Title</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name SPECIFICATION_TITLE = new Name("Specification-Title");
@@ -648,7 +648,7 @@
         /**
          * <code>Name</code> object for <code>Specification-Version</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name SPECIFICATION_VERSION = new Name("Specification-Version");
@@ -656,7 +656,7 @@
         /**
          * <code>Name</code> object for <code>Specification-Vendor</code>
          * manifest attribute used for package versioning.
-         * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
+         * @see <a href="{@docRoot}/../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
          */
         public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");
diff --git a/ojluni/src/main/java/java/util/jar/JarFile.java b/ojluni/src/main/java/java/util/jar/JarFile.java
index a0d0de9..f219505 100755
--- a/ojluni/src/main/java/java/util/jar/JarFile.java
+++ b/ojluni/src/main/java/java/util/jar/JarFile.java
@@ -174,7 +174,7 @@
         return getManifestFromReference();
     }
 
-    private Manifest getManifestFromReference() throws IOException {
+    private synchronized Manifest getManifestFromReference() throws IOException {
         Manifest man = manRef != null ? manRef.get() : null;
 
         if (man == null) {
@@ -474,7 +474,7 @@
         optoSft[9]=1;
     }
 
-    private JarEntry getManEntry() {
+    private synchronized JarEntry getManEntry() {
         if (manEntry == null) {
             // First look up manifest entry using standard name
             manEntry = getJarEntry(MANIFEST_NAME);
@@ -591,100 +591,6 @@
         return new JarFileEntry(ze);
     }
 
-    Enumeration<String> entryNames(CodeSource[] cs) {
-        ensureInitialization();
-        if (jv != null) {
-            return jv.entryNames(this, cs);
-        }
-
-        /*
-         * JAR file has no signed content. Is there a non-signing
-         * code source?
-         */
-        boolean includeUnsigned = false;
-        for (int i = 0; i < cs.length; i++) {
-            if (cs[i].getCodeSigners() == null) {
-                includeUnsigned = true;
-                break;
-            }
-        }
-        if (includeUnsigned) {
-            return unsignedEntryNames();
-        } else {
-            return new Enumeration<String>() {
-
-                public boolean hasMoreElements() {
-                    return false;
-                }
-
-                public String nextElement() {
-                    throw new NoSuchElementException();
-                }
-            };
-        }
-    }
-
-    /**
-     * Returns an enumeration of the zip file entries
-     * excluding internal JAR mechanism entries and including
-     * signed entries missing from the ZIP directory.
-     */
-    Enumeration<JarEntry> entries2() {
-        ensureInitialization();
-        if (jv != null) {
-            return jv.entries2(this, super.entries());
-        }
-
-        // screen out entries which are never signed
-        final Enumeration enum_ = super.entries();
-        return new Enumeration<JarEntry>() {
-
-            ZipEntry entry;
-
-            public boolean hasMoreElements() {
-                if (entry != null) {
-                    return true;
-                }
-                while (enum_.hasMoreElements()) {
-                    ZipEntry ze = (ZipEntry) enum_.nextElement();
-                    if (JarVerifier.isSigningRelated(ze.getName())) {
-                        continue;
-                    }
-                    entry = ze;
-                    return true;
-                }
-                return false;
-            }
-
-            public JarFileEntry nextElement() {
-                if (hasMoreElements()) {
-                    ZipEntry ze = entry;
-                    entry = null;
-                    return new JarFileEntry(ze);
-                }
-                throw new NoSuchElementException();
-            }
-        };
-    }
-
-    CodeSource[] getCodeSources(URL url) {
-        ensureInitialization();
-        if (jv != null) {
-            return jv.getCodeSources(this, url);
-        }
-
-        /*
-         * JAR file has no signed content. Is there a non-signing
-         * code source?
-         */
-        Enumeration unsigned = unsignedEntryNames();
-        if (unsigned.hasMoreElements()) {
-            return new CodeSource[]{JarVerifier.getUnsignedCS(url)};
-        } else {
-            return null;
-        }
-    }
-
     private Enumeration<String> unsignedEntryNames() {
         final Enumeration entries = entries();
         return new Enumeration<String>() {
@@ -722,43 +628,4 @@
             }
         };
     }
-
-    CodeSource getCodeSource(URL url, String name) {
-        ensureInitialization();
-        if (jv != null) {
-            if (jv.eagerValidation) {
-                CodeSource cs = null;
-                JarEntry je = getJarEntry(name);
-                if (je != null) {
-                    cs = jv.getCodeSource(url, this, je);
-                } else {
-                    cs = jv.getCodeSource(url, name);
-                }
-                return cs;
-            } else {
-                return jv.getCodeSource(url, name);
-            }
-        }
-
-        return JarVerifier.getUnsignedCS(url);
-    }
-
-    void setEagerValidation(boolean eager) {
-        try {
-            maybeInstantiateVerifier();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        if (jv != null) {
-            jv.setEagerValidation(eager);
-        }
-    }
-
-    List getManifestDigests() {
-        ensureInitialization();
-        if (jv != null) {
-            return jv.getManifestDigests();
-        }
-        return new ArrayList();
-    }
 }
diff --git a/ojluni/src/main/java/java/util/jar/Manifest.java b/ojluni/src/main/java/java/util/jar/Manifest.java
index b6c7c3b..092926b 100755
--- a/ojluni/src/main/java/java/util/jar/Manifest.java
+++ b/ojluni/src/main/java/java/util/jar/Manifest.java
@@ -39,7 +39,7 @@
  * associated Attributes. There are main Manifest Attributes as well as
  * per-entry Attributes. For information on the Manifest format, please
  * see the
- * <a href="../../../../technotes/guides/jar/jar.html">
+ * <a href="{@docRoot}/../technotes/guides/jar/jar.html">
  * Manifest format specification</a>.
  *
  * @author  David Connelly
diff --git a/ojluni/src/main/java/java/util/jar/package.html b/ojluni/src/main/java/java/util/jar/package.html
index dd9ad73..f485e63 100755
--- a/ojluni/src/main/java/java/util/jar/package.html
+++ b/ojluni/src/main/java/java/util/jar/package.html
@@ -45,7 +45,7 @@
       package description.</a> <p>
       In JAR files, all file names must be encoded in the UTF-8 encoding. 
 <p>
-  <li><a href="../../../../technotes/guides/jar/jar.html">
+  <li><a href="{@docRoot}/../technotes/guides/jar/jar.html">
       Manifest and Signature Specification</a> - The manifest format specification.
 </ul>
 
diff --git a/ojluni/src/main/java/java/util/logging/Logger.java b/ojluni/src/main/java/java/util/logging/Logger.java
index e9728de..3652914 100755
--- a/ojluni/src/main/java/java/util/logging/Logger.java
+++ b/ojluni/src/main/java/java/util/logging/Logger.java
@@ -329,7 +329,7 @@
                     return System.getProperty(key);
                 }
             });
-            return Boolean.valueOf(s);
+            return Boolean.parseBoolean(s);
         }
     }
 
diff --git a/ojluni/src/main/java/java/util/logging/package.html b/ojluni/src/main/java/java/util/logging/package.html
index cafcdad..0dd7882 100755
--- a/ojluni/src/main/java/java/util/logging/package.html
+++ b/ojluni/src/main/java/java/util/logging/package.html
@@ -116,7 +116,7 @@
 <P>
 For an overview of control flow, 
 please refer to the 
-<a href="../../../../technotes/guides/logging/overview.html">
+<a href="{@docRoot}/../technotes/guides/logging/overview.html">
 Java Logging Overview</a>.
 </P>
 
diff --git a/ojluni/src/main/java/java/util/package.html b/ojluni/src/main/java/java/util/package.html
index a655934..d062b97 100755
--- a/ojluni/src/main/java/java/util/package.html
+++ b/ojluni/src/main/java/java/util/package.html
@@ -35,8 +35,8 @@
 
 <h2>Package Specification</h2>
 <ul>
-  <li><a href="../../../technotes/guides/collections/overview.html"><b>Collections Framework Overview</b></a>
-  <li><a href="../../../technotes/guides/collections/reference.html"><b>
+  <li><a href="{@docRoot}/../technotes/guides/collections/overview.html"><b>Collections Framework Overview</b></a>
+  <li><a href="{@docRoot}/../technotes/guides/collections/reference.html"><b>
        Collections Framework Annotated Outline</b></a>
 </ul>
 
@@ -46,7 +46,7 @@
     <li><a href="http://www.java.sun.com/docs/books/tutorial/collections/">
        <b>Collections Framework Tutorial</b></a>
     <li><a
-    href="../../../technotes/guides/collections/designfaq.html"><b>Collections
+    href="{@docRoot}/../technotes/guides/collections/designfaq.html"><b>Collections
     Framework Design FAQ</b></a>
 </ul>
 
diff --git a/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java b/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java
index c655ea1..a9c0962 100755
--- a/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java
+++ b/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java
@@ -53,15 +53,6 @@
 // Android changed: @hide.
 public class FileSystemPreferences extends AbstractPreferences {
     /**
-     * Sync interval in seconds.
-     */
-    private static final int SYNC_INTERVAL = Math.max(1,
-        Integer.parseInt(
-            AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "java.util.prefs.syncInterval", "30"))));
-
-    /**
      * Returns logger for error messages. Backing store exceptions are logged at
      * WARNING level.
      */
@@ -427,27 +418,12 @@
             changeLog.get(i).replay();
     }
 
-    private static Timer syncTimer = new Timer(true); // Daemon Thread
-
     static {
-        // Add periodic timer task to periodically sync cached prefs
-        syncTimer.schedule(new TimerTask() {
+        // Add shutdown hook to flush cached prefs on normal termination
+        Runtime.getRuntime().addShutdownHook(new Thread() {
             public void run() {
                 syncWorld();
             }
-        }, SYNC_INTERVAL*1000, SYNC_INTERVAL*1000);
-
-        // Add shutdown hook to flush cached prefs on normal termination
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            public Void run() {
-                Runtime.getRuntime().addShutdownHook(new Thread() {
-                    public void run() {
-                        syncTimer.cancel();
-                        syncWorld();
-                    }
-                });
-                return null;
-            }
         });
     }
 
diff --git a/ojluni/src/main/java/java/util/regex/Matcher.java b/ojluni/src/main/java/java/util/regex/Matcher.java
index 47062d7..dc37946 100755
--- a/ojluni/src/main/java/java/util/regex/Matcher.java
+++ b/ojluni/src/main/java/java/util/regex/Matcher.java
@@ -26,6 +26,7 @@
 
 package java.util.regex;
 
+import libcore.util.NativeAllocationRegistry;
 
 /**
  * An engine that performs match operations on a {@link java.lang.CharSequence
@@ -115,6 +116,14 @@
     private long address;
 
     /**
+     * If non-null, a Runnable that can be used to explicitly deallocate address.
+     */
+    private Runnable nativeFinalizer;
+
+    private static final NativeAllocationRegistry registry = new NativeAllocationRegistry(
+            getNativeFinalizer(), nativeSize());
+
+    /**
      * Holds the input text.
      */
     private String input;
@@ -211,11 +220,13 @@
         this.pattern = newPattern;
 
         synchronized (this) {
-            if (address != 0) {
-                closeImpl(address);
+            if (nativeFinalizer != null) {
+                nativeFinalizer.run();
                 address = 0; // In case openImpl throws.
+                nativeFinalizer = null;
             }
             address = openImpl(pattern.address);
+            nativeFinalizer = registry.registerNativeAllocation(this, address);
         }
 
         if (input != null) {
@@ -1041,16 +1052,6 @@
         }
     }
 
-    @Override protected void finalize() throws Throwable {
-        try {
-            synchronized (this) {
-                closeImpl(address);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
     /**
      * Returns the start index of the previous match.  </p>
      *
@@ -1093,13 +1094,14 @@
         return matchOffsets[group * 2];
     }
 
-    private static native void closeImpl(long addr);
     private static native boolean findImpl(long addr, String s, int startIndex, int[] offsets);
     private static native boolean findNextImpl(long addr, String s, int[] offsets);
+    private static native long getNativeFinalizer();
     private static native int groupCountImpl(long addr);
     private static native boolean hitEndImpl(long addr);
     private static native boolean lookingAtImpl(long addr, String s, int[] offsets);
     private static native boolean matchesImpl(long addr, String s, int[] offsets);
+    private static native int nativeSize();
     private static native long openImpl(long patternAddr);
     private static native boolean requireEndImpl(long addr);
     private static native void setInputImpl(long addr, String s, int start, int end);
diff --git a/ojluni/src/main/java/java/util/regex/Pattern.java b/ojluni/src/main/java/java/util/regex/Pattern.java
index 8f6fe1f..1d772d9 100755
--- a/ojluni/src/main/java/java/util/regex/Pattern.java
+++ b/ojluni/src/main/java/java/util/regex/Pattern.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,18 @@
 
 package java.util.regex;
 
-import java.util.ArrayList;
+import libcore.util.NativeAllocationRegistry;
 
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import libcore.util.EmptyArray;
 
 /**
  * A compiled representation of a regular expression.
@@ -919,6 +929,9 @@
 
     transient long address;
 
+    private static final NativeAllocationRegistry registry = new NativeAllocationRegistry(
+            getNativeFinalizer(), nativeSize());
+
 
     /**
      * Compiles the given regular expression into a pattern.  </p>
@@ -1096,6 +1109,11 @@
      *          around matches of this pattern
      */
     public String[] split(CharSequence input, int limit) {
+        String[] fast = fastSplit(pattern, input.toString(), limit);
+        if (fast != null) {
+            return fast;
+        }
+
         int index = 0;
         boolean matchLimited = limit > 0;
         ArrayList<String> matchList = new ArrayList<>();
@@ -1132,6 +1150,85 @@
         return matchList.subList(0, resultSize).toArray(result);
     }
 
+    private static final String FASTSPLIT_METACHARACTERS = "\\?*+[](){}^$.|";
+
+    /**
+     * Returns a result equivalent to {@code s.split(separator, limit)} if it's able
+     * to compute it more cheaply than native impl, or null if the caller should fall back to
+     * using native impl.
+     *
+     *  fastpath will work  if the regex is a
+     *   (1)one-char String and this character is not one of the
+     *      RegEx's meta characters ".$|()[{^?*+\\", or
+     *   (2)two-char String and the first char is the backslash and
+     *      the second is one of regEx's meta characters ".$|()[{^?*+\\".
+     * @hide
+     */
+    public static String[] fastSplit(String re, String input, int limit) {
+        // Can we do it cheaply?
+        int len = re.length();
+        if (len == 0) {
+            return null;
+        }
+        char ch = re.charAt(0);
+        if (len == 1 && FASTSPLIT_METACHARACTERS.indexOf(ch) == -1) {
+            // We're looking for a single non-metacharacter. Easy.
+        } else if (len == 2 && ch == '\\') {
+            // We're looking for a quoted character.
+            // Quoted metacharacters are effectively single non-metacharacters.
+            ch = re.charAt(1);
+            if (FASTSPLIT_METACHARACTERS.indexOf(ch) == -1) {
+                return null;
+            }
+        } else {
+            return null;
+        }
+
+        // We can do this cheaply...
+
+        // Unlike Perl, which considers the result of splitting the empty string to be the empty
+        // array, Java returns an array containing the empty string.
+        if (input.isEmpty()) {
+            return new String[] { "" };
+        }
+
+        // Count separators
+        int separatorCount = 0;
+        int begin = 0;
+        int end;
+        while (separatorCount + 1 != limit && (end = input.indexOf(ch, begin)) != -1) {
+            ++separatorCount;
+            begin = end + 1;
+        }
+        int lastPartEnd = input.length();
+        if (limit == 0 && begin == lastPartEnd) {
+            // Last part is empty for limit == 0, remove all trailing empty matches.
+            if (separatorCount == lastPartEnd) {
+                // Input contains only separators.
+                return EmptyArray.STRING;
+            }
+            // Find the beginning of trailing separators.
+            do {
+                --begin;
+            } while (input.charAt(begin - 1) == ch);
+            // Reduce separatorCount and fix lastPartEnd.
+            separatorCount -= input.length() - begin;
+            lastPartEnd = begin;
+        }
+
+        // Collect the result parts.
+        String[] result = new String[separatorCount + 1];
+        begin = 0;
+        for (int i = 0; i != separatorCount; ++i) {
+            end = input.indexOf(ch, begin);
+            result[i] = input.substring(begin, end);
+            begin = end + 1;
+        }
+        // Add last part.
+        result[separatorCount] = input.substring(begin, lastPartEnd);
+        return result;
+    }
+
     /**
      * Splits the given input sequence around matches of this pattern.
      *
@@ -1241,18 +1338,118 @@
         // They even have the same value in native code.
         int icuFlags = flags & (CASE_INSENSITIVE | COMMENTS | MULTILINE | DOTALL | UNIX_LINES);
         address = compileImpl(icuPattern, icuFlags);
+        registry.registerNativeAllocation(this, address);
     }
 
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            closeImpl(address);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private static native void closeImpl(long addr);
     private static native long compileImpl(String regex, int flags);
+    private static native long getNativeFinalizer();
+    private static native int nativeSize();
+
+    /**
+     * Creates a predicate which can be used to match a string.
+     *
+     * @return  The predicate which can be used for matching on a string
+     * @since   1.8
+     */
+    public Predicate<String> asPredicate() {
+        return s -> matcher(s).find();
+    }
+
+    /**
+     * Creates a stream from the given input sequence around matches of this
+     * pattern.
+     *
+     * <p> The stream returned by this method contains each substring of the
+     * input sequence that is terminated by another subsequence that matches
+     * this pattern or is terminated by the end of the input sequence.  The
+     * substrings in the stream are in the order in which they occur in the
+     * input. Trailing empty strings will be discarded and not encountered in
+     * the stream.
+     *
+     * <p> If this pattern does not match any subsequence of the input then
+     * the resulting stream has just one element, namely the input sequence in
+     * string form.
+     *
+     * <p> When there is a positive-width match at the beginning of the input
+     * sequence then an empty leading substring is included at the beginning
+     * of the stream. A zero-width match at the beginning however never produces
+     * such empty leading substring.
+     *
+     * <p> If the input sequence is mutable, it must remain constant during the
+     * execution of the terminal stream operation.  Otherwise, the result of the
+     * terminal stream operation is undefined.
+     *
+     * @param   input
+     *          The character sequence to be split
+     *
+     * @return  The stream of strings computed by splitting the input
+     *          around matches of this pattern
+     * @see     #split(CharSequence)
+     * @since   1.8
+     */
+    public Stream<String> splitAsStream(final CharSequence input) {
+        class MatcherIterator implements Iterator<String> {
+            private final Matcher matcher;
+            // The start position of the next sub-sequence of input
+            // when current == input.length there are no more elements
+            private int current;
+            // null if the next element, if any, needs to obtained
+            private String nextElement;
+            // > 0 if there are N next empty elements
+            private int emptyElementCount;
+
+            MatcherIterator() {
+                this.matcher = matcher(input);
+            }
+
+            public String next() {
+                if (!hasNext())
+                    throw new NoSuchElementException();
+
+                if (emptyElementCount == 0) {
+                    String n = nextElement;
+                    nextElement = null;
+                    return n;
+                } else {
+                    emptyElementCount--;
+                    return "";
+                }
+            }
+
+            public boolean hasNext() {
+                if (nextElement != null || emptyElementCount > 0)
+                    return true;
+
+                if (current == input.length())
+                    return false;
+
+                // Consume the next matching element
+                // Count sequence of matching empty elements
+                while (matcher.find()) {
+                    nextElement = input.subSequence(current, matcher.start()).toString();
+                    current = matcher.end();
+                    if (!nextElement.isEmpty()) {
+                        return true;
+                    } else if (current > 0) { // no empty leading substring for zero-width
+                                              // match at the beginning of the input
+                        emptyElementCount++;
+                    }
+                }
+
+                // Consume last matching element
+                nextElement = input.subSequence(current, input.length()).toString();
+                current = input.length();
+                if (!nextElement.isEmpty()) {
+                    return true;
+                } else {
+                    // Ignore a terminal sequence of matching empty elements
+                    emptyElementCount = 0;
+                    nextElement = null;
+                    return false;
+                }
+            }
+        }
+        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
+                new MatcherIterator(), Spliterator.ORDERED | Spliterator.NONNULL), false);
+    }
 }
diff --git a/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java b/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java
index 7abb25b..5308d812 100755
--- a/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java
+++ b/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java
@@ -44,7 +44,7 @@
  * <p>
  * <h4>Packaging of Locale Sensitive Service Provider Implementations</h4>
  * Implementations of these locale sensitive services are packaged using the
- * <a href="../../../../technotes/guides/extensions/index.html">Java Extension Mechanism</a>
+ * <a href="{@docRoot}/../technotes/guides/extensions/index.html">Java Extension Mechanism</a>
  * as installed extensions.  A provider identifies itself with a
  * provider-configuration file in the resource directory META-INF/services,
  * using the fully qualified provider interface class name as the file name.
diff --git a/ojluni/src/main/java/java/util/stream/LongStream.java b/ojluni/src/main/java/java/util/stream/LongStream.java
index 33d74ec..84189ef 100644
--- a/ojluni/src/main/java/java/util/stream/LongStream.java
+++ b/ojluni/src/main/java/java/util/stream/LongStream.java
@@ -24,6 +24,7 @@
  */
 package java.util.stream;
 
+import java.math.BigInteger;
 import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Collection;
@@ -790,8 +791,11 @@
             // Split the range in two and concatenate
             // Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE) then
             // the lower range, [Long.MIN_VALUE, 0) will be further split in two
-            // Android-changed: no divideUnsigned support yet
-            long m = startInclusive + ((endExclusive - startInclusive) / 2) + 1;
+            // Android-changed: no divideUnsigned support yet, use BigInteger instead.
+            long m = startInclusive +
+                BigInteger.valueOf(endExclusive).subtract(BigInteger.valueOf(startInclusive))
+                     .divide(BigInteger.valueOf(2)).longValue() + 1;
+
             return concat(range(startInclusive, m), range(m, endExclusive));
         } else {
             return StreamSupport.longStream(
@@ -825,8 +829,11 @@
             // Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE] then
             // the lower range, [Long.MIN_VALUE, 0), and upper range,
             // [0, Long.MAX_VALUE], will both be further split in two
-            // Android-changed: no divideUnsigned support yet
-            long m = startInclusive + ((endInclusive - startInclusive) / 2) + 1;
+            // Android-changed: no divideUnsigned support yet, use BigInteger instead.
+            long m = startInclusive +
+                BigInteger.valueOf(endInclusive).subtract(BigInteger.valueOf(startInclusive))
+                     .divide(BigInteger.valueOf(2)).longValue() + 1;
+
             return concat(range(startInclusive, m), rangeClosed(m, endInclusive));
         } else {
             return StreamSupport.longStream(
diff --git a/ojluni/src/main/java/javax/security/sasl/package.html b/ojluni/src/main/java/javax/security/sasl/package.html
index cf497eb..7d9ba43 100755
--- a/ojluni/src/main/java/javax/security/sasl/package.html
+++ b/ojluni/src/main/java/javax/security/sasl/package.html
@@ -102,7 +102,7 @@
 <h2>Related Documentation</h2>
 
 Please refer to the 
-<a href="../../../../technotes/guides/security/sasl/sasl-refguide.html">Java 
+<a href="{@docRoot}/../technotes/guides/security/sasl/sasl-refguide.html">Java 
 SASL Programming Guide</a> for information on how to use this API.
 
 
diff --git a/ojluni/src/main/java/sun/misc/Hashing.java b/ojluni/src/main/java/sun/misc/Hashing.java
index 50e55ab..2b3b144 100755
--- a/ojluni/src/main/java/sun/misc/Hashing.java
+++ b/ojluni/src/main/java/sun/misc/Hashing.java
@@ -25,9 +25,6 @@
 package sun.misc;
 
 import java.util.concurrent.ThreadLocalRandom;
-// ----- BEGIN android -----
-import java.lang.JavaLangAccess;
-// ----- END android -----
 
 /**
  * Hashing utilities.
@@ -43,212 +40,18 @@
         throw new Error("No instances");
     }
 
-    public static int murmur3_32(byte[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
+    // Spread bits to regularize both segment and index locations,
+    // using variant of single-word Wang/Jenkins hash.
+    //
+    // Based on commit 1424a2a1a9fc53dc8b859a77c02c924.
+    public static int singleWordWangJenkinsHash(Object k) {
+        int h = k.hashCode();
 
-    public static int murmur3_32(int seed, byte[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    @SuppressWarnings("fallthrough")
-    public static int murmur3_32(int seed, byte[] data, int offset, int len) {
-        int h1 = seed;
-        int count = len;
-
-        // body
-        while (count >= 4) {
-            int k1 = (data[offset] & 0x0FF)
-                    | (data[offset + 1] & 0x0FF) << 8
-                    | (data[offset + 2] & 0x0FF) << 16
-                    | data[offset + 3] << 24;
-
-            count -= 4;
-            offset += 4;
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail
-
-        if (count > 0) {
-            int k1 = 0;
-
-            switch (count) {
-                case 3:
-                    k1 ^= (data[offset + 2] & 0xff) << 16;
-                // fall through
-                case 2:
-                    k1 ^= (data[offset + 1] & 0xff) << 8;
-                // fall through
-                case 1:
-                    k1 ^= (data[offset] & 0xff);
-                // fall through
-                default:
-                    k1 *= 0xcc9e2d51;
-                    k1 = Integer.rotateLeft(k1, 15);
-                    k1 *= 0x1b873593;
-                    h1 ^= k1;
-            }
-        }
-
-        // finalization
-
-        h1 ^= len;
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    public static int murmur3_32(char[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, char[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, char[] data, int offset, int len) {
-        int h1 = seed;
-
-        int off = offset;
-        int count = len;
-
-        // body
-        while (count >= 2) {
-            int k1 = (data[off++] & 0xFFFF) | (data[off++] << 16);
-
-            count -= 2;
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail
-
-        if (count > 0) {
-            int k1 = data[off];
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-            h1 ^= k1;
-        }
-
-        // finalization
-
-        h1 ^= len * (Character.SIZE / Byte.SIZE);
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    public static int murmur3_32(int[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, int[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, int[] data, int offset, int len) {
-        int h1 = seed;
-
-        int off = offset;
-        int end = offset + len;
-
-        // body
-        while (off < end) {
-            int k1 = data[off++];
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail (always empty, as body is always 32-bit chunks)
-
-        // finalization
-
-        h1 ^= len * (Integer.SIZE / Byte.SIZE);
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    /**
-     * Return a 32 bit hash value for the specified string. The algorithm is
-     * unspecified but will be consistent within a VM instance.
-     *
-     * @param string String to be hashed.
-     * @return hash value of the string.
-     */
-    public static int stringHash32(String string) {
-        // Android-changed: Access JavaLangAccess directly.
-        return JavaLangAccess.getStringHash32(string);
-    }
-
-    /**
-     * Return a non-zero 32-bit pseudo random value. The {@code instance} object
-     * may be used as part of the value.
-     *
-     * @param instance an object to use if desired in choosing value.
-     * @return a non-zero 32-bit pseudo random value.
-     */
-    public static int randomHashSeed(Object instance) {
-        int seed;
-        if (sun.misc.VM.isBooted()) {
-            seed = ThreadLocalRandom.current().nextInt();
-        } else {
-            // lower quality "random" seed value--still better than zero and not
-            // not practically reversible.
-            int hashing_seed[] = {
-                System.identityHashCode(Hashing.class),
-                System.identityHashCode(instance),
-                System.identityHashCode(Thread.currentThread()),
-                (int) Thread.currentThread().getId(),
-                (int) (System.currentTimeMillis() >>> 2), // resolution is poor
-                (int) (System.nanoTime() >>> 5), // resolution is poor
-                (int) (Runtime.getRuntime().freeMemory() >>> 4) // alloc min
-            };
-
-            seed = murmur3_32(hashing_seed);
-        }
-
-        // force to non-zero.
-        return (0 != seed) ? seed : 1;
+        h += (h <<  15) ^ 0xffffcd7d;
+        h ^= (h >>> 10);
+        h += (h <<   3);
+        h ^= (h >>>  6);
+        h += (h <<   2) + (h << 14);
+        return h ^ (h >>> 16);
     }
 }
diff --git a/ojluni/src/main/java/sun/misc/VM.java b/ojluni/src/main/java/sun/misc/VM.java
index e8af1d1..b57eb4a 100755
--- a/ojluni/src/main/java/sun/misc/VM.java
+++ b/ojluni/src/main/java/sun/misc/VM.java
@@ -295,7 +295,7 @@
         allowGetCallerClass = (s != null
                                    ? (s.isEmpty() || Boolean.parseBoolean(s))
                                    : true) ||
-             Boolean.valueOf(props.getProperty("jdk.logging.allowStackWalkSearch"));
+             Boolean.parseBoolean(props.getProperty("jdk.logging.allowStackWalkSearch"));
 
         // Remove other private system properties
         // used by java.lang.Integer.IntegerCache
diff --git a/ojluni/src/main/java/sun/misc/Version.java b/ojluni/src/main/java/sun/misc/Version.java
index 319180c..2908005 100644
--- a/ojluni/src/main/java/sun/misc/Version.java
+++ b/ojluni/src/main/java/sun/misc/Version.java
@@ -31,7 +31,7 @@
     // Android-changed : launcher_name, java_version,
     // java_runtime_name and java_runtime_version.
     private static final String launcher_name = "";
-    private static final String java_version = "0";
+    private static final String java_version = AndroidHardcodedSystemProperties.JAVA_VERSION;
     private static final String java_runtime_name = "Android Runtime";
     private static final String java_runtime_version = "0.9";
 
@@ -280,7 +280,7 @@
                     int nextChar = 3;
                     try {
                         String uu = cs.subSequence(1, 3).toString();
-                        jvm_update_version = Integer.valueOf(uu).intValue();
+                        jvm_update_version = Integer.parseInt(uu);
                         if (cs.length() >= 4) {
                             char c = cs.charAt(3);
                             if (c >= 'a' && c <= 'z') {
@@ -305,7 +305,7 @@
                             Character.isDigit(s.charAt(1)) &&
                             Character.isDigit(s.charAt(2))) {
                             jvm_build_number =
-                                Integer.valueOf(s.substring(1, 3)).intValue();
+                                Integer.parseInt(s.substring(1, 3));
                             break;
                         }
                     }
diff --git a/ojluni/src/main/java/sun/net/www/http/HttpClient.java b/ojluni/src/main/java/sun/net/www/http/HttpClient.java
index b5a4329..09e0dbb 100755
--- a/ojluni/src/main/java/sun/net/www/http/HttpClient.java
+++ b/ojluni/src/main/java/sun/net/www/http/HttpClient.java
@@ -150,13 +150,13 @@
             new sun.security.action.GetPropertyAction("sun.net.http.retryPost"));
 
         if (keepAlive != null) {
-            keepAliveProp = Boolean.valueOf(keepAlive).booleanValue();
+            keepAliveProp = Boolean.parseBoolean(keepAlive);
         } else {
             keepAliveProp = true;
         }
 
         if (retryPost != null) {
-            retryPostProp = Boolean.valueOf(retryPost).booleanValue();
+            retryPostProp = Boolean.parseBoolean(retryPost);
         } else
             retryPostProp = true;
 
diff --git a/ojluni/src/main/java/sun/nio/ch/AsynchronousChannelGroupImpl.java b/ojluni/src/main/java/sun/nio/ch/AsynchronousChannelGroupImpl.java
new file mode 100755
index 0000000..a584ce9
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/AsynchronousChannelGroupImpl.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.Channel;
+import java.nio.channels.AsynchronousChannelGroup;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.util.Queue;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import sun.security.action.GetIntegerAction;
+
+/**
+ * Base implementation of AsynchronousChannelGroup
+ */
+
+abstract class AsynchronousChannelGroupImpl
+    extends AsynchronousChannelGroup implements Executor
+{
+    // number of internal threads handling I/O events when using an unbounded
+    // thread pool. Internal threads do not dispatch to completion handlers.
+    private static final int internalThreadCount = AccessController.doPrivileged(
+        new GetIntegerAction("sun.nio.ch.internalThreadPoolSize", 1));
+
+    // associated thread pool
+    private final ThreadPool pool;
+
+    // number of tasks running (including internal)
+    private final AtomicInteger threadCount = new AtomicInteger();
+
+    // associated Executor for timeouts
+    private ScheduledThreadPoolExecutor timeoutExecutor;
+
+    // task queue for when using a fixed thread pool. In that case, thread
+    // waiting on I/O events must be awokon to poll tasks from this queue.
+    private final Queue<Runnable> taskQueue;
+
+    // group shutdown
+    private final AtomicBoolean shutdown = new AtomicBoolean();
+    private final Object shutdownNowLock = new Object();
+    private volatile boolean terminateInitiated;
+
+    AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
+                                 ThreadPool pool)
+    {
+        super(provider);
+        this.pool = pool;
+
+        if (pool.isFixedThreadPool()) {
+            taskQueue = new ConcurrentLinkedQueue<Runnable>();
+        } else {
+            taskQueue = null;   // not used
+        }
+
+        // use default thread factory as thread should not be visible to
+        // application (it doesn't execute completion handlers).
+        this.timeoutExecutor = (ScheduledThreadPoolExecutor)
+            Executors.newScheduledThreadPool(1, ThreadPool.defaultThreadFactory());
+        this.timeoutExecutor.setRemoveOnCancelPolicy(true);
+    }
+
+    final ExecutorService executor() {
+        return pool.executor();
+    }
+
+    final boolean isFixedThreadPool() {
+        return pool.isFixedThreadPool();
+    }
+
+    final int fixedThreadCount() {
+        if (isFixedThreadPool()) {
+            return pool.poolSize();
+        } else {
+            return pool.poolSize() + internalThreadCount;
+        }
+    }
+
+    private Runnable bindToGroup(final Runnable task) {
+        final AsynchronousChannelGroupImpl thisGroup = this;
+        return new Runnable() {
+            public void run() {
+                Invoker.bindToGroup(thisGroup);
+                task.run();
+            }
+        };
+    }
+
+    private void startInternalThread(final Runnable task) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                // internal threads should not be visible to application so
+                // cannot use user-supplied thread factory
+                ThreadPool.defaultThreadFactory().newThread(task).start();
+                return null;
+            }
+         });
+    }
+
+    protected final void startThreads(Runnable task) {
+        if (!isFixedThreadPool()) {
+            for (int i=0; i<internalThreadCount; i++) {
+                startInternalThread(task);
+                threadCount.incrementAndGet();
+            }
+        }
+        if (pool.poolSize() > 0) {
+            task = bindToGroup(task);
+            try {
+                for (int i=0; i<pool.poolSize(); i++) {
+                    pool.executor().execute(task);
+                    threadCount.incrementAndGet();
+                }
+            } catch (RejectedExecutionException  x) {
+                // nothing we can do
+            }
+        }
+    }
+
+    final int threadCount() {
+        return threadCount.get();
+    }
+
+    /**
+     * Invoked by tasks as they terminate
+     */
+    final int threadExit(Runnable task, boolean replaceMe) {
+        if (replaceMe) {
+            try {
+                if (Invoker.isBoundToAnyGroup()) {
+                    // submit new task to replace this thread
+                    pool.executor().execute(bindToGroup(task));
+                } else {
+                    // replace internal thread
+                    startInternalThread(task);
+                }
+                return threadCount.get();
+            } catch (RejectedExecutionException x) {
+                // unable to replace
+            }
+        }
+        return threadCount.decrementAndGet();
+    }
+
+    /**
+     * Wakes up a thread waiting for I/O events to execute the given task.
+     */
+    abstract void executeOnHandlerTask(Runnable task);
+
+    /**
+     * For a fixed thread pool the task is queued to a thread waiting on I/O
+     * events. For other thread pools we simply submit the task to the thread
+     * pool.
+     */
+    final void executeOnPooledThread(Runnable task) {
+        if (isFixedThreadPool()) {
+            executeOnHandlerTask(task);
+        } else {
+            pool.executor().execute(bindToGroup(task));
+        }
+    }
+
+    final void offerTask(Runnable task) {
+        taskQueue.offer(task);
+    }
+
+    final Runnable pollTask() {
+        return (taskQueue == null) ? null : taskQueue.poll();
+    }
+
+    final Future<?> schedule(Runnable task, long timeout, TimeUnit unit) {
+        try {
+            return timeoutExecutor.schedule(task, timeout, unit);
+        } catch (RejectedExecutionException rej) {
+            if (terminateInitiated) {
+                // no timeout scheduled as group is terminating
+                return null;
+            }
+            throw new AssertionError(rej);
+        }
+    }
+
+    @Override
+    public final boolean isShutdown() {
+        return shutdown.get();
+    }
+
+    @Override
+    public final boolean isTerminated()  {
+        return pool.executor().isTerminated();
+    }
+
+    /**
+     * Returns true if there are no channels in the group
+     */
+    abstract boolean isEmpty();
+
+    /**
+     * Attaches a foreign channel to this group.
+     */
+    abstract Object attachForeignChannel(Channel channel, FileDescriptor fdo)
+        throws IOException;
+
+    /**
+     * Detaches a foreign channel from this group.
+     */
+    abstract void detachForeignChannel(Object key);
+
+    /**
+     * Closes all channels in the group
+     */
+    abstract void closeAllChannels() throws IOException;
+
+    /**
+     * Shutdown all tasks waiting for I/O events.
+     */
+    abstract void shutdownHandlerTasks();
+
+    private void shutdownExecutors() {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                pool.executor().shutdown();
+                timeoutExecutor.shutdown();
+                return null;
+            }
+        });
+    }
+
+    @Override
+    public final void shutdown() {
+        if (shutdown.getAndSet(true)) {
+            // already shutdown
+            return;
+        }
+        // if there are channels in the group then shutdown will continue
+        // when the last channel is closed
+        if (!isEmpty()) {
+            return;
+        }
+        // initiate termination (acquire shutdownNowLock to ensure that other
+        // threads invoking shutdownNow will block).
+        synchronized (shutdownNowLock) {
+            if (!terminateInitiated) {
+                terminateInitiated = true;
+                shutdownHandlerTasks();
+                shutdownExecutors();
+            }
+        }
+    }
+
+    @Override
+    public final void shutdownNow() throws IOException {
+        shutdown.set(true);
+        synchronized (shutdownNowLock) {
+            if (!terminateInitiated) {
+                terminateInitiated = true;
+                closeAllChannels();
+                shutdownHandlerTasks();
+                shutdownExecutors();
+            }
+        }
+    }
+
+    /**
+     * For use by AsynchronousFileChannel to release resources without shutting
+     * down the thread pool.
+     */
+    final void detachFromThreadPool() {
+        if (shutdown.getAndSet(true))
+            throw new AssertionError("Already shutdown");
+        if (!isEmpty())
+            throw new AssertionError("Group not empty");
+        shutdownHandlerTasks();
+    }
+
+    @Override
+    public final boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        return pool.executor().awaitTermination(timeout, unit);
+    }
+
+    /**
+     * Executes the given command on one of the channel group's pooled threads.
+     */
+    @Override
+    public final void execute(Runnable task) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            // when a security manager is installed then the user's task
+            // must be run with the current calling context
+            final AccessControlContext acc = AccessController.getContext();
+            final Runnable delegate = task;
+            task = new Runnable() {
+                @Override
+                public void run() {
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                        @Override
+                        public Void run() {
+                            delegate.run();
+                            return null;
+                        }
+                    }, acc);
+                }
+            };
+        }
+        executeOnPooledThread(task);
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
new file mode 100755
index 0000000..d852b36
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.net.InetSocketAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.concurrent.Future;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import sun.net.NetHooks;
+
+/**
+ * Base implementation of AsynchronousServerSocketChannel.
+ */
+
+abstract class AsynchronousServerSocketChannelImpl
+    extends AsynchronousServerSocketChannel
+    implements Cancellable, Groupable
+{
+    protected final FileDescriptor fd;
+
+    // the local address to which the channel's socket is bound
+    protected volatile InetSocketAddress localAddress = null;
+
+    // need this lock to set local address
+    private final Object stateLock = new Object();
+
+    // close support
+    private ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    private volatile boolean open = true;
+
+    // set true when accept operation is cancelled
+    private volatile boolean acceptKilled;
+
+    // set true when exclusive binding is on and SO_REUSEADDR is emulated
+    private boolean isReuseAddress;
+
+    AsynchronousServerSocketChannelImpl(AsynchronousChannelGroupImpl group) {
+        super(group.provider());
+        this.fd = Net.serverSocket(true);
+    }
+
+    @Override
+    public final boolean isOpen() {
+        return open;
+    }
+
+    /**
+     * Marks beginning of access to file descriptor/handle
+     */
+    final void begin() throws IOException {
+        closeLock.readLock().lock();
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    /**
+     * Marks end of access to file descriptor/handle
+     */
+    final void end() {
+        closeLock.readLock().unlock();
+    }
+
+    /**
+     * Invoked to close file descriptor/handle.
+     */
+    abstract void implClose() throws IOException;
+
+    @Override
+    public final void close() throws IOException {
+        // synchronize with any threads using file descriptor/handle
+        closeLock.writeLock().lock();
+        try {
+            if (!open)
+                return;     // already closed
+            open = false;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+        implClose();
+    }
+
+    /**
+     * Invoked by accept to accept connection
+     */
+    abstract Future<AsynchronousSocketChannel>
+        implAccept(Object attachment,
+                   CompletionHandler<AsynchronousSocketChannel,Object> handler);
+
+
+    @Override
+    public final Future<AsynchronousSocketChannel> accept() {
+        return implAccept(null, null);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <A> void accept(A attachment,
+                                 CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);
+    }
+
+    final boolean isAcceptKilled() {
+        return acceptKilled;
+    }
+
+    @Override
+    public final void onCancel(PendingFuture<?,?> task) {
+        acceptKilled = true;
+    }
+
+    @Override
+    public final AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)
+        throws IOException
+    {
+        InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
+            Net.checkAddress(local);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkListen(isa.getPort());
+
+        try {
+            begin();
+            synchronized (stateLock) {
+                if (localAddress != null)
+                    throw new AlreadyBoundException();
+                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
+                Net.bind(fd, isa.getAddress(), isa.getPort());
+                Net.listen(fd, backlog < 1 ? 50 : backlog);
+                localAddress = Net.localAddress(fd);
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+    @Override
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return Net.getRevealedLocalAddress(localAddress);
+    }
+
+    @Override
+    public final <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name,
+                                                               T value)
+        throws IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            if (name == StandardSocketOptions.SO_REUSEADDR &&
+                    Net.useExclusiveBind())
+            {
+                // SO_REUSEADDR emulated when using exclusive bind
+                isReuseAddress = (Boolean)value;
+            } else {
+                Net.setSocketOption(fd, Net.UNSPEC, name, value);
+            }
+            return this;
+        } finally {
+            end();
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            if (name == StandardSocketOptions.SO_REUSEADDR &&
+                    Net.useExclusiveBind())
+            {
+                // SO_REUSEADDR emulated when using exclusive bind
+                return (T)Boolean.valueOf(isReuseAddress);
+            }
+            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            end();
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
+            set.add(StandardSocketOptions.SO_RCVBUF);
+            set.add(StandardSocketOptions.SO_REUSEADDR);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    @Override
+    public final Set<SocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    @Override
+    public final String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.getClass().getName());
+        sb.append('[');
+        if (!isOpen())
+            sb.append("closed");
+        else {
+            if (localAddress == null) {
+                sb.append("unbound");
+            } else {
+                sb.append(Net.getRevealedLocalAddressAsString(localAddress));
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java
new file mode 100755
index 0000000..af20709
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import sun.net.NetHooks;
+
+/**
+ * Base implementation of AsynchronousSocketChannel
+ */
+
+abstract class AsynchronousSocketChannelImpl
+    extends AsynchronousSocketChannel
+    implements Cancellable, Groupable
+{
+    protected final FileDescriptor fd;
+
+    // protects state, localAddress, and remoteAddress
+    protected final Object stateLock = new Object();
+
+    protected volatile InetSocketAddress localAddress = null;
+    protected volatile InetSocketAddress remoteAddress = null;
+
+    // State, increases monotonically
+    static final int ST_UNINITIALIZED = -1;
+    static final int ST_UNCONNECTED = 0;
+    static final int ST_PENDING = 1;
+    static final int ST_CONNECTED = 2;
+    protected volatile int state = ST_UNINITIALIZED;
+
+    // reading state
+    private final Object readLock = new Object();
+    private boolean reading;
+    private boolean readShutdown;
+    private boolean readKilled;     // further reading disallowed due to timeout
+
+    // writing state
+    private final Object writeLock = new Object();
+    private boolean writing;
+    private boolean writeShutdown;
+    private boolean writeKilled;    // further writing disallowed due to timeout
+
+    // close support
+    private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
+    private volatile boolean open = true;
+
+    // set true when exclusive binding is on and SO_REUSEADDR is emulated
+    private boolean isReuseAddress;
+
+    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group)
+        throws IOException
+    {
+        super(group.provider());
+        this.fd = Net.socket(true);
+        this.state = ST_UNCONNECTED;
+    }
+
+    // Constructor for sockets obtained from AsynchronousServerSocketChannelImpl
+    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group,
+                                  FileDescriptor fd,
+                                  InetSocketAddress remote)
+        throws IOException
+    {
+        super(group.provider());
+        this.fd = fd;
+        this.state = ST_CONNECTED;
+        this.localAddress = Net.localAddress(fd);
+        this.remoteAddress = remote;
+    }
+
+    @Override
+    public final boolean isOpen() {
+        return open;
+    }
+
+    /**
+     * Marks beginning of access to file descriptor/handle
+     */
+    final void begin() throws IOException {
+        closeLock.readLock().lock();
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    /**
+     * Marks end of access to file descriptor/handle
+     */
+    final void end() {
+        closeLock.readLock().unlock();
+    }
+
+    /**
+     * Invoked to close socket and release other resources.
+     */
+    abstract void implClose() throws IOException;
+
+    @Override
+    public final void close() throws IOException {
+        // synchronize with any threads initiating asynchronous operations
+        closeLock.writeLock().lock();
+        try {
+            if (!open)
+                return;     // already closed
+            open = false;
+        } finally {
+            closeLock.writeLock().unlock();
+        }
+        implClose();
+    }
+
+    final void enableReading(boolean killed) {
+        synchronized (readLock) {
+            reading = false;
+            if (killed)
+                readKilled = true;
+        }
+    }
+
+    final void enableReading() {
+        enableReading(false);
+    }
+
+    final void enableWriting(boolean killed) {
+        synchronized (writeLock) {
+            writing = false;
+            if (killed)
+                writeKilled = true;
+        }
+    }
+
+    final void enableWriting() {
+        enableWriting(false);
+    }
+
+    final void killReading() {
+        synchronized (readLock) {
+            readKilled = true;
+        }
+    }
+
+    final void killWriting() {
+        synchronized (writeLock) {
+            writeKilled = true;
+        }
+    }
+
+    final void killConnect() {
+        // when a connect is cancelled then the connection may have been
+        // established so prevent reading or writing.
+        killReading();
+        killWriting();
+    }
+
+    /**
+     * Invoked by connect to initiate the connect operation.
+     */
+    abstract <A> Future<Void> implConnect(SocketAddress remote,
+                                          A attachment,
+                                          CompletionHandler<Void,? super A> handler);
+
+    @Override
+    public final Future<Void> connect(SocketAddress remote) {
+        return implConnect(remote, null, null);
+    }
+
+    @Override
+    public final <A> void connect(SocketAddress remote,
+                                  A attachment,
+                                  CompletionHandler<Void,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        implConnect(remote, attachment, handler);
+    }
+
+    /**
+     * Invoked by read to initiate the I/O operation.
+     */
+    abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+                                                     ByteBuffer dst,
+                                                     ByteBuffer[] dsts,
+                                                     long timeout,
+                                                     TimeUnit unit,
+                                                     A attachment,
+                                                     CompletionHandler<V,? super A> handler);
+
+    @SuppressWarnings("unchecked")
+    private <V extends Number,A> Future<V> read(boolean isScatteringRead,
+                                                ByteBuffer dst,
+                                                ByteBuffer[] dsts,
+                                                long timeout,
+                                                TimeUnit unit,
+                                                A att,
+                                                CompletionHandler<V,? super A> handler)
+    {
+        if (!isOpen()) {
+            Throwable e = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(e);
+            Invoker.invoke(this, handler, att, null, e);
+            return null;
+        }
+
+        if (remoteAddress == null)
+            throw new NotYetConnectedException();
+
+        boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
+        boolean shutdown = false;
+
+        // check and update state
+        synchronized (readLock) {
+            if (readKilled)
+                throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
+            if (reading)
+                throw new ReadPendingException();
+            if (readShutdown) {
+                shutdown = true;
+            } else {
+                if (hasSpaceToRead) {
+                    reading = true;
+                }
+            }
+        }
+
+        // immediately complete with -1 if shutdown for read
+        // immediately complete with 0 if no space remaining
+        if (shutdown || !hasSpaceToRead) {
+            Number result;
+            if (isScatteringRead) {
+                result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
+            } else {
+                result = (shutdown) ? -1 : 0;
+            }
+            if (handler == null)
+                return CompletedFuture.withResult((V)result);
+            Invoker.invoke(this, handler, att, (V)result, null);
+            return null;
+        }
+
+        return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
+    }
+
+    @Override
+    public final Future<Integer> read(ByteBuffer dst) {
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    @Override
+    public final <A> void read(ByteBuffer dst,
+                               long timeout,
+                               TimeUnit unit,
+                               A attachment,
+                               CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        if (dst.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+        read(false, dst, null, timeout, unit, attachment, handler);
+    }
+
+    @Override
+    public final <A> void read(ByteBuffer[] dsts,
+                               int offset,
+                               int length,
+                               long timeout,
+                               TimeUnit unit,
+                               A attachment,
+                               CompletionHandler<Long,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+            throw new IndexOutOfBoundsException();
+        ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
+        for (int i=0; i<bufs.length; i++) {
+            if (bufs[i].isReadOnly())
+                throw new IllegalArgumentException("Read-only buffer");
+        }
+        read(true, null, bufs, timeout, unit, attachment, handler);
+    }
+
+    /**
+     * Invoked by write to initiate the I/O operation.
+     */
+    abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+                                                      ByteBuffer src,
+                                                      ByteBuffer[] srcs,
+                                                      long timeout,
+                                                      TimeUnit unit,
+                                                      A attachment,
+                                                      CompletionHandler<V,? super A> handler);
+
+    @SuppressWarnings("unchecked")
+    private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
+                                                 ByteBuffer src,
+                                                 ByteBuffer[] srcs,
+                                                 long timeout,
+                                                 TimeUnit unit,
+                                                 A att,
+                                                 CompletionHandler<V,? super A> handler)
+    {
+        boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
+
+        boolean closed = false;
+        if (isOpen()) {
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            // check and update state
+            synchronized (writeLock) {
+                if (writeKilled)
+                    throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
+                if (writing)
+                    throw new WritePendingException();
+                if (writeShutdown) {
+                    closed = true;
+                } else {
+                    if (hasDataToWrite)
+                        writing = true;
+                }
+            }
+        } else {
+            closed = true;
+        }
+
+        // channel is closed or shutdown for write
+        if (closed) {
+            Throwable e = new ClosedChannelException();
+            if (handler == null)
+                return CompletedFuture.withFailure(e);
+            Invoker.invoke(this, handler, att, null, e);
+            return null;
+        }
+
+        // nothing to write so complete immediately
+        if (!hasDataToWrite) {
+            Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
+            if (handler == null)
+                return CompletedFuture.withResult((V)result);
+            Invoker.invoke(this, handler, att, (V)result, null);
+            return null;
+        }
+
+        return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
+    }
+
+    @Override
+    public final Future<Integer> write(ByteBuffer src) {
+        return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    @Override
+    public final <A> void write(ByteBuffer src,
+                                long timeout,
+                                TimeUnit unit,
+                                A attachment,
+                                CompletionHandler<Integer,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        write(false, src, null, timeout, unit, attachment, handler);
+    }
+
+    @Override
+    public final <A> void  write(ByteBuffer[] srcs,
+                                 int offset,
+                                 int length,
+                                 long timeout,
+                                 TimeUnit unit,
+                                 A attachment,
+                                 CompletionHandler<Long,? super A> handler)
+    {
+        if (handler == null)
+            throw new NullPointerException("'handler' is null");
+        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+            throw new IndexOutOfBoundsException();
+        srcs = Util.subsequence(srcs, offset, length);
+        write(true, null, srcs, timeout, unit, attachment, handler);
+    }
+
+    @Override
+    public final AsynchronousSocketChannel bind(SocketAddress local)
+        throws IOException
+    {
+        try {
+            begin();
+            synchronized (stateLock) {
+                if (state == ST_PENDING)
+                    throw new ConnectionPendingException();
+                if (localAddress != null)
+                    throw new AlreadyBoundException();
+                InetSocketAddress isa = (local == null) ?
+                    new InetSocketAddress(0) : Net.checkAddress(local);
+                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
+                Net.bind(fd, isa.getAddress(), isa.getPort());
+                localAddress = Net.localAddress(fd);
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+    @Override
+    public final SocketAddress getLocalAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+         return Net.getRevealedLocalAddress(localAddress);
+    }
+
+    @Override
+    public final <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            if (writeShutdown)
+                throw new IOException("Connection has been shutdown for writing");
+            if (name == StandardSocketOptions.SO_REUSEADDR &&
+                    Net.useExclusiveBind())
+            {
+                // SO_REUSEADDR emulated when using exclusive bind
+                isReuseAddress = (Boolean)value;
+            } else {
+                Net.setSocketOption(fd, Net.UNSPEC, name, value);
+            }
+            return this;
+        } finally {
+            end();
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        try {
+            begin();
+            if (name == StandardSocketOptions.SO_REUSEADDR &&
+                    Net.useExclusiveBind())
+            {
+                // SO_REUSEADDR emulated when using exclusive bind
+                return (T)Boolean.valueOf(isReuseAddress);
+            }
+            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            end();
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(5);
+            set.add(StandardSocketOptions.SO_SNDBUF);
+            set.add(StandardSocketOptions.SO_RCVBUF);
+            set.add(StandardSocketOptions.SO_KEEPALIVE);
+            set.add(StandardSocketOptions.SO_REUSEADDR);
+            set.add(StandardSocketOptions.TCP_NODELAY);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    @Override
+    public final Set<SocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    @Override
+    public final SocketAddress getRemoteAddress() throws IOException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+        return remoteAddress;
+    }
+
+    @Override
+    public final AsynchronousSocketChannel shutdownInput() throws IOException {
+        try {
+            begin();
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            synchronized (readLock) {
+                if (!readShutdown) {
+                    Net.shutdown(fd, Net.SHUT_RD);
+                    readShutdown = true;
+                }
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+    @Override
+    public final AsynchronousSocketChannel shutdownOutput() throws IOException {
+        try {
+            begin();
+            if (remoteAddress == null)
+                throw new NotYetConnectedException();
+            synchronized (writeLock) {
+                if (!writeShutdown) {
+                    Net.shutdown(fd, Net.SHUT_WR);
+                    writeShutdown = true;
+                }
+            }
+        } finally {
+            end();
+        }
+        return this;
+    }
+
+    @Override
+    public final String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.getClass().getName());
+        sb.append('[');
+        synchronized (stateLock) {
+            if (!isOpen()) {
+                sb.append("closed");
+            } else {
+                switch (state) {
+                case ST_UNCONNECTED:
+                    sb.append("unconnected");
+                    break;
+                case ST_PENDING:
+                    sb.append("connection-pending");
+                    break;
+                case ST_CONNECTED:
+                    sb.append("connected");
+                    if (readShutdown)
+                        sb.append(" ishut");
+                    if (writeShutdown)
+                        sb.append(" oshut");
+                    break;
+                }
+                if (localAddress != null) {
+                    sb.append(" local=");
+                    sb.append(
+                            Net.getRevealedLocalAddressAsString(localAddress));
+                }
+                if (remoteAddress != null) {
+                    sb.append(" remote=");
+                    sb.append(remoteAddress.toString());
+                }
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/BsdAsynchronousChannelProvider.java b/ojluni/src/main/java/sun/nio/ch/BsdAsynchronousChannelProvider.java
new file mode 100755
index 0000000..a732c11
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/BsdAsynchronousChannelProvider.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.io.IOException;
+
+public class BsdAsynchronousChannelProvider
+    extends AsynchronousChannelProvider
+{
+    private static volatile KQueuePort defaultPort;
+
+    private KQueuePort defaultEventPort() throws IOException {
+        if (defaultPort == null) {
+            synchronized (BsdAsynchronousChannelProvider.class) {
+                if (defaultPort == null) {
+                    defaultPort = new KQueuePort(this, ThreadPool.getDefault()).start();
+                }
+            }
+        }
+        return defaultPort;
+    }
+
+    public BsdAsynchronousChannelProvider() {
+    }
+
+    @Override
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
+        throws IOException
+    {
+        return new KQueuePort(this, ThreadPool.create(nThreads, factory)).start();
+    }
+
+    @Override
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
+        throws IOException
+    {
+        return new KQueuePort(this, ThreadPool.wrap(executor, initialSize)).start();
+    }
+
+    private Port toPort(AsynchronousChannelGroup group) throws IOException {
+        if (group == null) {
+            return defaultEventPort();
+        } else {
+            if (!(group instanceof KQueuePort))
+                throw new IllegalChannelGroupException();
+            return (Port)group;
+        }
+    }
+
+    @Override
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousServerSocketChannelImpl(toPort(group));
+    }
+
+    @Override
+    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousSocketChannelImpl(toPort(group));
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/Cancellable.java b/ojluni/src/main/java/sun/nio/ch/Cancellable.java
new file mode 100755
index 0000000..9a84a63
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/Cancellable.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+/**
+ * Implemented by asynchronous channels that require notification when an I/O
+ * operation is cancelled.
+ */
+
+interface Cancellable {
+    /**
+     * Invoked to notify channel that cancel has been invoked while holding
+     * the Future's lock.
+     */
+    void onCancel(PendingFuture<?,?> task);
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index 7da4bc86..e4d24a5 100755
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -96,6 +96,9 @@
     // Our socket adaptor, if any
     private DatagramSocket socket;
 
+    // Multicast support
+    private MembershipRegistry registry;
+
     // set true when socket is bound and SO_REUSEADDRESS is emulated
     private boolean reuseAddressEmulated;
 
@@ -165,6 +168,7 @@
         }
     }
 
+    @Override
     public SocketAddress getLocalAddress() throws IOException {
         synchronized (stateLock) {
             if (!isOpen())
@@ -242,6 +246,7 @@
         }
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public <T> T getOption(SocketOption<T> name)
         throws IOException
@@ -320,6 +325,7 @@
         }
     }
 
+    @Override
     public final Set<SocketOption<?>> supportedOptions() {
         return DefaultOptionsHolder.defaultOptions;
     }
@@ -787,12 +793,228 @@
         return this;
     }
 
+    /**
+     * Joins channel's socket to the given group/interface and
+     * optional source address.
+     */
+    private MembershipKey innerJoin(InetAddress group,
+                                    NetworkInterface interf,
+                                    InetAddress source)
+        throws IOException
+    {
+        if (!group.isMulticastAddress())
+            throw new IllegalArgumentException("Group not a multicast address");
+
+        // check multicast address is compatible with this socket
+        if (group instanceof Inet4Address) {
+            if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
+                throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group");
+        } else if (group instanceof Inet6Address) {
+            if (family != StandardProtocolFamily.INET6)
+                throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group");
+        } else {
+            throw new IllegalArgumentException("Address type not supported");
+        }
+
+        // check source address
+        if (source != null) {
+            if (source.isAnyLocalAddress())
+                throw new IllegalArgumentException("Source address is a wildcard address");
+            if (source.isMulticastAddress())
+                throw new IllegalArgumentException("Source address is multicast address");
+            if (source.getClass() != group.getClass())
+                throw new IllegalArgumentException("Source address is different type to group");
+        }
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkMulticast(group);
+
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            // check the registry to see if we are already a member of the group
+            if (registry == null) {
+                registry = new MembershipRegistry();
+            } else {
+                // return existing membership key
+                MembershipKey key = registry.checkMembership(group, interf, source);
+                if (key != null)
+                    return key;
+            }
+
+            MembershipKeyImpl key;
+            if ((family == StandardProtocolFamily.INET6) &&
+                ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
+            {
+                int index = interf.getIndex();
+                if (index == -1)
+                    throw new IOException("Network interface cannot be identified");
+
+                // need multicast and source address as byte arrays
+                byte[] groupAddress = Net.inet6AsByteArray(group);
+                byte[] sourceAddress = (source == null) ? null :
+                    Net.inet6AsByteArray(source);
+
+                // join the group
+                int n = Net.join6(fd, groupAddress, index, sourceAddress);
+                if (n == IOStatus.UNAVAILABLE)
+                    throw new UnsupportedOperationException();
+
+                key = new MembershipKeyImpl.Type6(this, group, interf, source,
+                                                  groupAddress, index, sourceAddress);
+
+            } else {
+                // need IPv4 address to identify interface
+                Inet4Address target = Net.anyInet4Address(interf);
+                if (target == null)
+                    throw new IOException("Network interface not configured for IPv4");
+
+                int groupAddress = Net.inet4AsInt(group);
+                int targetAddress = Net.inet4AsInt(target);
+                int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
+
+                // join the group
+                int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
+                if (n == IOStatus.UNAVAILABLE)
+                    throw new UnsupportedOperationException();
+
+                key = new MembershipKeyImpl.Type4(this, group, interf, source,
+                                                  groupAddress, targetAddress, sourceAddress);
+            }
+
+            registry.add(key);
+            return key;
+        }
+    }
+
+    @Override
+    public MembershipKey join(InetAddress group,
+                              NetworkInterface interf)
+        throws IOException
+    {
+        return innerJoin(group, interf, null);
+    }
+
+    @Override
+    public MembershipKey join(InetAddress group,
+                              NetworkInterface interf,
+                              InetAddress source)
+        throws IOException
+    {
+        if (source == null)
+            throw new NullPointerException("source address is null");
+        return innerJoin(group, interf, source);
+    }
+
+    // package-private
+    void drop(MembershipKeyImpl key) {
+        assert key.channel() == this;
+
+        synchronized (stateLock) {
+            if (!key.isValid())
+                return;
+
+            try {
+                if (key instanceof MembershipKeyImpl.Type6) {
+                    MembershipKeyImpl.Type6 key6 =
+                        (MembershipKeyImpl.Type6)key;
+                    Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
+                } else {
+                    MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key;
+                    Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(),
+                        key4.source());
+                }
+            } catch (IOException ioe) {
+                // should not happen
+                throw new AssertionError(ioe);
+            }
+
+            key.invalidate();
+            registry.remove(key);
+        }
+    }
+
+    /**
+     * Block datagrams from given source if a memory to receive all
+     * datagrams.
+     */
+    void block(MembershipKeyImpl key, InetAddress source)
+        throws IOException
+    {
+        assert key.channel() == this;
+        assert key.sourceAddress() == null;
+
+        synchronized (stateLock) {
+            if (!key.isValid())
+                throw new IllegalStateException("key is no longer valid");
+            if (source.isAnyLocalAddress())
+                throw new IllegalArgumentException("Source address is a wildcard address");
+            if (source.isMulticastAddress())
+                throw new IllegalArgumentException("Source address is multicast address");
+            if (source.getClass() != key.group().getClass())
+                throw new IllegalArgumentException("Source address is different type to group");
+
+            int n;
+            if (key instanceof MembershipKeyImpl.Type6) {
+                 MembershipKeyImpl.Type6 key6 =
+                    (MembershipKeyImpl.Type6)key;
+                n = Net.block6(fd, key6.groupAddress(), key6.index(),
+                               Net.inet6AsByteArray(source));
+            } else {
+                MembershipKeyImpl.Type4 key4 =
+                    (MembershipKeyImpl.Type4)key;
+                n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(),
+                               Net.inet4AsInt(source));
+            }
+            if (n == IOStatus.UNAVAILABLE) {
+                // ancient kernel
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    /**
+     * Unblock given source.
+     */
+    void unblock(MembershipKeyImpl key, InetAddress source) {
+        assert key.channel() == this;
+        assert key.sourceAddress() == null;
+
+        synchronized (stateLock) {
+            if (!key.isValid())
+                throw new IllegalStateException("key is no longer valid");
+
+            try {
+                if (key instanceof MembershipKeyImpl.Type6) {
+                    MembershipKeyImpl.Type6 key6 =
+                        (MembershipKeyImpl.Type6)key;
+                    Net.unblock6(fd, key6.groupAddress(), key6.index(),
+                                 Net.inet6AsByteArray(source));
+                } else {
+                    MembershipKeyImpl.Type4 key4 =
+                        (MembershipKeyImpl.Type4)key;
+                    Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(),
+                                 Net.inet4AsInt(source));
+                }
+            } catch (IOException ioe) {
+                // should not happen
+                throw new AssertionError(ioe);
+            }
+        }
+    }
+
     protected void implCloseSelectableChannel() throws IOException {
         synchronized (stateLock) {
             if (state != ST_KILLED)
                 nd.preClose(fd);
             ResourceManager.afterUdpClose();
 
+            // if member of mulitcast group then invalidate all keys
+            if (registry != null)
+                registry.invalidateAll();
+
             long th;
             if ((th = readerThread) != 0)
                 NativeThread.signal(th);
diff --git a/ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java
new file mode 100755
index 0000000..38dd74f
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Creates this platform's default asynchronous channel provider
+ */
+
+public class DefaultAsynchronousChannelProvider {
+
+    /**
+     * Prevent instantiation.
+     */
+    private DefaultAsynchronousChannelProvider() { }
+
+    /**
+     * Returns the default AsynchronousChannelProvider.
+     */
+    public static AsynchronousChannelProvider create() {
+        String osname = AccessController
+            .doPrivileged(new GetPropertyAction("os.name"));
+        // Android-changed: We don't compile SolarisAsynchronousChannelProvider.
+        //
+        // if (osname.equals("SunOS"))
+        //     return new SolarisAsynchronousChannelProvider();
+        if (osname.equals("Linux"))
+            return new LinuxAsynchronousChannelProvider();
+        if (osname.contains("OS X"))
+            return new BsdAsynchronousChannelProvider();
+        throw new InternalError("platform not recognized");
+    }
+
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/EPollPort.java b/ojluni/src/main/java/sun/nio/ch/EPollPort.java
new file mode 100755
index 0000000..6b496ca
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/EPollPort.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import static sun.nio.ch.EPoll.*;
+
+/**
+ * AsynchronousChannelGroup implementation based on the Linux epoll facility.
+ */
+
+final class EPollPort
+    extends Port
+{
+    // maximum number of events to poll at a time
+    private static final int MAX_EPOLL_EVENTS = 512;
+
+    // errors
+    private static final int ENOENT     = 2;
+
+    // epoll file descriptor
+    private final int epfd;
+
+    // true if epoll closed
+    private boolean closed;
+
+    // socket pair used for wakeup
+    private final int sp[];
+
+    // number of wakeups pending
+    private final AtomicInteger wakeupCount = new AtomicInteger();
+
+    // address of the poll array passed to epoll_wait
+    private final long address;
+
+    // encapsulates an event for a channel
+    static class Event {
+        final PollableChannel channel;
+        final int events;
+
+        Event(PollableChannel channel, int events) {
+            this.channel = channel;
+            this.events = events;
+        }
+
+        PollableChannel channel()   { return channel; }
+        int events()                { return events; }
+    }
+
+    // queue of events for cases that a polling thread dequeues more than one
+    // event
+    private final ArrayBlockingQueue<Event> queue;
+    private final Event NEED_TO_POLL = new Event(null, 0);
+    private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
+
+    EPollPort(AsynchronousChannelProvider provider, ThreadPool pool)
+        throws IOException
+    {
+        super(provider, pool);
+
+        // open epoll
+        this.epfd = epollCreate();
+
+        // create socket pair for wakeup mechanism
+        int[] sv = new int[2];
+        try {
+            socketpair(sv);
+            // register one end with epoll
+            epollCtl(epfd, EPOLL_CTL_ADD, sv[0], POLLIN);
+        } catch (IOException x) {
+            close0(epfd);
+            throw x;
+        }
+        this.sp = sv;
+
+        // allocate the poll array
+        this.address = allocatePollArray(MAX_EPOLL_EVENTS);
+
+        // create the queue and offer the special event to ensure that the first
+        // threads polls
+        this.queue = new ArrayBlockingQueue<Event>(MAX_EPOLL_EVENTS);
+        this.queue.offer(NEED_TO_POLL);
+    }
+
+    EPollPort start() {
+        startThreads(new EventHandlerTask());
+        return this;
+    }
+
+    /**
+     * Release all resources
+     */
+    private void implClose() {
+        synchronized (this) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        freePollArray(address);
+        close0(sp[0]);
+        close0(sp[1]);
+        close0(epfd);
+    }
+
+    private void wakeup() {
+        if (wakeupCount.incrementAndGet() == 1) {
+            // write byte to socketpair to force wakeup
+            try {
+                interrupt(sp[1]);
+            } catch (IOException x) {
+                throw new AssertionError(x);
+            }
+        }
+    }
+
+    @Override
+    void executeOnHandlerTask(Runnable task) {
+        synchronized (this) {
+            if (closed)
+                throw new RejectedExecutionException();
+            offerTask(task);
+            wakeup();
+        }
+    }
+
+    @Override
+    void shutdownHandlerTasks() {
+        /*
+         * If no tasks are running then just release resources; otherwise
+         * write to the one end of the socketpair to wakeup any polling threads.
+         */
+        int nThreads = threadCount();
+        if (nThreads == 0) {
+            implClose();
+        } else {
+            // send interrupt to each thread
+            while (nThreads-- > 0) {
+                wakeup();
+            }
+        }
+    }
+
+    // invoke by clients to register a file descriptor
+    @Override
+    void startPoll(int fd, int events) {
+        // update events (or add to epoll on first usage)
+        int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
+        if (err == ENOENT)
+            err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
+        if (err != 0)
+            throw new AssertionError();     // should not happen
+    }
+
+    /*
+     * Task to process events from epoll and dispatch to the channel's
+     * onEvent handler.
+     *
+     * Events are retreived from epoll in batch and offered to a BlockingQueue
+     * where they are consumed by handler threads. A special "NEED_TO_POLL"
+     * event is used to signal one consumer to re-poll when all events have
+     * been consumed.
+     */
+    private class EventHandlerTask implements Runnable {
+        private Event poll() throws IOException {
+            try {
+                for (;;) {
+                    int n = epollWait(epfd, address, MAX_EPOLL_EVENTS);
+                    /*
+                     * 'n' events have been read. Here we map them to their
+                     * corresponding channel in batch and queue n-1 so that
+                     * they can be handled by other handler threads. The last
+                     * event is handled by this thread (and so is not queued).
+                     */
+                    fdToChannelLock.readLock().lock();
+                    try {
+                        while (n-- > 0) {
+                            long eventAddress = getEvent(address, n);
+                            int fd = getDescriptor(eventAddress);
+
+                            // wakeup
+                            if (fd == sp[0]) {
+                                if (wakeupCount.decrementAndGet() == 0) {
+                                    // no more wakeups so drain pipe
+                                    drain1(sp[0]);
+                                }
+
+                                // queue special event if there are more events
+                                // to handle.
+                                if (n > 0) {
+                                    queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
+                                    continue;
+                                }
+                                return EXECUTE_TASK_OR_SHUTDOWN;
+                            }
+
+                            PollableChannel channel = fdToChannel.get(fd);
+                            if (channel != null) {
+                                int events = getEvents(eventAddress);
+                                Event ev = new Event(channel, events);
+
+                                // n-1 events are queued; This thread handles
+                                // the last one except for the wakeup
+                                if (n > 0) {
+                                    queue.offer(ev);
+                                } else {
+                                    return ev;
+                                }
+                            }
+                        }
+                    } finally {
+                        fdToChannelLock.readLock().unlock();
+                    }
+                }
+            } finally {
+                // to ensure that some thread will poll when all events have
+                // been consumed
+                queue.offer(NEED_TO_POLL);
+            }
+        }
+
+        public void run() {
+            Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+                Invoker.getGroupAndInvokeCount();
+            final boolean isPooledThread = (myGroupAndInvokeCount != null);
+            boolean replaceMe = false;
+            Event ev;
+            try {
+                for (;;) {
+                    // reset invoke count
+                    if (isPooledThread)
+                        myGroupAndInvokeCount.resetInvokeCount();
+
+                    try {
+                        replaceMe = false;
+                        ev = queue.take();
+
+                        // no events and this thread has been "selected" to
+                        // poll for more.
+                        if (ev == NEED_TO_POLL) {
+                            try {
+                                ev = poll();
+                            } catch (IOException x) {
+                                x.printStackTrace();
+                                return;
+                            }
+                        }
+                    } catch (InterruptedException x) {
+                        continue;
+                    }
+
+                    // handle wakeup to execute task or shutdown
+                    if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
+                        Runnable task = pollTask();
+                        if (task == null) {
+                            // shutdown request
+                            return;
+                        }
+                        // run task (may throw error/exception)
+                        replaceMe = true;
+                        task.run();
+                        continue;
+                    }
+
+                    // process event
+                    try {
+                        ev.channel().onEvent(ev.events(), isPooledThread);
+                    } catch (Error x) {
+                        replaceMe = true; throw x;
+                    } catch (RuntimeException x) {
+                        replaceMe = true; throw x;
+                    }
+                }
+            } finally {
+                // last handler to exit when shutdown releases resources
+                int remaining = threadExit(this, replaceMe);
+                if (remaining == 0 && isShutdown()) {
+                    implClose();
+                }
+            }
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void socketpair(int[] sv) throws IOException;
+
+    private static native void interrupt(int fd) throws IOException;
+
+    private static native void drain1(int fd) throws IOException;
+
+    private static native void close0(int fd);
+
+    static {
+        Util.load();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/EPollSelectorImpl.java b/ojluni/src/main/java/sun/nio/ch/EPollSelectorImpl.java
index aac539b..113f84b 100755
--- a/ojluni/src/main/java/sun/nio/ch/EPollSelectorImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/EPollSelectorImpl.java
@@ -159,7 +159,7 @@
         if (closed)
             throw new ClosedSelectorException();
         SelChImpl ch = ski.channel;
-        int fd = Integer.valueOf(ch.getFDVal());
+        Integer fd = Integer.valueOf(ch.getFDVal());
         fdToKey.put(fd, ski);
         pollWrapper.add(fd);
         keys.add(ski);
diff --git a/ojluni/src/main/java/sun/nio/ch/Groupable.java b/ojluni/src/main/java/sun/nio/ch/Groupable.java
new file mode 100755
index 0000000..64d8958
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/Groupable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+/**
+ * Implemented by asynchronous channels that can be associated with an
+ * asynchronous channel group.
+ */
+
+interface Groupable {
+    AsynchronousChannelGroupImpl group();
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/Invoker.java b/ojluni/src/main/java/sun/nio/ch/Invoker.java
new file mode 100755
index 0000000..e55db54
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/Invoker.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.security.AccessController;
+import sun.security.action.GetIntegerAction;
+
+/**
+ * Defines static methods to invoke a completion handler or arbitrary task.
+ */
+
+class Invoker {
+    private Invoker() { }
+
+    // maximum number of completion handlers that may be invoked on the current
+    // thread before it re-directs invocations to the thread pool. This helps
+    // avoid stack overflow and lessens the risk of starvation.
+    private static final int maxHandlerInvokeCount = AccessController.doPrivileged(
+        new GetIntegerAction("sun.nio.ch.maxCompletionHandlersOnStack", 16));
+
+    // Per-thread object with reference to channel group and a counter for
+    // the number of completion handlers invoked. This should be reset to 0
+    // when all completion handlers have completed.
+    static class GroupAndInvokeCount {
+        private final AsynchronousChannelGroupImpl group;
+        private int handlerInvokeCount;
+        GroupAndInvokeCount(AsynchronousChannelGroupImpl group) {
+            this.group = group;
+        }
+        AsynchronousChannelGroupImpl group() {
+            return group;
+        }
+        int invokeCount() {
+            return handlerInvokeCount;
+        }
+        void setInvokeCount(int value) {
+            handlerInvokeCount = value;
+        }
+        void resetInvokeCount() {
+            handlerInvokeCount = 0;
+        }
+        void incrementInvokeCount() {
+            handlerInvokeCount++;
+        }
+    }
+    private static final ThreadLocal<GroupAndInvokeCount> myGroupAndInvokeCount =
+        new ThreadLocal<GroupAndInvokeCount>() {
+            @Override protected GroupAndInvokeCount initialValue() {
+                return null;
+            }
+        };
+
+    /**
+     * Binds this thread to the given group
+     */
+    static void bindToGroup(AsynchronousChannelGroupImpl group) {
+        myGroupAndInvokeCount.set(new GroupAndInvokeCount(group));
+    }
+
+    /**
+     * Returns the GroupAndInvokeCount object for this thread.
+     */
+    static GroupAndInvokeCount getGroupAndInvokeCount() {
+        return myGroupAndInvokeCount.get();
+    }
+
+    /**
+     * Returns true if the current thread is in a channel group's thread pool
+     */
+    static boolean isBoundToAnyGroup() {
+        return myGroupAndInvokeCount.get() != null;
+    }
+
+    /**
+     * Returns true if the current thread is in the given channel's thread
+     * pool and we haven't exceeded the maximum number of handler frames on
+     * the stack.
+     */
+    static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
+                                   AsynchronousChannelGroupImpl group)
+    {
+        if ((myGroupAndInvokeCount != null) &&
+            (myGroupAndInvokeCount.group() == group) &&
+            (myGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Invoke handler without checking the thread identity or number of handlers
+     * on the thread stack.
+     */
+    static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
+                                      A attachment,
+                                      V value,
+                                      Throwable exc)
+    {
+        if (exc == null) {
+            handler.completed(value, attachment);
+        } else {
+            handler.failed(exc, attachment);
+        }
+
+        // clear interrupt
+        Thread.interrupted();
+    }
+
+    /**
+     * Invoke handler assuming thread identity already checked
+     */
+    static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
+                                   CompletionHandler<V,? super A> handler,
+                                   A attachment,
+                                   V result,
+                                   Throwable exc)
+    {
+        myGroupAndInvokeCount.incrementInvokeCount();
+        Invoker.invokeUnchecked(handler, attachment, result, exc);
+    }
+
+    /**
+     * Invokes the handler. If the current thread is in the channel group's
+     * thread pool then the handler is invoked directly, otherwise it is
+     * invoked indirectly.
+     */
+    static <V,A> void invoke(AsynchronousChannel channel,
+                             CompletionHandler<V,? super A> handler,
+                             A attachment,
+                             V result,
+                             Throwable exc)
+    {
+        boolean invokeDirect = false;
+        boolean identityOkay = false;
+        GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+        if (thisGroupAndInvokeCount != null) {
+            if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
+                identityOkay = true;
+            if (identityOkay &&
+                (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
+            {
+                // group match
+                invokeDirect = true;
+            }
+        }
+        if (invokeDirect) {
+            invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
+        } else {
+            try {
+                invokeIndirectly(channel, handler, attachment, result, exc);
+            } catch (RejectedExecutionException ree) {
+                // channel group shutdown; fallback to invoking directly
+                // if the current thread has the right identity.
+                if (identityOkay) {
+                    invokeDirect(thisGroupAndInvokeCount,
+                                 handler, attachment, result, exc);
+                } else {
+                    throw new ShutdownChannelGroupException();
+                }
+            }
+        }
+    }
+
+    /**
+     * Invokes the handler indirectly via the channel group's thread pool.
+     */
+    static <V,A> void invokeIndirectly(AsynchronousChannel channel,
+                                       final CompletionHandler<V,? super A> handler,
+                                       final A attachment,
+                                       final V result,
+                                       final Throwable exc)
+    {
+        try {
+            ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
+                public void run() {
+                    GroupAndInvokeCount thisGroupAndInvokeCount =
+                        myGroupAndInvokeCount.get();
+                    if (thisGroupAndInvokeCount != null)
+                        thisGroupAndInvokeCount.setInvokeCount(1);
+                    invokeUnchecked(handler, attachment, result, exc);
+                }
+            });
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+    }
+
+    /**
+     * Invokes the handler "indirectly" in the given Executor
+     */
+    static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
+                                       final A attachment,
+                                       final V value,
+                                       final Throwable exc,
+                                       Executor executor)
+    {
+         try {
+            executor.execute(new Runnable() {
+                public void run() {
+                    invokeUnchecked(handler, attachment, value, exc);
+                }
+            });
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+    }
+
+    /**
+     * Invokes the given task on the thread pool associated with the given
+     * channel. If the current thread is in the thread pool then the task is
+     * invoked directly.
+     */
+    static void invokeOnThreadInThreadPool(Groupable channel,
+                                           Runnable task)
+    {
+        boolean invokeDirect;
+        GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+        AsynchronousChannelGroupImpl targetGroup = channel.group();
+        if (thisGroupAndInvokeCount == null) {
+            invokeDirect = false;
+        } else {
+            invokeDirect = (thisGroupAndInvokeCount.group == targetGroup);
+        }
+        try {
+            if (invokeDirect) {
+                task.run();
+            } else {
+                targetGroup.executeOnPooledThread(task);
+            }
+        } catch (RejectedExecutionException ree) {
+            throw new ShutdownChannelGroupException();
+        }
+    }
+
+    /**
+     * Invoke handler with completed result. This method does not check the
+     * thread identity or the number of handlers on the thread stack.
+     */
+    static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invokeUnchecked(handler,
+                            future.attachment(),
+                            future.value(),
+                            future.exception());
+        }
+    }
+
+    /**
+     * Invoke handler with completed result. If the current thread is in the
+     * channel group's thread pool then the handler is invoked directly,
+     * otherwise it is invoked indirectly.
+     */
+    static <V,A> void invoke(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invoke(future.channel(),
+                   handler,
+                   future.attachment(),
+                   future.value(),
+                   future.exception());
+        }
+    }
+
+    /**
+     * Invoke handler with completed result. The handler is invoked indirectly,
+     * via the channel group's thread pool.
+     */
+    static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
+        assert future.isDone();
+        CompletionHandler<V,? super A> handler = future.handler();
+        if (handler != null) {
+            invokeIndirectly(future.channel(),
+                             handler,
+                             future.attachment(),
+                             future.value(),
+                             future.exception());
+        }
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/KQueue.java b/ojluni/src/main/java/sun/nio/ch/KQueue.java
new file mode 100755
index 0000000..e3466e3
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/KQueue.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+/**
+ * Provides access to the BSD kqueue facility.
+ */
+
+class KQueue {
+    private KQueue() { }
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /**
+     * struct kevent {
+     *        uintptr_t       ident;          // identifier for this event, usually the fd
+     *        int16_t         filter;         // filter for event
+     *        uint16_t        flags;          // general flags
+     *        uint32_t        fflags;         // filter-specific flags
+     *        intptr_t        data;           // filter-specific data
+     *        void            *udata;         // opaque user data identifier
+     * };
+     */
+    private static final int SIZEOF_KQUEUEEVENT    = keventSize();
+    private static final int OFFSET_IDENT          = identOffset();
+    private static final int OFFSET_FILTER         = filterOffset();
+    private static final int OFFSET_FLAGS          = flagsOffset();
+
+    // filters
+    static final int EVFILT_READ  = -1;
+    static final int EVFILT_WRITE = -2;
+
+    // flags
+    static final int EV_ADD     = 0x0001;
+    static final int EV_ONESHOT = 0x0010;
+    static final int EV_CLEAR   = 0x0020;
+
+    /**
+     * Allocates a poll array to handle up to {@code count} events.
+     */
+    static long allocatePollArray(int count) {
+        return unsafe.allocateMemory(count * SIZEOF_KQUEUEEVENT);
+    }
+
+    /**
+     * Free a poll array
+     */
+    static void freePollArray(long address) {
+        unsafe.freeMemory(address);
+    }
+
+    /**
+     * Returns kevent[i].
+     */
+    static long getEvent(long address, int i) {
+        return address + (SIZEOF_KQUEUEEVENT*i);
+    }
+
+    /**
+     * Returns the file descriptor from a kevent (assuming to be in ident field)
+     */
+    static int getDescriptor(long address) {
+        return unsafe.getInt(address + OFFSET_IDENT);
+    }
+
+    static int getFilter(long address) {
+        return unsafe.getShort(address + OFFSET_FILTER);
+    }
+
+    static int getFlags(long address) {
+        return unsafe.getShort(address + OFFSET_FLAGS);
+    }
+
+    // -- Native methods --
+
+    private static native int keventSize();
+
+    private static native int identOffset();
+
+    private static native int filterOffset();
+
+    private static native int flagsOffset();
+
+    static native int kqueue() throws IOException;
+
+    static native int keventRegister(int kqpfd, int fd, int filter, int flags);
+
+    static native int keventPoll(int kqpfd, long pollAddress, int nevents)
+        throws IOException;
+
+    static {
+        Util.load();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/KQueuePort.java b/ojluni/src/main/java/sun/nio/ch/KQueuePort.java
new file mode 100755
index 0000000..cd16e2e
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/KQueuePort.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.io.IOException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import static sun.nio.ch.KQueue.*;
+
+/**
+ * AsynchronousChannelGroup implementation based on the BSD kqueue facility.
+ */
+
+final class KQueuePort
+    extends Port
+{
+    // maximum number of events to poll at a time
+    private static final int MAX_KEVENTS_TO_POLL = 512;
+
+    // kqueue file descriptor
+    private final int kqfd;
+
+    // true if kqueue closed
+    private boolean closed;
+
+    // socket pair used for wakeup
+    private final int sp[];
+
+    // number of wakeups pending
+    private final AtomicInteger wakeupCount = new AtomicInteger();
+
+    // address of the poll array passed to kqueue_wait
+    private final long address;
+
+    // encapsulates an event for a channel
+    static class Event {
+        final PollableChannel channel;
+        final int events;
+
+        Event(PollableChannel channel, int events) {
+            this.channel = channel;
+            this.events = events;
+        }
+
+        PollableChannel channel()   { return channel; }
+        int events()                { return events; }
+    }
+
+    // queue of events for cases that a polling thread dequeues more than one
+    // event
+    private final ArrayBlockingQueue<Event> queue;
+    private final Event NEED_TO_POLL = new Event(null, 0);
+    private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
+
+    KQueuePort(AsynchronousChannelProvider provider, ThreadPool pool)
+        throws IOException
+    {
+        super(provider, pool);
+
+        // open kqueue
+        this.kqfd = kqueue();
+
+        // create socket pair for wakeup mechanism
+        int[] sv = new int[2];
+        try {
+            socketpair(sv);
+
+            // register one end with kqueue
+            keventRegister(kqfd, sv[0], EVFILT_READ, EV_ADD);
+        } catch (IOException x) {
+            close0(kqfd);
+            throw x;
+        }
+        this.sp = sv;
+
+        // allocate the poll array
+        this.address = allocatePollArray(MAX_KEVENTS_TO_POLL);
+
+        // create the queue and offer the special event to ensure that the first
+        // threads polls
+        this.queue = new ArrayBlockingQueue<Event>(MAX_KEVENTS_TO_POLL);
+        this.queue.offer(NEED_TO_POLL);
+    }
+
+    KQueuePort start() {
+        startThreads(new EventHandlerTask());
+        return this;
+    }
+
+    /**
+     * Release all resources
+     */
+    private void implClose() {
+        synchronized (this) {
+            if (closed)
+                return;
+            closed = true;
+        }
+        freePollArray(address);
+        close0(sp[0]);
+        close0(sp[1]);
+        close0(kqfd);
+    }
+
+    private void wakeup() {
+        if (wakeupCount.incrementAndGet() == 1) {
+            // write byte to socketpair to force wakeup
+            try {
+                interrupt(sp[1]);
+            } catch (IOException x) {
+                throw new AssertionError(x);
+            }
+        }
+    }
+
+    @Override
+    void executeOnHandlerTask(Runnable task) {
+        synchronized (this) {
+            if (closed)
+                throw new RejectedExecutionException();
+            offerTask(task);
+            wakeup();
+        }
+    }
+
+    @Override
+    void shutdownHandlerTasks() {
+        /*
+         * If no tasks are running then just release resources; otherwise
+         * write to the one end of the socketpair to wakeup any polling threads.
+         */
+        int nThreads = threadCount();
+        if (nThreads == 0) {
+            implClose();
+        } else {
+            // send interrupt to each thread
+            while (nThreads-- > 0) {
+                wakeup();
+            }
+        }
+    }
+
+    // invoked by clients to register a file descriptor
+    @Override
+    void startPoll(int fd, int events) {
+        // We use a separate filter for read and write events.
+        // TBD: Measure cost of EV_ONESHOT vs. EV_CLEAR, either will do here.
+        int err = 0;
+        int flags = (EV_ADD|EV_ONESHOT);
+        if ((events & Port.POLLIN) > 0)
+            err = keventRegister(kqfd, fd, EVFILT_READ, flags);
+        if (err == 0 && (events & Port.POLLOUT) > 0)
+            err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
+        if (err != 0)
+            throw new InternalError("kevent failed: " + err);  // should not happen
+    }
+
+    /*
+     * Task to process events from kqueue and dispatch to the channel's
+     * onEvent handler.
+     *
+     * Events are retreived from kqueue in batch and offered to a BlockingQueue
+     * where they are consumed by handler threads. A special "NEED_TO_POLL"
+     * event is used to signal one consumer to re-poll when all events have
+     * been consumed.
+     */
+    private class EventHandlerTask implements Runnable {
+        private Event poll() throws IOException {
+            try {
+                for (;;) {
+                    int n = keventPoll(kqfd, address, MAX_KEVENTS_TO_POLL);
+                    /*
+                     * 'n' events have been read. Here we map them to their
+                     * corresponding channel in batch and queue n-1 so that
+                     * they can be handled by other handler threads. The last
+                     * event is handled by this thread (and so is not queued).
+                     */
+                    fdToChannelLock.readLock().lock();
+                    try {
+                        while (n-- > 0) {
+                            long keventAddress = getEvent(address, n);
+                            int fd = getDescriptor(keventAddress);
+
+                            // wakeup
+                            if (fd == sp[0]) {
+                                if (wakeupCount.decrementAndGet() == 0) {
+                                    // no more wakeups so drain pipe
+                                    drain1(sp[0]);
+                                }
+
+                                // queue special event if there are more events
+                                // to handle.
+                                if (n > 0) {
+                                    queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
+                                    continue;
+                                }
+                                return EXECUTE_TASK_OR_SHUTDOWN;
+                            }
+
+                            PollableChannel channel = fdToChannel.get(fd);
+                            if (channel != null) {
+                                int filter = getFilter(keventAddress);
+                                int events = 0;
+                                if (filter == EVFILT_READ)
+                                    events = Port.POLLIN;
+                                else if (filter == EVFILT_WRITE)
+                                    events = Port.POLLOUT;
+
+                                Event ev = new Event(channel, events);
+
+                                // n-1 events are queued; This thread handles
+                                // the last one except for the wakeup
+                                if (n > 0) {
+                                    queue.offer(ev);
+                                } else {
+                                    return ev;
+                                }
+                            }
+                        }
+                    } finally {
+                        fdToChannelLock.readLock().unlock();
+                    }
+                }
+            } finally {
+                // to ensure that some thread will poll when all events have
+                // been consumed
+                queue.offer(NEED_TO_POLL);
+            }
+        }
+
+        public void run() {
+            Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+                Invoker.getGroupAndInvokeCount();
+            final boolean isPooledThread = (myGroupAndInvokeCount != null);
+            boolean replaceMe = false;
+            Event ev;
+            try {
+                for (;;) {
+                    // reset invoke count
+                    if (isPooledThread)
+                        myGroupAndInvokeCount.resetInvokeCount();
+
+                    try {
+                        replaceMe = false;
+                        ev = queue.take();
+
+                        // no events and this thread has been "selected" to
+                        // poll for more.
+                        if (ev == NEED_TO_POLL) {
+                            try {
+                                ev = poll();
+                            } catch (IOException x) {
+                                x.printStackTrace();
+                                return;
+                            }
+                        }
+                    } catch (InterruptedException x) {
+                        continue;
+                    }
+
+                    // handle wakeup to execute task or shutdown
+                    if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
+                        Runnable task = pollTask();
+                        if (task == null) {
+                            // shutdown request
+                            return;
+                        }
+                        // run task (may throw error/exception)
+                        replaceMe = true;
+                        task.run();
+                        continue;
+                    }
+
+                    // process event
+                    try {
+                        ev.channel().onEvent(ev.events(), isPooledThread);
+                    } catch (Error x) {
+                        replaceMe = true; throw x;
+                    } catch (RuntimeException x) {
+                        replaceMe = true; throw x;
+                    }
+                }
+            } finally {
+                // last handler to exit when shutdown releases resources
+                int remaining = threadExit(this, replaceMe);
+                if (remaining == 0 && isShutdown()) {
+                    implClose();
+                }
+            }
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void socketpair(int[] sv) throws IOException;
+
+    private static native void interrupt(int fd) throws IOException;
+
+    private static native void drain1(int fd) throws IOException;
+
+    private static native void close0(int fd);
+
+    static {
+        Util.load();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/LinuxAsynchronousChannelProvider.java b/ojluni/src/main/java/sun/nio/ch/LinuxAsynchronousChannelProvider.java
new file mode 100755
index 0000000..2fbe896
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/LinuxAsynchronousChannelProvider.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.io.IOException;
+
+public class LinuxAsynchronousChannelProvider
+    extends AsynchronousChannelProvider
+{
+    private static volatile EPollPort defaultPort;
+
+    private EPollPort defaultEventPort() throws IOException {
+        if (defaultPort == null) {
+            synchronized (LinuxAsynchronousChannelProvider.class) {
+                if (defaultPort == null) {
+                    defaultPort = new EPollPort(this, ThreadPool.getDefault()).start();
+                }
+            }
+        }
+        return defaultPort;
+    }
+
+    public LinuxAsynchronousChannelProvider() {
+    }
+
+    @Override
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
+        throws IOException
+    {
+        return new EPollPort(this, ThreadPool.create(nThreads, factory)).start();
+    }
+
+    @Override
+    public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
+        throws IOException
+    {
+        return new EPollPort(this, ThreadPool.wrap(executor, initialSize)).start();
+    }
+
+    private Port toPort(AsynchronousChannelGroup group) throws IOException {
+        if (group == null) {
+            return defaultEventPort();
+        } else {
+            if (!(group instanceof EPollPort))
+                throw new IllegalChannelGroupException();
+            return (Port)group;
+        }
+    }
+
+    @Override
+    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousServerSocketChannelImpl(toPort(group));
+    }
+
+    @Override
+    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        return new UnixAsynchronousSocketChannelImpl(toPort(group));
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java b/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java
new file mode 100755
index 0000000..5ecc396
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.io.IOException;
+import java.util.HashSet;
+
+/**
+ * MembershipKey implementation.
+ */
+
+class MembershipKeyImpl
+    extends MembershipKey
+{
+    private final MulticastChannel ch;
+    private final InetAddress group;
+    private final NetworkInterface interf;
+    private final InetAddress source;
+
+    // true when key is valid
+    private volatile boolean valid = true;
+
+    // lock used when creating or accessing blockedSet
+    private Object stateLock = new Object();
+
+    // set of source addresses that are blocked
+    private HashSet<InetAddress> blockedSet;
+
+    private MembershipKeyImpl(MulticastChannel ch,
+                              InetAddress group,
+                              NetworkInterface interf,
+                              InetAddress source)
+    {
+        this.ch = ch;
+        this.group = group;
+        this.interf = interf;
+        this.source = source;
+    }
+
+    /**
+     * MembershipKey will additional context for IPv4 membership
+     */
+    static class Type4 extends MembershipKeyImpl {
+        private final int groupAddress;
+        private final int interfAddress;
+        private final int sourceAddress;
+
+        Type4(MulticastChannel ch,
+              InetAddress group,
+              NetworkInterface interf,
+              InetAddress source,
+              int groupAddress,
+              int interfAddress,
+              int sourceAddress)
+        {
+            super(ch, group, interf, source);
+            this.groupAddress = groupAddress;
+            this.interfAddress = interfAddress;
+            this.sourceAddress = sourceAddress;
+        }
+
+        int groupAddress() {
+            return groupAddress;
+        }
+
+        int interfaceAddress() {
+            return interfAddress;
+        }
+
+        int source() {
+            return sourceAddress;
+        }
+    }
+
+    /**
+     * MembershipKey will additional context for IPv6 membership
+     */
+    static class Type6 extends MembershipKeyImpl {
+        private final byte[] groupAddress;
+        private final int index;
+        private final byte[] sourceAddress;
+
+        Type6(MulticastChannel ch,
+              InetAddress group,
+              NetworkInterface interf,
+              InetAddress source,
+              byte[] groupAddress,
+              int index,
+              byte[] sourceAddress)
+        {
+            super(ch, group, interf, source);
+            this.groupAddress = groupAddress;
+            this.index = index;
+            this.sourceAddress = sourceAddress;
+        }
+
+        byte[] groupAddress() {
+            return groupAddress;
+        }
+
+        int index() {
+            return index;
+        }
+
+        byte[] source() {
+            return sourceAddress;
+        }
+    }
+
+    public boolean isValid() {
+        return valid;
+    }
+
+    // package-private
+    void invalidate() {
+        valid = false;
+    }
+
+    public void drop() {
+        // delegate to channel
+        ((DatagramChannelImpl)ch).drop(this);
+    }
+
+    @Override
+    public MulticastChannel channel() {
+        return ch;
+    }
+
+    @Override
+    public InetAddress group() {
+        return group;
+    }
+
+    @Override
+    public NetworkInterface networkInterface() {
+        return interf;
+    }
+
+    @Override
+    public InetAddress sourceAddress() {
+        return source;
+    }
+
+    @Override
+    public MembershipKey block(InetAddress toBlock)
+        throws IOException
+    {
+        if (source != null)
+            throw new IllegalStateException("key is source-specific");
+
+        synchronized (stateLock) {
+            if ((blockedSet != null) && blockedSet.contains(toBlock)) {
+                // already blocked, nothing to do
+                return this;
+            }
+
+            ((DatagramChannelImpl)ch).block(this, toBlock);
+
+            // created blocked set if required and add source address
+            if (blockedSet == null)
+                blockedSet = new HashSet<InetAddress>();
+            blockedSet.add(toBlock);
+        }
+        return this;
+    }
+
+    @Override
+    public MembershipKey unblock(InetAddress toUnblock) {
+        synchronized (stateLock) {
+            if ((blockedSet == null) || !blockedSet.contains(toUnblock))
+                throw new IllegalStateException("not blocked");
+
+            ((DatagramChannelImpl)ch).unblock(this, toUnblock);
+
+            blockedSet.remove(toUnblock);
+        }
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(64);
+        sb.append('<');
+        sb.append(group.getHostAddress());
+        sb.append(',');
+        sb.append(interf.getName());
+        if (source != null) {
+            sb.append(',');
+            sb.append(source.getHostAddress());
+        }
+        sb.append('>');
+        return sb.toString();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java b/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java
new file mode 100755
index 0000000..6607fc8
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.*;
+
+/**
+ * Simple registry of membership keys for a MulticastChannel.
+ *
+ * Instances of this object are not safe by multiple concurrent threads.
+ */
+
+class MembershipRegistry {
+
+    // map multicast group to keys
+    private Map<InetAddress,List<MembershipKeyImpl>> groups = null;
+
+    MembershipRegistry() {
+    }
+
+    /**
+     * Checks registry for membership of the group on the given
+     * network interface.
+     */
+    MembershipKey checkMembership(InetAddress group, NetworkInterface interf,
+                                  InetAddress source)
+    {
+        if (groups != null) {
+            List<MembershipKeyImpl> keys = groups.get(group);
+            if (keys != null) {
+                for (MembershipKeyImpl key: keys) {
+                    if (key.networkInterface().equals(interf)) {
+                        // already a member to receive all packets so return
+                        // existing key or detect conflict
+                        if (source == null) {
+                            if (key.sourceAddress() == null)
+                                return key;
+                            throw new IllegalStateException("Already a member to receive all packets");
+                        }
+
+                        // already have source-specific membership so return key
+                        // or detect conflict
+                        if (key.sourceAddress() == null)
+                            throw new IllegalStateException("Already have source-specific membership");
+                        if (source.equals(key.sourceAddress()))
+                            return key;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Add membership to the registry, returning a new membership key.
+     */
+    void add(MembershipKeyImpl key) {
+        InetAddress group = key.group();
+        List<MembershipKeyImpl> keys;
+        if (groups == null) {
+            groups = new HashMap<InetAddress,List<MembershipKeyImpl>>();
+            keys = null;
+        } else {
+            keys = groups.get(group);
+        }
+        if (keys == null) {
+            keys = new LinkedList<MembershipKeyImpl>();
+            groups.put(group, keys);
+        }
+        keys.add(key);
+    }
+
+    /**
+     * Remove a key from the registry
+     */
+    void remove(MembershipKeyImpl key) {
+        InetAddress group = key.group();
+        List<MembershipKeyImpl> keys = groups.get(group);
+        if (keys != null) {
+            Iterator<MembershipKeyImpl> i = keys.iterator();
+            while (i.hasNext()) {
+                if (i.next() == key) {
+                    i.remove();
+                    break;
+                }
+            }
+            if (keys.isEmpty()) {
+                groups.remove(group);
+            }
+        }
+    }
+
+    /**
+     * Invalidate all keys in the registry
+     */
+    void invalidateAll() {
+        if (groups != null) {
+            for (InetAddress group: groups.keySet()) {
+                for (MembershipKeyImpl key: groups.get(group)) {
+                    key.invalidate();
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/PendingFuture.java b/ojluni/src/main/java/sun/nio/ch/PendingFuture.java
new file mode 100755
index 0000000..863b0f0
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/PendingFuture.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+
+/**
+ * A Future for a pending I/O operation. A PendingFuture allows for the
+ * attachment of an additional arbitrary context object and a timer task.
+ */
+
+final class PendingFuture<V,A> implements Future<V> {
+    private static final CancellationException CANCELLED =
+        new CancellationException();
+
+    private final AsynchronousChannel channel;
+    private final CompletionHandler<V,? super A> handler;
+    private final A attachment;
+
+    // true if result (or exception) is available
+    private volatile boolean haveResult;
+    private volatile V result;
+    private volatile Throwable exc;
+
+    // latch for waiting (created lazily if needed)
+    private CountDownLatch latch;
+
+    // optional timer task that is cancelled when result becomes available
+    private Future<?> timeoutTask;
+
+    // optional context object
+    private volatile Object context;
+
+    PendingFuture(AsynchronousChannel channel,
+                  CompletionHandler<V,? super A> handler,
+                  A attachment,
+                  Object context)
+    {
+        this.channel = channel;
+        this.handler = handler;
+        this.attachment = attachment;
+        this.context = context;
+    }
+
+    PendingFuture(AsynchronousChannel channel,
+                  CompletionHandler<V,? super A> handler,
+                  A attachment)
+    {
+        this.channel = channel;
+        this.handler = handler;
+        this.attachment = attachment;
+    }
+
+    PendingFuture(AsynchronousChannel channel) {
+        this(channel, null, null);
+    }
+
+    PendingFuture(AsynchronousChannel channel, Object context) {
+        this(channel, null, null, context);
+    }
+
+    AsynchronousChannel channel() {
+        return channel;
+    }
+
+    CompletionHandler<V,? super A> handler() {
+        return handler;
+    }
+
+    A attachment() {
+        return attachment;
+    }
+
+    void setContext(Object context) {
+        this.context = context;
+    }
+
+    Object getContext() {
+        return context;
+    }
+
+    void setTimeoutTask(Future<?> task) {
+        synchronized (this) {
+            if (haveResult) {
+                task.cancel(false);
+            } else {
+                this.timeoutTask = task;
+            }
+        }
+    }
+
+    // creates latch if required; return true if caller needs to wait
+    private boolean prepareForWait() {
+        synchronized (this) {
+            if (haveResult) {
+                return false;
+            } else {
+                if (latch == null)
+                    latch = new CountDownLatch(1);
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Sets the result, or a no-op if the result or exception is already set.
+     */
+    void setResult(V res) {
+        synchronized (this) {
+            if (haveResult)
+                return;
+            result = res;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            if (latch != null)
+                latch.countDown();
+        }
+    }
+
+    /**
+     * Sets the result, or a no-op if the result or exception is already set.
+     */
+    void setFailure(Throwable x) {
+        if (!(x instanceof IOException) && !(x instanceof SecurityException))
+            x = new IOException(x);
+        synchronized (this) {
+            if (haveResult)
+                return;
+            exc = x;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+            if (latch != null)
+                latch.countDown();
+        }
+    }
+
+    /**
+     * Sets the result
+     */
+    void setResult(V res, Throwable x) {
+        if (x == null) {
+            setResult(res);
+        } else {
+            setFailure(x);
+        }
+    }
+
+    @Override
+    public V get() throws ExecutionException, InterruptedException {
+        if (!haveResult) {
+            boolean needToWait = prepareForWait();
+            if (needToWait)
+                latch.await();
+        }
+        if (exc != null) {
+            if (exc == CANCELLED)
+                throw new CancellationException();
+            throw new ExecutionException(exc);
+        }
+        return result;
+    }
+
+    @Override
+    public V get(long timeout, TimeUnit unit)
+        throws ExecutionException, InterruptedException, TimeoutException
+    {
+        if (!haveResult) {
+            boolean needToWait = prepareForWait();
+            if (needToWait)
+                if (!latch.await(timeout, unit)) throw new TimeoutException();
+        }
+        if (exc != null) {
+            if (exc == CANCELLED)
+                throw new CancellationException();
+            throw new ExecutionException(exc);
+        }
+        return result;
+    }
+
+    Throwable exception() {
+        return (exc != CANCELLED) ? exc : null;
+    }
+
+    V value() {
+        return result;
+    }
+
+    @Override
+    public boolean isCancelled() {
+        return (exc == CANCELLED);
+    }
+
+    @Override
+    public boolean isDone() {
+        return haveResult;
+    }
+
+    @Override
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        synchronized (this) {
+            if (haveResult)
+                return false;    // already completed
+
+            // notify channel
+            if (channel() instanceof Cancellable)
+                ((Cancellable)channel()).onCancel(this);
+
+            // set result and cancel timer
+            exc = CANCELLED;
+            haveResult = true;
+            if (timeoutTask != null)
+                timeoutTask.cancel(false);
+        }
+
+        // close channel if forceful cancel
+        if (mayInterruptIfRunning) {
+            try {
+                channel().close();
+            } catch (IOException ignore) { }
+        }
+
+        // release waiters
+        if (latch != null)
+            latch.countDown();
+        return true;
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/Port.java b/ojluni/src/main/java/sun/nio/ch/Port.java
new file mode 100755
index 0000000..9402508
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/Port.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.spi.AsynchronousChannelProvider;
+import java.nio.channels.*;
+import java.io.IOException;
+import java.io.Closeable;
+import java.io.FileDescriptor;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Base implementation of AsynchronousChannelGroupImpl for Unix systems.
+ */
+
+abstract class Port extends AsynchronousChannelGroupImpl {
+    static final short POLLIN       = 0x0001;
+    static final short POLLOUT      = 0x0004;
+    static final short POLLERR      = 0x0008;
+    static final short POLLHUP      = 0x0010;
+
+    /**
+     * Implemented by clients registered with this port.
+     */
+    interface PollableChannel extends Closeable {
+        void onEvent(int events, boolean mayInvokeDirect);
+    }
+
+    // maps fd to "pollable" channel
+    protected final ReadWriteLock fdToChannelLock = new ReentrantReadWriteLock();
+    protected final Map<Integer,PollableChannel> fdToChannel =
+        new HashMap<Integer,PollableChannel>();
+
+
+    Port(AsynchronousChannelProvider provider, ThreadPool pool) {
+        super(provider, pool);
+    }
+
+    /**
+     * Register channel identified by its file descriptor
+     */
+    final void register(int fd, PollableChannel ch) {
+        fdToChannelLock.writeLock().lock();
+        try {
+            if (isShutdown())
+                throw new ShutdownChannelGroupException();
+            fdToChannel.put(Integer.valueOf(fd), ch);
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * Unregister channel identified by its file descriptor
+     */
+    final void unregister(int fd) {
+        boolean checkForShutdown = false;
+
+        fdToChannelLock.writeLock().lock();
+        try {
+            fdToChannel.remove(Integer.valueOf(fd));
+
+            // last key to be removed so check if group is shutdown
+            if (fdToChannel.isEmpty())
+                checkForShutdown = true;
+
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+
+        // continue shutdown
+        if (checkForShutdown && isShutdown()) {
+            try {
+                shutdownNow();
+            } catch (IOException ignore) { }
+        }
+    }
+    /**
+     * Register file descriptor with polling mechanism for given events.
+     * The implementation should translate the events as required.
+     */
+    abstract void startPoll(int fd, int events);
+
+    @Override
+    final boolean isEmpty() {
+        fdToChannelLock.writeLock().lock();
+        try {
+            return fdToChannel.isEmpty();
+        } finally {
+            fdToChannelLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    final Object attachForeignChannel(final Channel channel, FileDescriptor fd) {
+        int fdVal = IOUtil.fdVal(fd);
+        register(fdVal, new PollableChannel() {
+            public void onEvent(int events, boolean mayInvokeDirect) { }
+            public void close() throws IOException {
+                channel.close();
+            }
+        });
+        return Integer.valueOf(fdVal);
+    }
+
+    @Override
+    final void detachForeignChannel(Object key) {
+        unregister((Integer)key);
+    }
+
+    @Override
+    final void closeAllChannels() {
+        /**
+         * Close channels in batches of up to 128 channels. This allows close
+         * to remove the channel from the map without interference.
+         */
+        final int MAX_BATCH_SIZE = 128;
+        PollableChannel channels[] = new PollableChannel[MAX_BATCH_SIZE];
+        int count;
+        do {
+            // grab a batch of up to 128 channels
+            fdToChannelLock.writeLock().lock();
+            count = 0;
+            try {
+                for (Integer fd: fdToChannel.keySet()) {
+                    channels[count++] = fdToChannel.get(fd);
+                    if (count >= MAX_BATCH_SIZE)
+                        break;
+                }
+            } finally {
+                fdToChannelLock.writeLock().unlock();
+            }
+
+            // close them
+            for (int i=0; i<count; i++) {
+                try {
+                    channels[i].close();
+                } catch (IOException ignore) { }
+            }
+        } while (count > 0);
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
new file mode 100755
index 0000000..3b431e7
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.net.InetSocketAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Unix implementation of AsynchronousServerSocketChannel
+ */
+
+class UnixAsynchronousServerSocketChannelImpl
+    extends AsynchronousServerSocketChannelImpl
+    implements Port.PollableChannel
+{
+    private final static NativeDispatcher nd = new SocketDispatcher();
+
+    private final Port port;
+    private final int fdVal;
+
+    // flag to indicate an accept is outstanding
+    private final AtomicBoolean accepting = new AtomicBoolean();
+    private void enableAccept() {
+        accepting.set(false);
+    }
+
+    // used to ensure that the context for an asynchronous accept is visible
+    // the pooled thread that handles the I/O event
+    private final Object updateLock = new Object();
+
+    // pending accept
+    private boolean acceptPending;
+    private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
+    private Object acceptAttachment;
+    private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
+
+    // context for permission check when security manager set
+    private AccessControlContext acceptAcc;
+
+
+    UnixAsynchronousServerSocketChannelImpl(Port port)
+        throws IOException
+    {
+        super(port);
+
+        try {
+            IOUtil.configureBlocking(fd, false);
+        } catch (IOException x) {
+            nd.close(fd);  // prevent leak
+            throw x;
+        }
+        this.port = port;
+        this.fdVal = IOUtil.fdVal(fd);
+
+        // add mapping from file descriptor to this channel
+        port.register(fdVal, this);
+    }
+
+    @Override
+    void implClose() throws IOException {
+        // remove the mapping
+        port.unregister(fdVal);
+
+        // close file descriptor
+        nd.close(fd);
+
+        // if there is a pending accept then complete it
+        CompletionHandler<AsynchronousSocketChannel,Object> handler;
+        Object att;
+        PendingFuture<AsynchronousSocketChannel,Object> future;
+        synchronized (updateLock) {
+            if (!acceptPending)
+                return;  // no pending accept
+            acceptPending = false;
+            handler = acceptHandler;
+            att = acceptAttachment;
+            future = acceptFuture;
+        }
+
+        // discard the stack trace as otherwise it may appear that implClose
+        // has thrown the exception.
+        AsynchronousCloseException x = new AsynchronousCloseException();
+        x.setStackTrace(new StackTraceElement[0]);
+        if (handler == null) {
+            future.setFailure(x);
+        } else {
+            // invoke by submitting task rather than directly
+            Invoker.invokeIndirectly(this, handler, att, null, x);
+        }
+    }
+
+    @Override
+    public AsynchronousChannelGroupImpl group() {
+        return port;
+    }
+
+    /**
+     * Invoked by event handling thread when listener socket is polled
+     */
+    @Override
+    public void onEvent(int events, boolean mayInvokeDirect) {
+        synchronized (updateLock) {
+            if (!acceptPending)
+                return;  // may have been grabbed by asynchronous close
+            acceptPending = false;
+        }
+
+        // attempt to accept connection
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+        Throwable exc = null;
+        try {
+            begin();
+            int n = accept0(this.fd, newfd, isaa);
+
+            // spurious wakeup, is this possible?
+            if (n == IOStatus.UNAVAILABLE) {
+                synchronized (updateLock) {
+                    acceptPending = true;
+                }
+                port.startPoll(fdVal, Port.POLLIN);
+                return;
+            }
+
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            end();
+        }
+
+        // Connection accepted so finish it when not holding locks.
+        AsynchronousSocketChannel child = null;
+        if (exc == null) {
+            try {
+                child = finishAccept(newfd, isaa[0], acceptAcc);
+            } catch (Throwable x) {
+                if (!(x instanceof IOException) && !(x instanceof SecurityException))
+                    x = new IOException(x);
+                exc = x;
+            }
+        }
+
+        // copy field befores accept is re-renabled
+        CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
+        Object att = acceptAttachment;
+        PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
+
+        // re-enable accepting and invoke handler
+        enableAccept();
+
+        if (handler == null) {
+            future.setResult(child, exc);
+            // if an async cancel has already cancelled the operation then
+            // close the new channel so as to free resources
+            if (child != null && future.isCancelled()) {
+                try {
+                    child.close();
+                } catch (IOException ignore) { }
+            }
+        } else {
+            Invoker.invoke(this, handler, att, child, exc);
+        }
+    }
+
+    /**
+     * Completes the accept by creating the AsynchronousSocketChannel for
+     * the given file descriptor and remote address. If this method completes
+     * with an IOException or SecurityException then the channel/file descriptor
+     * will be closed.
+     */
+    private AsynchronousSocketChannel finishAccept(FileDescriptor newfd,
+                                                   final InetSocketAddress remote,
+                                                   AccessControlContext acc)
+        throws IOException, SecurityException
+    {
+        AsynchronousSocketChannel ch = null;
+        try {
+            ch = new UnixAsynchronousSocketChannelImpl(port, newfd, remote);
+        } catch (IOException x) {
+            nd.close(newfd);
+            throw x;
+        }
+
+        // permission check must always be in initiator's context
+        try {
+            if (acc != null) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        SecurityManager sm = System.getSecurityManager();
+                        if (sm != null) {
+                            sm.checkAccept(remote.getAddress().getHostAddress(),
+                                           remote.getPort());
+                        }
+                        return null;
+                    }
+                }, acc);
+            } else {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    sm.checkAccept(remote.getAddress().getHostAddress(),
+                                   remote.getPort());
+                }
+            }
+        } catch (SecurityException x) {
+            try {
+                ch.close();
+            } catch (Throwable suppressed) {
+                x.addSuppressed(suppressed);
+            }
+            throw x;
+        }
+        return ch;
+    }
+
+    @Override
+    Future<AsynchronousSocketChannel> implAccept(Object att,
+        CompletionHandler<AsynchronousSocketChannel,Object> handler)
+    {
+        // complete immediately if channel is closed
+        if (!isOpen()) {
+            Throwable e = new ClosedChannelException();
+            if (handler == null) {
+                return CompletedFuture.withFailure(e);
+            } else {
+                Invoker.invoke(this, handler, att, null, e);
+                return null;
+            }
+        }
+        if (localAddress == null)
+            throw new NotYetBoundException();
+
+        // cancel was invoked with pending accept so connection may have been
+        // dropped.
+        if (isAcceptKilled())
+            throw new RuntimeException("Accept not allowed due cancellation");
+
+        // check and set flag to prevent concurrent accepting
+        if (!accepting.compareAndSet(false, true))
+            throw new AcceptPendingException();
+
+        // attempt accept
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+        Throwable exc = null;
+        try {
+            begin();
+
+            int n = accept0(this.fd, newfd, isaa);
+            if (n == IOStatus.UNAVAILABLE) {
+
+                // need calling context when there is security manager as
+                // permission check may be done in a different thread without
+                // any application call frames on the stack
+                PendingFuture<AsynchronousSocketChannel,Object> result = null;
+                synchronized (updateLock) {
+                    if (handler == null) {
+                        this.acceptHandler = null;
+                        result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
+                        this.acceptFuture = result;
+                    } else {
+                        this.acceptHandler = handler;
+                        this.acceptAttachment = att;
+                    }
+                    this.acceptAcc = (System.getSecurityManager() == null) ?
+                        null : AccessController.getContext();
+                    this.acceptPending = true;
+                }
+
+                // register for connections
+                port.startPoll(fdVal, Port.POLLIN);
+                return result;
+            }
+        } catch (Throwable x) {
+            // accept failed
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            end();
+        }
+
+        AsynchronousSocketChannel child = null;
+        if (exc == null) {
+            // connection accepted immediately
+            try {
+                child = finishAccept(newfd, isaa[0], null);
+            } catch (Throwable x) {
+                exc = x;
+            }
+        }
+
+        // re-enable accepting before invoking handler
+        enableAccept();
+
+        if (handler == null) {
+            return CompletedFuture.withResult(child, exc);
+        } else {
+            Invoker.invokeIndirectly(this, handler, att, child, exc);
+            return null;
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void initIDs();
+
+    // Accepts a new connection, setting the given file descriptor to refer to
+    // the new socket and setting isaa[0] to the socket's remote address.
+    // Returns 1 on success, or IOStatus.UNAVAILABLE.
+    //
+    private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
+                               InetSocketAddress[] isaa)
+        throws IOException;
+
+    static {
+        Util.load();
+        initIDs();
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
new file mode 100755
index 0000000..8b74488
--- /dev/null
+++ b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.*;
+import java.nio.ByteBuffer;
+import java.net.*;
+import java.util.concurrent.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import sun.net.NetHooks;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Unix implementation of AsynchronousSocketChannel
+ */
+
+class UnixAsynchronousSocketChannelImpl
+    extends AsynchronousSocketChannelImpl implements Port.PollableChannel
+{
+    private final static NativeDispatcher nd = new SocketDispatcher();
+    private static enum OpType { CONNECT, READ, WRITE };
+
+    private static final boolean disableSynchronousRead;
+    static {
+        String propValue = AccessController.doPrivileged(
+            new GetPropertyAction("sun.nio.ch.disableSynchronousRead", "false"));
+        disableSynchronousRead = (propValue.length() == 0) ?
+            true : Boolean.valueOf(propValue);
+    }
+
+    private final Port port;
+    private final int fdVal;
+
+    // used to ensure that the context for I/O operations that complete
+    // ascynrhonously is visible to the pooled threads handling I/O events.
+    private final Object updateLock = new Object();
+
+    // pending connect (updateLock)
+    private boolean connectPending;
+    private CompletionHandler<Void,Object> connectHandler;
+    private Object connectAttachment;
+    private PendingFuture<Void,Object> connectFuture;
+
+    // pending remote address (stateLock)
+    private SocketAddress pendingRemote;
+
+    // pending read (updateLock)
+    private boolean readPending;
+    private boolean isScatteringRead;
+    private ByteBuffer readBuffer;
+    private ByteBuffer[] readBuffers;
+    private CompletionHandler<Number,Object> readHandler;
+    private Object readAttachment;
+    private PendingFuture<Number,Object> readFuture;
+    private Future<?> readTimer;
+
+    // pending write (updateLock)
+    private boolean writePending;
+    private boolean isGatheringWrite;
+    private ByteBuffer writeBuffer;
+    private ByteBuffer[] writeBuffers;
+    private CompletionHandler<Number,Object> writeHandler;
+    private Object writeAttachment;
+    private PendingFuture<Number,Object> writeFuture;
+    private Future<?> writeTimer;
+
+
+    UnixAsynchronousSocketChannelImpl(Port port)
+        throws IOException
+    {
+        super(port);
+
+        // set non-blocking
+        try {
+            IOUtil.configureBlocking(fd, false);
+        } catch (IOException x) {
+            nd.close(fd);
+            throw x;
+        }
+
+        this.port = port;
+        this.fdVal = IOUtil.fdVal(fd);
+
+        // add mapping from file descriptor to this channel
+        port.register(fdVal, this);
+    }
+
+    // Constructor for sockets created by UnixAsynchronousServerSocketChannelImpl
+    UnixAsynchronousSocketChannelImpl(Port port,
+                                      FileDescriptor fd,
+                                      InetSocketAddress remote)
+        throws IOException
+    {
+        super(port, fd, remote);
+
+        this.fdVal = IOUtil.fdVal(fd);
+        IOUtil.configureBlocking(fd, false);
+
+        try {
+            port.register(fdVal, this);
+        } catch (ShutdownChannelGroupException x) {
+            // ShutdownChannelGroupException thrown if we attempt to register a
+            // new channel after the group is shutdown
+            throw new IOException(x);
+        }
+
+        this.port = port;
+    }
+
+    @Override
+    public AsynchronousChannelGroupImpl group() {
+        return port;
+    }
+
+    // register events for outstanding I/O operations, caller already owns updateLock
+    private void updateEvents() {
+        assert Thread.holdsLock(updateLock);
+        int events = 0;
+        if (readPending)
+            events |= Port.POLLIN;
+        if (connectPending || writePending)
+            events |= Port.POLLOUT;
+        if (events != 0)
+            port.startPoll(fdVal, events);
+    }
+
+    // register events for outstanding I/O operations
+    private void lockAndUpdateEvents() {
+        synchronized (updateLock) {
+            updateEvents();
+        }
+    }
+
+    // invoke to finish read and/or write operations
+    private void finish(boolean mayInvokeDirect,
+                        boolean readable,
+                        boolean writable)
+    {
+        boolean finishRead = false;
+        boolean finishWrite = false;
+        boolean finishConnect = false;
+
+        // map event to pending result
+        synchronized (updateLock) {
+            if (readable && this.readPending) {
+                this.readPending = false;
+                finishRead = true;
+            }
+            if (writable) {
+                if (this.writePending) {
+                    this.writePending = false;
+                    finishWrite = true;
+                } else if (this.connectPending) {
+                    this.connectPending = false;
+                    finishConnect = true;
+                }
+            }
+        }
+
+        // complete the I/O operation. Special case for when channel is
+        // ready for both reading and writing. In that case, submit task to
+        // complete write if write operation has a completion handler.
+        if (finishRead) {
+            if (finishWrite)
+                finishWrite(false);
+            finishRead(mayInvokeDirect);
+            return;
+        }
+        if (finishWrite) {
+            finishWrite(mayInvokeDirect);
+        }
+        if (finishConnect) {
+            finishConnect(mayInvokeDirect);
+        }
+    }
+
+    /**
+     * Invoked by event handler thread when file descriptor is polled
+     */
+    @Override
+    public void onEvent(int events, boolean mayInvokeDirect) {
+        boolean readable = (events & Port.POLLIN) > 0;
+        boolean writable = (events & Port.POLLOUT) > 0;
+        if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
+            readable = true;
+            writable = true;
+        }
+        finish(mayInvokeDirect, readable, writable);
+    }
+
+    @Override
+    void implClose() throws IOException {
+        // remove the mapping
+        port.unregister(fdVal);
+
+        // close file descriptor
+        nd.close(fd);
+
+        // All outstanding I/O operations are required to fail
+        finish(false, true, true);
+    }
+
+    @Override
+    public void onCancel(PendingFuture<?,?> task) {
+        if (task.getContext() == OpType.CONNECT)
+            killConnect();
+        if (task.getContext() == OpType.READ)
+            killReading();
+        if (task.getContext() == OpType.WRITE)
+            killWriting();
+    }
+
+    // -- connect --
+
+    private void setConnected() throws IOException {
+        synchronized (stateLock) {
+            state = ST_CONNECTED;
+            localAddress = Net.localAddress(fd);
+            remoteAddress = (InetSocketAddress)pendingRemote;
+        }
+    }
+
+    private void finishConnect(boolean mayInvokeDirect) {
+        Throwable e = null;
+        try {
+            begin();
+            checkConnect(fdVal);
+            setConnected();
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            e = x;
+        } finally {
+            end();
+        }
+        if (e != null) {
+            // close channel if connection cannot be established
+            try {
+                close();
+            } catch (Throwable suppressed) {
+                e.addSuppressed(suppressed);
+            }
+        }
+
+        // invoke handler and set result
+        CompletionHandler<Void,Object> handler = connectHandler;
+        Object att = connectAttachment;
+        PendingFuture<Void,Object> future = connectFuture;
+        if (handler == null) {
+            future.setResult(null, e);
+        } else {
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, null, e);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, null, e);
+            }
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    <A> Future<Void> implConnect(SocketAddress remote,
+                                 A attachment,
+                                 CompletionHandler<Void,? super A> handler)
+    {
+        if (!isOpen()) {
+            Throwable e = new ClosedChannelException();
+            if (handler == null) {
+                return CompletedFuture.withFailure(e);
+            } else {
+                Invoker.invoke(this, handler, attachment, null, e);
+                return null;
+            }
+        }
+
+        InetSocketAddress isa = Net.checkAddress(remote);
+
+        // permission check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
+
+        // check and set state
+        boolean notifyBeforeTcpConnect;
+        synchronized (stateLock) {
+            if (state == ST_CONNECTED)
+                throw new AlreadyConnectedException();
+            if (state == ST_PENDING)
+                throw new ConnectionPendingException();
+            state = ST_PENDING;
+            pendingRemote = remote;
+            notifyBeforeTcpConnect = (localAddress == null);
+        }
+
+        Throwable e = null;
+        try {
+            begin();
+            // notify hook if unbound
+            if (notifyBeforeTcpConnect)
+                NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
+            int n = Net.connect(fd, isa.getAddress(), isa.getPort());
+            if (n == IOStatus.UNAVAILABLE) {
+                // connection could not be established immediately
+                PendingFuture<Void,A> result = null;
+                synchronized (updateLock) {
+                    if (handler == null) {
+                        result = new PendingFuture<Void,A>(this, OpType.CONNECT);
+                        this.connectFuture = (PendingFuture<Void,Object>)result;
+                    } else {
+                        this.connectHandler = (CompletionHandler<Void,Object>)handler;
+                        this.connectAttachment = attachment;
+                    }
+                    this.connectPending = true;
+                    updateEvents();
+                }
+                return result;
+            }
+            setConnected();
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            e = x;
+        } finally {
+            end();
+        }
+
+        // close channel if connect fails
+        if (e != null) {
+            try {
+                close();
+            } catch (Throwable suppressed) {
+                e.addSuppressed(suppressed);
+            }
+        }
+        if (handler == null) {
+            return CompletedFuture.withResult(null, e);
+        } else {
+            Invoker.invoke(this, handler, attachment, null, e);
+            return null;
+        }
+    }
+
+    // -- read --
+
+    private void finishRead(boolean mayInvokeDirect) {
+        int n = -1;
+        Throwable exc = null;
+
+        // copy fields as we can't access them after reading is re-enabled.
+        boolean scattering = isScatteringRead;
+        CompletionHandler<Number,Object> handler = readHandler;
+        Object att = readAttachment;
+        PendingFuture<Number,Object> future = readFuture;
+        Future<?> timeout = readTimer;
+
+        try {
+            begin();
+
+            if (scattering) {
+                n = (int)IOUtil.read(fd, readBuffers, nd);
+            } else {
+                n = IOUtil.read(fd, readBuffer, -1, nd);
+            }
+            if (n == IOStatus.UNAVAILABLE) {
+                // spurious wakeup, is this possible?
+                synchronized (updateLock) {
+                    readPending = true;
+                }
+                return;
+            }
+
+            // allow objects to be GC'ed.
+            this.readBuffer = null;
+            this.readBuffers = null;
+            this.readAttachment = null;
+
+            // allow another read to be initiated
+            enableReading();
+
+        } catch (Throwable x) {
+            enableReading();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            // restart poll in case of concurrent write
+            if (!(exc instanceof AsynchronousCloseException))
+                lockAndUpdateEvents();
+            end();
+        }
+
+        // cancel the associated timer
+        if (timeout != null)
+            timeout.cancel(false);
+
+        // create result
+        Number result = (exc != null) ? null : (scattering) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // invoke handler or set result
+        if (handler == null) {
+            future.setResult(result, exc);
+        } else {
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, result, exc);
+            }
+        }
+    }
+
+    private Runnable readTimeoutTask = new Runnable() {
+        public void run() {
+            CompletionHandler<Number,Object> handler = null;
+            Object att = null;
+            PendingFuture<Number,Object> future = null;
+
+            synchronized (updateLock) {
+                if (!readPending)
+                    return;
+                readPending = false;
+                handler = readHandler;
+                att = readAttachment;
+                future = readFuture;
+            }
+
+            // kill further reading before releasing waiters
+            enableReading(true);
+
+            // invoke handler or set result
+            Exception exc = new InterruptedByTimeoutException();
+            if (handler == null) {
+                future.setFailure(exc);
+            } else {
+                AsynchronousChannel ch = UnixAsynchronousSocketChannelImpl.this;
+                Invoker.invokeIndirectly(ch, handler, att, null, exc);
+            }
+        }
+    };
+
+    /**
+     * Initiates a read or scattering read operation
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+                                            ByteBuffer dst,
+                                            ByteBuffer[] dsts,
+                                            long timeout,
+                                            TimeUnit unit,
+                                            A attachment,
+                                            CompletionHandler<V,? super A> handler)
+    {
+        // A synchronous read is not attempted if disallowed by system property
+        // or, we are using a fixed thread pool and the completion handler may
+        // not be invoked directly (because the thread is not a pooled thread or
+        // there are too many handlers on the stack).
+        Invoker.GroupAndInvokeCount myGroupAndInvokeCount = null;
+        boolean invokeDirect = false;
+        boolean attemptRead = false;
+        if (!disableSynchronousRead) {
+            if (handler == null) {
+                attemptRead = true;
+            } else {
+                myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
+                invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+                // okay to attempt read with user thread pool
+                attemptRead = invokeDirect || !port.isFixedThreadPool();
+            }
+        }
+
+        int n = IOStatus.UNAVAILABLE;
+        Throwable exc = null;
+        boolean pending = false;
+
+        try {
+            begin();
+
+            if (attemptRead) {
+                if (isScatteringRead) {
+                    n = (int)IOUtil.read(fd, dsts, nd);
+                } else {
+                    n = IOUtil.read(fd, dst, -1, nd);
+                }
+            }
+
+            if (n == IOStatus.UNAVAILABLE) {
+                PendingFuture<V,A> result = null;
+                synchronized (updateLock) {
+                    this.isScatteringRead = isScatteringRead;
+                    this.readBuffer = dst;
+                    this.readBuffers = dsts;
+                    if (handler == null) {
+                        this.readHandler = null;
+                        result = new PendingFuture<V,A>(this, OpType.READ);
+                        this.readFuture = (PendingFuture<Number,Object>)result;
+                        this.readAttachment = null;
+                    } else {
+                        this.readHandler = (CompletionHandler<Number,Object>)handler;
+                        this.readAttachment = attachment;
+                        this.readFuture = null;
+                    }
+                    if (timeout > 0L) {
+                        this.readTimer = port.schedule(readTimeoutTask, timeout, unit);
+                    }
+                    this.readPending = true;
+                    updateEvents();
+                }
+                pending = true;
+                return result;
+            }
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            if (!pending)
+                enableReading();
+            end();
+        }
+
+        Number result = (exc != null) ? null : (isScatteringRead) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // read completed immediately
+        if (handler != null) {
+            if (invokeDirect) {
+                Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+            }
+            return null;
+        } else {
+            return CompletedFuture.withResult((V)result, exc);
+        }
+    }
+
+    // -- write --
+
+    private void finishWrite(boolean mayInvokeDirect) {
+        int n = -1;
+        Throwable exc = null;
+
+        // copy fields as we can't access them after reading is re-enabled.
+        boolean gathering = this.isGatheringWrite;
+        CompletionHandler<Number,Object> handler = this.writeHandler;
+        Object att = this.writeAttachment;
+        PendingFuture<Number,Object> future = this.writeFuture;
+        Future<?> timer = this.writeTimer;
+
+        try {
+            begin();
+
+            if (gathering) {
+                n = (int)IOUtil.write(fd, writeBuffers, nd);
+            } else {
+                n = IOUtil.write(fd, writeBuffer, -1, nd);
+            }
+            if (n == IOStatus.UNAVAILABLE) {
+                // spurious wakeup, is this possible?
+                synchronized (updateLock) {
+                    writePending = true;
+                }
+                return;
+            }
+
+            // allow objects to be GC'ed.
+            this.writeBuffer = null;
+            this.writeBuffers = null;
+            this.writeAttachment = null;
+
+            // allow another write to be initiated
+            enableWriting();
+
+        } catch (Throwable x) {
+            enableWriting();
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            // restart poll in case of concurrent write
+            if (!(exc instanceof AsynchronousCloseException))
+                lockAndUpdateEvents();
+            end();
+        }
+
+        // cancel the associated timer
+        if (timer != null)
+            timer.cancel(false);
+
+        // create result
+        Number result = (exc != null) ? null : (gathering) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // invoke handler or set result
+        if (handler == null) {
+            future.setResult(result, exc);
+        } else {
+            if (mayInvokeDirect) {
+                Invoker.invokeUnchecked(handler, att, result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, att, result, exc);
+            }
+        }
+    }
+
+    private Runnable writeTimeoutTask = new Runnable() {
+        public void run() {
+            CompletionHandler<Number,Object> handler = null;
+            Object att = null;
+            PendingFuture<Number,Object> future = null;
+
+            synchronized (updateLock) {
+                if (!writePending)
+                    return;
+                writePending = false;
+                handler = writeHandler;
+                att = writeAttachment;
+                future = writeFuture;
+            }
+
+            // kill further writing before releasing waiters
+            enableWriting(true);
+
+            // invoke handler or set result
+            Exception exc = new InterruptedByTimeoutException();
+            if (handler != null) {
+                Invoker.invokeIndirectly(UnixAsynchronousSocketChannelImpl.this,
+                    handler, att, null, exc);
+            } else {
+                future.setFailure(exc);
+            }
+        }
+    };
+
+    /**
+     * Initiates a read or scattering read operation
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+                                             ByteBuffer src,
+                                             ByteBuffer[] srcs,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<V,? super A> handler)
+    {
+        Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
+            Invoker.getGroupAndInvokeCount();
+        boolean invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+        boolean attemptWrite = (handler == null) || invokeDirect ||
+            !port.isFixedThreadPool();  // okay to attempt write with user thread pool
+
+        int n = IOStatus.UNAVAILABLE;
+        Throwable exc = null;
+        boolean pending = false;
+
+        try {
+            begin();
+
+            if (attemptWrite) {
+                if (isGatheringWrite) {
+                    n = (int)IOUtil.write(fd, srcs, nd);
+                } else {
+                    n = IOUtil.write(fd, src, -1, nd);
+                }
+            }
+
+            if (n == IOStatus.UNAVAILABLE) {
+                PendingFuture<V,A> result = null;
+                synchronized (updateLock) {
+                    this.isGatheringWrite = isGatheringWrite;
+                    this.writeBuffer = src;
+                    this.writeBuffers = srcs;
+                    if (handler == null) {
+                        this.writeHandler = null;
+                        result = new PendingFuture<V,A>(this, OpType.WRITE);
+                        this.writeFuture = (PendingFuture<Number,Object>)result;
+                        this.writeAttachment = null;
+                    } else {
+                        this.writeHandler = (CompletionHandler<Number,Object>)handler;
+                        this.writeAttachment = attachment;
+                        this.writeFuture = null;
+                    }
+                    if (timeout > 0L) {
+                        this.writeTimer = port.schedule(writeTimeoutTask, timeout, unit);
+                    }
+                    this.writePending = true;
+                    updateEvents();
+                }
+                pending = true;
+                return result;
+            }
+        } catch (Throwable x) {
+            if (x instanceof ClosedChannelException)
+                x = new AsynchronousCloseException();
+            exc = x;
+        } finally {
+            if (!pending)
+                enableWriting();
+            end();
+        }
+
+        Number result = (exc != null) ? null : (isGatheringWrite) ?
+            (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+        // write completed immediately
+        if (handler != null) {
+            if (invokeDirect) {
+                Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+            } else {
+                Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+            }
+            return null;
+        } else {
+            return CompletedFuture.withResult((V)result, exc);
+        }
+    }
+
+    // -- Native methods --
+
+    private static native void checkConnect(int fdVal) throws IOException;
+
+    static {
+        Util.load();
+    }
+}
diff --git a/ojluni/src/main/java/sun/security/jca/ProviderConfig.java b/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
index 62f8bdd..fc4ee76 100755
--- a/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
+++ b/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
@@ -208,58 +208,68 @@
                 if (debug != null) {
                     debug.println("Loading provider: " + ProviderConfig.this);
                 }
+
                 try {
-                    ClassLoader cl = ClassLoader.getSystemClassLoader();
-                    Class<?> provClass;
-                    if (cl != null) {
-                        provClass = cl.loadClass(className);
-                    } else {
-                        provClass = Class.forName(className);
-                    }
-                    Object obj;
-                    if (hasArgument() == false) {
-                        obj = provClass.newInstance();
-                    } else {
-                        Constructor<?> cons = provClass.getConstructor(CL_STRING);
-                        obj = cons.newInstance(argument);
-                    }
-                    if (obj instanceof Provider) {
-                        if (debug != null) {
-                            debug.println("Loaded provider " + obj);
+                    // First try with the boot classloader.
+                    return initProvider(className, Object.class.getClassLoader());
+                } catch (Exception e1) {
+                    // If that fails, try with the system classloader.
+                    try {
+                        return initProvider(className, ClassLoader.getSystemClassLoader());
+                    } catch (Exception e) {
+                        Throwable t;
+                        if (e instanceof InvocationTargetException) {
+                            t = ((InvocationTargetException)e).getCause();
+                        } else {
+                            t = e;
                         }
-                        return (Provider)obj;
-                    } else {
                         if (debug != null) {
-                            debug.println(className + " is not a provider");
+                            debug.println("Error loading provider " + ProviderConfig.this);
+                            t.printStackTrace();
                         }
-                        disableLoad();
+                        // provider indicates fatal error, pass through exception
+                        if (t instanceof ProviderException) {
+                            throw (ProviderException)t;
+                        }
+                        // provider indicates that loading should not be retried
+                        if (t instanceof UnsupportedOperationException) {
+                            disableLoad();
+                        }
                         return null;
                     }
-                } catch (Exception e) {
-                    Throwable t;
-                    if (e instanceof InvocationTargetException) {
-                        t = ((InvocationTargetException)e).getCause();
-                    } else {
-                        t = e;
-                    }
-                    if (debug != null) {
-                        debug.println("Error loading provider " + ProviderConfig.this);
-                        t.printStackTrace();
-                    }
-                    // provider indicates fatal error, pass through exception
-                    if (t instanceof ProviderException) {
-                        throw (ProviderException)t;
-                    }
-                    // provider indicates that loading should not be retried
-                    if (t instanceof UnsupportedOperationException) {
-                        disableLoad();
-                    }
-                    return null;
                 }
             }
         });
     }
 
+    private Provider initProvider(String className, ClassLoader cl) throws Exception {
+        Class<?> provClass;
+        if (cl != null) {
+            provClass = cl.loadClass(className);
+        } else {
+            provClass = Class.forName(className);
+        }
+        Object obj;
+        if (hasArgument() == false) {
+            obj = provClass.newInstance();
+        } else {
+            Constructor<?> cons = provClass.getConstructor(CL_STRING);
+            obj = cons.newInstance(argument);
+        }
+        if (obj instanceof Provider) {
+            if (debug != null) {
+                debug.println("Loaded provider " + obj);
+            }
+            return (Provider)obj;
+        } else {
+            if (debug != null) {
+                debug.println(className + " is not a provider");
+            }
+            disableLoad();
+            return null;
+        }
+    }
+
     /**
      * Perform property expansion of the provider value.
      *
diff --git a/ojluni/src/main/java/sun/security/jca/Providers.java b/ojluni/src/main/java/sun/security/jca/Providers.java
index d66d4f8..2212dc2 100755
--- a/ojluni/src/main/java/sun/security/jca/Providers.java
+++ b/ojluni/src/main/java/sun/security/jca/Providers.java
@@ -56,6 +56,15 @@
         // triggers a getInstance() call (although that should not happen)
         providerList = ProviderList.EMPTY;
         providerList = ProviderList.fromSecurityProperties();
+
+        // removeInvalid is specified to try initializing all configured providers
+        // and removing those that aren't instantiable. This has the side effect
+        // of eagerly initializing all providers.
+        final int numConfiguredProviders = providerList.size();
+        providerList = providerList.removeInvalid();
+        if (numConfiguredProviders != providerList.size()) {
+            throw new AssertionError("Unable to configure default providers");
+        }
     }
 
     private Providers() {
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
index 51fac9b..756a48e 100755
--- a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
+++ b/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
@@ -207,7 +207,7 @@
                         "javax.net.ssl.sessionCacheSize");
                 }
             });
-            cacheLimit = (s != null) ? Integer.valueOf(s).intValue() : 0;
+            cacheLimit = (s != null) ? Integer.parseInt(s) : 0;
         } catch (Exception e) {
         }
 
diff --git a/ojluni/src/main/native/DatagramChannelImpl.c b/ojluni/src/main/native/DatagramChannelImpl.c
index 471c62b..4307743 100644
--- a/ojluni/src/main/native/DatagramChannelImpl.c
+++ b/ojluni/src/main/native/DatagramChannelImpl.c
@@ -145,6 +145,8 @@
         len = MAX_PACKET_LEN;
     }
 
+    memset(&sa, 0, sa_len);
+
     do {
         retry = JNI_FALSE;
         n = recvfrom(fd, buf, len, 0, (struct sockaddr *)&sa, &sa_len);
@@ -171,7 +173,7 @@
 
     // Peer (or other thread) has performed an orderly shutdown, sockaddr will be
     // invalid.
-    if (n == 0) {
+    if (n == 0 && ((struct sockaddr *)&sa)->sa_family == 0) {
         // zero the sender field, so receive() returns null and not
         // random garbage
         (*env)->SetObjectField(env, this, dci_senderID, NULL);
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index e065270..66ae35b 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -85,6 +85,7 @@
     ojluni/src/main/java/java/io/StringReader.java \
     ojluni/src/main/java/java/io/StringWriter.java \
     ojluni/src/main/java/java/io/SyncFailedException.java \
+    ojluni/src/main/java/java/io/UncheckedIOException.java \
     ojluni/src/main/java/java/io/UnixFileSystem.java \
     ojluni/src/main/java/java/io/UnsupportedEncodingException.java \
     ojluni/src/main/java/java/io/UTFDataFormatException.java \
@@ -309,15 +310,87 @@
     ojluni/src/main/java/java/nio/Buffer.java \
     ojluni/src/main/java/java/nio/BufferOverflowException.java \
     ojluni/src/main/java/java/nio/BufferUnderflowException.java \
-    ojluni/src/main/java/java/nio/ByteBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsDoubleBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsFloatBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsIntBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsLongBuffer.java \
     ojluni/src/main/java/java/nio/ByteBufferAsShortBuffer.java \
+    ojluni/src/main/java/java/nio/ByteBuffer.java \
     ojluni/src/main/java/java/nio/ByteOrder.java \
+    ojluni/src/main/java/java/nio/channels/AcceptPendingException.java \
+    ojluni/src/main/java/java/nio/channels/AlreadyBoundException.java \
+    ojluni/src/main/java/java/nio/channels/AlreadyConnectedException.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousChannelGroup.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousChannel.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousCloseException.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousServerSocketChannel.java \
+    ojluni/src/main/java/java/nio/channels/AsynchronousSocketChannel.java \
+    ojluni/src/main/java/java/nio/channels/ByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/CancelledKeyException.java \
+    ojluni/src/main/java/java/nio/channels/Channel.java \
+    ojluni/src/main/java/java/nio/channels/Channels.java \
+    ojluni/src/main/java/java/nio/channels/ClosedByInterruptException.java \
+    ojluni/src/main/java/java/nio/channels/ClosedChannelException.java \
+    ojluni/src/main/java/java/nio/channels/ClosedSelectorException.java \
+    ojluni/src/main/java/java/nio/channels/CompletionHandler.java \
+    ojluni/src/main/java/java/nio/channels/ConnectionPendingException.java \
+    ojluni/src/main/java/java/nio/channels/DatagramChannel.java \
+    ojluni/src/main/java/java/nio/channels/FileChannel.java \
+    ojluni/src/main/java/java/nio/channels/FileLockInterruptionException.java \
+    ojluni/src/main/java/java/nio/channels/FileLock.java \
+    ojluni/src/main/java/java/nio/channels/GatheringByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/IllegalBlockingModeException.java \
+    ojluni/src/main/java/java/nio/channels/IllegalChannelGroupException.java \
+    ojluni/src/main/java/java/nio/channels/IllegalSelectorException.java \
+    ojluni/src/main/java/java/nio/channels/InterruptedByTimeoutException.java \
+    ojluni/src/main/java/java/nio/channels/InterruptibleChannel.java \
+    ojluni/src/main/java/java/nio/channels/MembershipKey.java \
+    ojluni/src/main/java/java/nio/channels/MulticastChannel.java \
+    ojluni/src/main/java/java/nio/channels/NetworkChannel.java \
+    ojluni/src/main/java/java/nio/channels/NoConnectionPendingException.java \
+    ojluni/src/main/java/java/nio/channels/NonReadableChannelException.java \
+    ojluni/src/main/java/java/nio/channels/NonWritableChannelException.java \
+    ojluni/src/main/java/java/nio/channels/NotYetBoundException.java \
+    ojluni/src/main/java/java/nio/channels/NotYetConnectedException.java \
+    ojluni/src/main/java/java/nio/channels/OverlappingFileLockException.java \
+    ojluni/src/main/java/java/nio/channels/Pipe.java \
+    ojluni/src/main/java/java/nio/channels/ReadableByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/ReadPendingException.java \
+    ojluni/src/main/java/java/nio/channels/ScatteringByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/SeekableByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/SelectableChannel.java \
+    ojluni/src/main/java/java/nio/channels/SelectionKey.java \
+    ojluni/src/main/java/java/nio/channels/Selector.java \
+    ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java \
+    ojluni/src/main/java/java/nio/channels/ShutdownChannelGroupException.java \
+    ojluni/src/main/java/java/nio/channels/SocketChannel.java \
+    ojluni/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java \
+    ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java \
+    ojluni/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java \
+    ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java \
+    ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java \
+    ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java \
+    ojluni/src/main/java/java/nio/channels/UnresolvedAddressException.java \
+    ojluni/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java \
+    ojluni/src/main/java/java/nio/channels/WritableByteChannel.java \
+    ojluni/src/main/java/java/nio/channels/WritePendingException.java \
     ojluni/src/main/java/java/nio/CharBuffer.java \
+    ojluni/src/main/java/java/nio/CharBufferSpliterator.java \
+    ojluni/src/main/java/java/nio/charset/CharacterCodingException.java \
+    ojluni/src/main/java/java/nio/charset/CharsetDecoder.java \
+    ojluni/src/main/java/java/nio/charset/CharsetEncoder.java \
+    ojluni/src/main/java/java/nio/charset/Charset.java \
+    ojluni/src/main/java/java/nio/charset/CoderMalfunctionError.java \
+    ojluni/src/main/java/java/nio/charset/CoderResult.java \
+    ojluni/src/main/java/java/nio/charset/CodingErrorAction.java \
+    ojluni/src/main/java/java/nio/charset/IllegalCharsetNameException.java \
+    ojluni/src/main/java/java/nio/charset/MalformedInputException.java \
+    ojluni/src/main/java/java/nio/charset/spi/CharsetProvider.java \
+    ojluni/src/main/java/java/nio/charset/StandardCharsets.java \
+    ojluni/src/main/java/java/nio/charset/UnmappableCharacterException.java \
+    ojluni/src/main/java/java/nio/charset/UnsupportedCharsetException.java \
     ojluni/src/main/java/java/nio/DirectByteBuffer.java \
     ojluni/src/main/java/java/nio/DoubleBuffer.java \
     ojluni/src/main/java/java/nio/FloatBuffer.java \
@@ -335,62 +408,6 @@
     ojluni/src/main/java/java/nio/ReadOnlyBufferException.java \
     ojluni/src/main/java/java/nio/ShortBuffer.java \
     ojluni/src/main/java/java/nio/StringCharBuffer.java \
-    ojluni/src/main/java/java/nio/channels/AlreadyBoundException.java \
-    ojluni/src/main/java/java/nio/channels/AlreadyConnectedException.java \
-    ojluni/src/main/java/java/nio/channels/AsynchronousCloseException.java \
-    ojluni/src/main/java/java/nio/channels/ByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/CancelledKeyException.java \
-    ojluni/src/main/java/java/nio/channels/Channel.java \
-    ojluni/src/main/java/java/nio/channels/Channels.java \
-    ojluni/src/main/java/java/nio/channels/ClosedByInterruptException.java \
-    ojluni/src/main/java/java/nio/channels/ClosedChannelException.java \
-    ojluni/src/main/java/java/nio/channels/ClosedSelectorException.java \
-    ojluni/src/main/java/java/nio/channels/ConnectionPendingException.java \
-    ojluni/src/main/java/java/nio/channels/DatagramChannel.java \
-    ojluni/src/main/java/java/nio/channels/FileChannel.java \
-    ojluni/src/main/java/java/nio/channels/FileLock.java \
-    ojluni/src/main/java/java/nio/channels/FileLockInterruptionException.java \
-    ojluni/src/main/java/java/nio/channels/GatheringByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/IllegalBlockingModeException.java \
-    ojluni/src/main/java/java/nio/channels/IllegalSelectorException.java \
-    ojluni/src/main/java/java/nio/channels/InterruptibleChannel.java \
-    ojluni/src/main/java/java/nio/channels/NetworkChannel.java \
-    ojluni/src/main/java/java/nio/channels/NoConnectionPendingException.java \
-    ojluni/src/main/java/java/nio/channels/NonReadableChannelException.java \
-    ojluni/src/main/java/java/nio/channels/NonWritableChannelException.java \
-    ojluni/src/main/java/java/nio/channels/NotYetBoundException.java \
-    ojluni/src/main/java/java/nio/channels/NotYetConnectedException.java \
-    ojluni/src/main/java/java/nio/channels/OverlappingFileLockException.java \
-    ojluni/src/main/java/java/nio/channels/Pipe.java \
-    ojluni/src/main/java/java/nio/channels/ReadableByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/ScatteringByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/SeekableByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/SelectableChannel.java \
-    ojluni/src/main/java/java/nio/channels/SelectionKey.java \
-    ojluni/src/main/java/java/nio/channels/Selector.java \
-    ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java \
-    ojluni/src/main/java/java/nio/channels/SocketChannel.java \
-    ojluni/src/main/java/java/nio/channels/UnresolvedAddressException.java \
-    ojluni/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java \
-    ojluni/src/main/java/java/nio/channels/WritableByteChannel.java \
-    ojluni/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java \
-    ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java \
-    ojluni/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java \
-    ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java \
-    ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java \
-    ojluni/src/main/java/java/nio/charset/CharacterCodingException.java \
-    ojluni/src/main/java/java/nio/charset/Charset.java \
-    ojluni/src/main/java/java/nio/charset/CharsetDecoder.java \
-    ojluni/src/main/java/java/nio/charset/CharsetEncoder.java \
-    ojluni/src/main/java/java/nio/charset/CoderMalfunctionError.java \
-    ojluni/src/main/java/java/nio/charset/CoderResult.java \
-    ojluni/src/main/java/java/nio/charset/CodingErrorAction.java \
-    ojluni/src/main/java/java/nio/charset/IllegalCharsetNameException.java \
-    ojluni/src/main/java/java/nio/charset/MalformedInputException.java \
-    ojluni/src/main/java/java/nio/charset/StandardCharsets.java \
-    ojluni/src/main/java/java/nio/charset/UnmappableCharacterException.java \
-    ojluni/src/main/java/java/nio/charset/UnsupportedCharsetException.java \
-    ojluni/src/main/java/java/nio/charset/spi/CharsetProvider.java \
     ojluni/src/main/java/java/security/AccessControlContext.java \
     ojluni/src/main/java/java/security/AccessControlException.java \
     ojluni/src/main/java/java/security/AccessController.java \
@@ -648,6 +665,7 @@
     ojluni/src/main/java/java/util/AbstractSet.java \
     ojluni/src/main/java/java/util/ArrayDeque.java \
     ojluni/src/main/java/java/util/ArrayList.java \
+    ojluni/src/main/java/java/util/ArrayPrefixHelpers.java \
     ojluni/src/main/java/java/util/Arrays.java \
     ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java \
     ojluni/src/main/java/java/util/BitSet.java \
@@ -1176,11 +1194,17 @@
     ojluni/src/main/java/sun/nio/ch/AbstractPollArrayWrapper.java \
     ojluni/src/main/java/sun/nio/ch/AbstractPollSelectorImpl.java \
     ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java \
+    ojluni/src/main/java/sun/nio/ch/AsynchronousChannelGroupImpl.java \
+    ojluni/src/main/java/sun/nio/ch/AsynchronousServerSocketChannelImpl.java \
+    ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java \
+    ojluni/src/main/java/sun/nio/ch/BsdAsynchronousChannelProvider.java \
+    ojluni/src/main/java/sun/nio/ch/Cancellable.java \
     ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java \
     ojluni/src/main/java/sun/nio/ch/CompletedFuture.java \
     ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java \
     ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java \
     ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java \
+    ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java \
     ojluni/src/main/java/sun/nio/ch/DefaultSelectorProvider.java \
     ojluni/src/main/java/sun/nio/ch/DevPollArrayWrapper.java \
     ojluni/src/main/java/sun/nio/ch/DevPollSelectorImpl.java \
@@ -1188,6 +1212,7 @@
     ojluni/src/main/java/sun/nio/ch/DirectBuffer.java \
     ojluni/src/main/java/sun/nio/ch/EPollArrayWrapper.java \
     ojluni/src/main/java/sun/nio/ch/EPoll.java \
+    ojluni/src/main/java/sun/nio/ch/EPollPort.java \
     ojluni/src/main/java/sun/nio/ch/EPollSelectorImpl.java \
     ojluni/src/main/java/sun/nio/ch/EPollSelectorProvider.java \
     ojluni/src/main/java/sun/nio/ch/ExtendedSocketOption.java \
@@ -1198,21 +1223,30 @@
     ojluni/src/main/java/sun/nio/ch/FileKey.java \
     ojluni/src/main/java/sun/nio/ch/FileLockImpl.java \
     ojluni/src/main/java/sun/nio/ch/FileLockTable.java \
+    ojluni/src/main/java/sun/nio/ch/Groupable.java \
     ojluni/src/main/java/sun/nio/ch/InheritedChannel.java \
     ojluni/src/main/java/sun/nio/ch/Interruptible.java \
+    ojluni/src/main/java/sun/nio/ch/Invoker.java \
     ojluni/src/main/java/sun/nio/ch/IOStatus.java \
     ojluni/src/main/java/sun/nio/ch/IOUtil.java \
     ojluni/src/main/java/sun/nio/ch/IOVecWrapper.java \
+    ojluni/src/main/java/sun/nio/ch/KQueue.java \
+    ojluni/src/main/java/sun/nio/ch/KQueuePort.java \
+    ojluni/src/main/java/sun/nio/ch/LinuxAsynchronousChannelProvider.java \
+    ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java \
+    ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java \
     ojluni/src/main/java/sun/nio/ch/NativeDispatcher.java \
     ojluni/src/main/java/sun/nio/ch/NativeObject.java \
     ojluni/src/main/java/sun/nio/ch/NativeThread.java \
     ojluni/src/main/java/sun/nio/ch/NativeThreadSet.java \
     ojluni/src/main/java/sun/nio/ch/Net.java \
     ojluni/src/main/java/sun/nio/ch/OptionKey.java \
+    ojluni/src/main/java/sun/nio/ch/PendingFuture.java \
     ojluni/src/main/java/sun/nio/ch/PipeImpl.java \
     ojluni/src/main/java/sun/nio/ch/PollArrayWrapper.java \
     ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java \
     ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java \
+    ojluni/src/main/java/sun/nio/ch/Port.java \
     ojluni/src/main/java/sun/nio/ch/Reflect.java \
     ojluni/src/main/java/sun/nio/ch/SelChImpl.java \
     ojluni/src/main/java/sun/nio/ch/SelectionKeyImpl.java \
@@ -1227,6 +1261,8 @@
     ojluni/src/main/java/sun/nio/ch/SocketOptionRegistry.java \
     ojluni/src/main/java/sun/nio/ch/SourceChannelImpl.java \
     ojluni/src/main/java/sun/nio/ch/ThreadPool.java \
+    ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \
+    ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
     ojluni/src/main/java/sun/nio/ch/Util.java \
     ojluni/src/main/java/sun/nio/cs/ArrayDecoder.java \
     ojluni/src/main/java/sun/nio/cs/ArrayEncoder.java \
diff --git a/run-libcore-tests b/run-libcore-tests
index 90a2e41..996030a 100755
--- a/run-libcore-tests
+++ b/run-libcore-tests
@@ -21,9 +21,9 @@
 
 $VOGAR \
   --vm-arg -Xmx32M \
-  --classpath out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar \
-  --classpath out/target/common/obj/JAVA_LIBRARIES/sqlite-jdbc_intermediates/classes.jar \
-  --classpath out/target/common/obj/JAVA_LIBRARIES/bouncycastle_intermediates/classes.jar \
-  --classpath out/target/common/obj/JAVA_LIBRARIES/okhttp_intermediates/classes.jar \
+  --classpath out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/classes.jack \
+  --classpath out/target/common/obj/JAVA_LIBRARIES/sqlite-jdbc_intermediates/classes.jack \
+  --classpath out/target/common/obj/JAVA_LIBRARIES/bouncycastle_intermediates/classes.jack \
+  --classpath out/target/common/obj/JAVA_LIBRARIES/okhttp_intermediates/classes.jack \
   $test_packages \
   || true
diff --git a/support/src/test/java/libcore/java/security/CpuFeatures.java b/support/src/test/java/libcore/java/security/CpuFeatures.java
index 30ca868..319056a 100644
--- a/support/src/test/java/libcore/java/security/CpuFeatures.java
+++ b/support/src/test/java/libcore/java/security/CpuFeatures.java
@@ -19,6 +19,8 @@
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -39,6 +41,19 @@
             return true;
         }
 
+        // If we're in an emulated ABI, Conscrypt's NativeCrypto might bridge to
+        // a library that has accelerated AES instructions. See if Conscrypt
+        // detects that condition.
+        try {
+            Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto");
+            Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
+            return ((Integer) EVP_has_aes_hardware.invoke(null)) == 1;
+        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException
+                | IllegalAccessException | IllegalArgumentException ignored) {
+        } catch (InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+
         return false;
     }
 
diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java
index d6e6c91..2313a74 100644
--- a/support/src/test/java/libcore/java/security/TestKeyStore.java
+++ b/support/src/test/java/libcore/java/security/TestKeyStore.java
@@ -68,10 +68,12 @@
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import javax.crypto.spec.DHParameterSpec;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.TrustManager;
@@ -89,9 +91,6 @@
  * accessible via TestKeyStore.get().
  */
 public final class TestKeyStore extends Assert {
-    /** Size of DH keys to generate for testing. */
-    private static final int DH_KEY_SIZE_BITS = 1024;
-
     /** Size of DSA keys to generate for testing. */
     private static final int DSA_KEY_SIZE_BITS = 1024;
 
@@ -101,6 +100,35 @@
     /** Size of RSA keys to generate for testing. */
     private static final int RSA_KEY_SIZE_BITS = 1024;
 
+    // Generated with: openssl dhparam -C 1024
+    private static final BigInteger DH_PARAMS_P = new BigInteger(1, new byte[] {
+            (byte) 0xA2, (byte) 0x31, (byte) 0xB4, (byte) 0xB3, (byte) 0x6D, (byte) 0x9B,
+            (byte) 0x7E, (byte) 0xF4, (byte) 0xE7, (byte) 0x21, (byte) 0x51, (byte) 0x40,
+            (byte) 0xEB, (byte) 0xC6, (byte) 0xB6, (byte) 0xD6, (byte) 0x54, (byte) 0x56,
+            (byte) 0x72, (byte) 0xBE, (byte) 0x43, (byte) 0x18, (byte) 0x30, (byte) 0x5C,
+            (byte) 0x15, (byte) 0x5A, (byte) 0xF9, (byte) 0x19, (byte) 0x62, (byte) 0xAD,
+            (byte) 0xF4, (byte) 0x29, (byte) 0xCB, (byte) 0xC6, (byte) 0xF6, (byte) 0x64,
+            (byte) 0x0B, (byte) 0x9D, (byte) 0x23, (byte) 0x80, (byte) 0xF9, (byte) 0x5B,
+            (byte) 0x1C, (byte) 0x1C, (byte) 0x6A, (byte) 0xB4, (byte) 0xEA, (byte) 0xB9,
+            (byte) 0x80, (byte) 0x98, (byte) 0x8B, (byte) 0xAF, (byte) 0x15, (byte) 0xA8,
+            (byte) 0x5C, (byte) 0xC4, (byte) 0xB0, (byte) 0x41, (byte) 0x29, (byte) 0x66,
+            (byte) 0x9F, (byte) 0x9F, (byte) 0x1F, (byte) 0x88, (byte) 0x50, (byte) 0x97,
+            (byte) 0x38, (byte) 0x0B, (byte) 0x01, (byte) 0x16, (byte) 0xD6, (byte) 0x84,
+            (byte) 0x1D, (byte) 0x48, (byte) 0x6F, (byte) 0x7C, (byte) 0x06, (byte) 0x8C,
+            (byte) 0x6E, (byte) 0x68, (byte) 0xCD, (byte) 0x38, (byte) 0xE6, (byte) 0x22,
+            (byte) 0x30, (byte) 0x61, (byte) 0x37, (byte) 0x02, (byte) 0x3D, (byte) 0x47,
+            (byte) 0x62, (byte) 0xCE, (byte) 0xB9, (byte) 0x1A, (byte) 0x69, (byte) 0x9D,
+            (byte) 0xA1, (byte) 0x9F, (byte) 0x10, (byte) 0xA1, (byte) 0xAA, (byte) 0x70,
+            (byte) 0xF7, (byte) 0x27, (byte) 0x9C, (byte) 0xD4, (byte) 0xA5, (byte) 0x15,
+            (byte) 0xE2, (byte) 0x15, (byte) 0x0C, (byte) 0x20, (byte) 0x90, (byte) 0x08,
+            (byte) 0xB6, (byte) 0xF5, (byte) 0xDF, (byte) 0x1C, (byte) 0xCB, (byte) 0x82,
+            (byte) 0x6D, (byte) 0xC0, (byte) 0xE1, (byte) 0xBD, (byte) 0xCC, (byte) 0x4A,
+            (byte) 0x76, (byte) 0xE3,
+    });
+
+    // generator of 2
+    private static final BigInteger DH_PARAMS_G = BigInteger.valueOf(2);
+
     private static TestKeyStore ROOT_CA;
     private static TestKeyStore INTERMEDIATE_CA;
     private static TestKeyStore INTERMEDIATE_CA_2;
@@ -174,6 +202,7 @@
                 .aliasPrefix("RootCA")
                 .subject("CN=Test Root Certificate Authority")
                 .ca(true)
+                .certificateSerialNumber(BigInteger.valueOf(1))
                 .build();
         INTERMEDIATE_CA = new Builder()
                 .aliasPrefix("IntermediateCA")
@@ -181,12 +210,14 @@
                 .ca(true)
                 .signer(ROOT_CA.getPrivateKey("RSA", "RSA"))
                 .rootCa(ROOT_CA.getRootCertificate("RSA"))
+                .certificateSerialNumber(BigInteger.valueOf(2))
                 .build();
         SERVER = new Builder()
                 .aliasPrefix("server")
                 .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"))
                 .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA"))
                 .addSubjectAltNameIpAddress(LOCAL_HOST_ADDRESS)
+                .certificateSerialNumber(BigInteger.valueOf(3))
                 .build();
         CLIENT = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null);
         CLIENT_CERTIFICATE = new Builder()
@@ -293,6 +324,8 @@
                 = new ArrayList<GeneralSubtree>();
         private final List<GeneralSubtree> excludedNameConstraints
                 = new ArrayList<GeneralSubtree>();
+        // Generated randomly if not set
+        private BigInteger certificateSerialNumber = null;
 
         public Builder() {
             subject = localhost();
@@ -386,6 +419,11 @@
                     new GeneralName(GeneralName.iPAddress, new DEROctetString(ipAddress)));
         }
 
+        public Builder certificateSerialNumber(BigInteger certificateSerialNumber) {
+            this.certificateSerialNumber = certificateSerialNumber;
+            return this;
+        }
+
         public TestKeyStore build() {
             try {
                 if (StandardNames.IS_RI) {
@@ -483,16 +521,17 @@
             } else {
                 if (privateEntry == null) {
                     // 1a.) we make the keys
-                    int keySize;
+                    int keySize = -1;
+                    AlgorithmParameterSpec spec = null;
                     if (keyAlgorithm.equals("RSA")) {
                         keySize = RSA_KEY_SIZE_BITS;
                     } else if (keyAlgorithm.equals("DH_RSA")) {
-                        keySize = DH_KEY_SIZE_BITS;
+                        spec = new DHParameterSpec(DH_PARAMS_P, DH_PARAMS_G);
                         keyAlgorithm = "DH";
                     } else if (keyAlgorithm.equals("DSA")) {
                         keySize = DSA_KEY_SIZE_BITS;
                     } else if (keyAlgorithm.equals("DH_DSA")) {
-                        keySize = DH_KEY_SIZE_BITS;
+                        spec = new DHParameterSpec(DH_PARAMS_P, DH_PARAMS_G);
                         keyAlgorithm = "DH";
                     } else if (keyAlgorithm.equals("EC")) {
                         keySize = EC_KEY_SIZE_BITS;
@@ -504,7 +543,13 @@
                     }
 
                     KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
-                    kpg.initialize(keySize, new SecureRandom());
+                    if (spec != null) {
+                        kpg.initialize(spec);
+                    } else if (keySize != -1) {
+                        kpg.initialize(keySize);
+                    } else {
+                        throw new AssertionError("Must either have set algorithm parameters or key size!");
+                    }
 
                     KeyPair kp = kpg.generateKeyPair();
                     privateKey = kp.getPrivate();
@@ -523,7 +568,8 @@
                 x509c = createCertificate(publicKey, signingKey, subject, issuer, keyUsage, ca,
                                           extendedKeyUsages, criticalExtendedKeyUsages,
                                           subjectAltNames,
-                                          permittedNameConstraints, excludedNameConstraints);
+                                          permittedNameConstraints, excludedNameConstraints,
+                                          certificateSerialNumber);
             }
 
             X509Certificate[] x509cc;
@@ -565,7 +611,8 @@
                                      new ArrayList<Boolean>(),
                                      new ArrayList<GeneralName>(),
                                      new ArrayList<GeneralSubtree>(),
-                                     new ArrayList<GeneralSubtree>());
+                                     new ArrayList<GeneralSubtree>(),
+                                     null /* serialNumber, generated randomly */);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -582,7 +629,8 @@
             List<Boolean> criticalExtendedKeyUsages,
             List<GeneralName> subjectAltNames,
             List<GeneralSubtree> permittedNameConstraints,
-            List<GeneralSubtree> excludedNameConstraints) throws Exception {
+            List<GeneralSubtree> excludedNameConstraints,
+            BigInteger serialNumber) throws Exception {
         // Note that there is no way to programmatically make a
         // Certificate using java.* or javax.* APIs. The
         // CertificateFactory interface assumes you want to read
@@ -596,11 +644,6 @@
         Date start = new Date(now - millisPerDay);
         Date end = new Date(now + millisPerDay);
 
-        // Generate a random serial number.
-        byte[] serialBytes = new byte[16];
-        new SecureRandom().nextBytes(serialBytes);
-        BigInteger serial = new BigInteger(1, serialBytes);
-
         String keyAlgorithm = privateKey.getAlgorithm();
         String signatureAlgorithm;
         if (keyAlgorithm.equals("RSA")) {
@@ -622,7 +665,12 @@
         x509cg.setNotAfter(end);
         x509cg.setPublicKey(publicKey);
         x509cg.setSignatureAlgorithm(signatureAlgorithm);
-        x509cg.setSerialNumber(serial);
+        if (serialNumber == null) {
+            byte[] serialBytes = new byte[16];
+            new SecureRandom().nextBytes(serialBytes);
+            serialNumber = new BigInteger(1, serialBytes);
+        }
+        x509cg.setSerialNumber(serialNumber);
         if (keyUsage != 0) {
             x509cg.addExtension(X509Extensions.KeyUsage,
                                 true,