Merge "Removal of text/util spi classes and references"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index ef7703e..43ea9d6 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -53,7 +53,7 @@
   luni/src/main/java \
   ojluni/src/main/resources/
 test_resource_dirs := $(call all-core-resource-dirs,test)
-test_src_files := $(call all-test-java-files-under,dalvik dom harmony-tests json luni xml)
+test_src_files := $(call all-test-java-files-under,dalvik dalvik/test-rules dom harmony-tests json luni xml)
 ojtest_src_files := $(call all-test-java-files-under,ojluni)
 
 ifeq ($(EMMA_INSTRUMENT),true)
@@ -166,6 +166,24 @@
 LOCAL_CORE_LIBRARY := true
 include $(BUILD_JAVA_LIBRARY)
 
+# Build libcore test rules for target
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules
+LOCAL_JAVA_LIBRARIES := core-all core-junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Build libcore test rules for host
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules-hostdex
+LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target-hostdex
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(non_openjdk_java_files) $(android_icu4j_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(android_icu4j_resource_dirs)
@@ -189,8 +207,14 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp core-junit junit4-target bouncycastle mockito-target
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_STATIC_JAVA_LIBRARIES := \
+	core-test-rules \
+	core-tests-support \
+	mockwebserver \
+	nist-pkix-tests \
+	sqlite-jdbc
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -329,14 +353,14 @@
 LOCAL_CORE_LIBRARY := true
 include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
 
-# Make the core-tests library.
+# Make the core-tests-hostdex library.
 ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
     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 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_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host core-test-rules-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
new file mode 100644
index 0000000..bd5bf1a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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.BeforeExperiment;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public final class DateFormatBenchmark {
+
+    private Locale locale1;
+    private Locale locale2;
+    private Locale locale3;
+    private Locale locale4;
+
+    @BeforeExperiment
+    protected void setUp() throws Exception {
+        locale1 = Locale.TAIWAN;
+        locale2 = Locale.GERMANY;
+        locale3 = Locale.FRANCE;
+        locale4 = Locale.ITALY;
+    }
+
+    public void timeGetDateTimeInstance(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            DateFormat.getDateTimeInstance();
+        }
+    }
+
+    public void timeGetDateTimeInstance_multiple(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale1);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale2);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale3);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale4);
+        }
+    }
+}
diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java
index a45ffa1..e718ee7 100644
--- a/dalvik/src/main/java/dalvik/system/CloseGuard.java
+++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java
@@ -118,6 +118,16 @@
     private static volatile Reporter REPORTER = new DefaultReporter();
 
     /**
+     * The default {@link Tracker}.
+     */
+    private static final DefaultTracker DEFAULT_TRACKER = new DefaultTracker();
+
+    /**
+     * Hook for customizing how CloseGuard issues are tracked.
+     */
+    private static volatile Tracker currentTracker = DEFAULT_TRACKER;
+
+    /**
      * Returns a CloseGuard instance. If CloseGuard is enabled, {@code
      * #open(String)} can be used to set up the instance to warn on
      * failure to close. If CloseGuard is disabled, a non-null no-op
@@ -139,6 +149,13 @@
     }
 
     /**
+     * True if CloseGuard mechanism is enabled.
+     */
+    public static boolean isEnabled() {
+        return ENABLED;
+    }
+
+    /**
      * Used to replace default Reporter used to warn of CloseGuard
      * violations. Must be non-null.
      */
@@ -156,6 +173,32 @@
         return REPORTER;
     }
 
+    /**
+     * Sets the {@link Tracker} that is notified when resources are allocated and released.
+     *
+     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+     * MUST NOT be used for any other purposes.
+     *
+     * @throws NullPointerException if tracker is null
+     */
+    public static void setTracker(Tracker tracker) {
+        if (tracker == null) {
+            throw new NullPointerException("tracker == null");
+        }
+        currentTracker = tracker;
+    }
+
+    /**
+     * Returns {@link #setTracker(Tracker) last Tracker that was set}, or otherwise a default
+     * Tracker that does nothing.
+     *
+     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+     * MUST NOT be used for any other purposes.
+     */
+    public static Tracker getTracker() {
+        return currentTracker;
+    }
+
     private CloseGuard() {}
 
     /**
@@ -178,6 +221,7 @@
         }
         String message = "Explicit termination method '" + closer + "' not called";
         allocationSite = new Throwable(message);
+        currentTracker.open(allocationSite);
     }
 
     private Throwable allocationSite;
@@ -187,6 +231,7 @@
      * finalization.
      */
     public void close() {
+        currentTracker.close(allocationSite);
         allocationSite = null;
     }
 
@@ -209,10 +254,35 @@
     }
 
     /**
+     * Interface to allow customization of tracking behaviour.
+     *
+     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+     * MUST NOT be used for any other purposes.
+     */
+    public interface Tracker {
+        void open(Throwable allocationSite);
+        void close(Throwable allocationSite);
+    }
+
+    /**
+     * Default tracker which does nothing special and simply leaves it up to the GC to detect a
+     * leak.
+     */
+    private static final class DefaultTracker implements Tracker {
+        @Override
+        public void open(Throwable allocationSite) {
+        }
+
+        @Override
+        public void close(Throwable allocationSite) {
+        }
+    }
+
+    /**
      * Interface to allow customization of reporting behavior.
      */
-    public static interface Reporter {
-        public void report (String message, Throwable allocationSite);
+    public interface Reporter {
+        void report (String message, Throwable allocationSite);
     }
 
     /**
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java b/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
deleted file mode 100644
index b5bf380..0000000
--- a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2014 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 dalvik.system;
-
-import dalvik.system.CloseGuard.Reporter;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.ref.WeakReference;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Provides support for detecting issues found by {@link CloseGuard} from within tests.
- *
- * <p>This is a best effort as it relies on both {@link CloseGuard} being enabled and being able to
- * force a GC and finalization, none of which are directly controllable by this.
- *
- * <p>This is loaded using reflection by the AbstractResourceLeakageDetectorTestCase class as that
- * class needs to run on the reference implementation which does not have this class. It implements
- * {@link Runnable} because that is simpler than trying to manage a specialized interface.
- *
- * @hide
- */
-public class CloseGuardMonitor implements Runnable {
-  /**
-   * The {@link Reporter} instance used to receive warnings from {@link CloseGuard}.
-   */
-  private final Reporter closeGuardReporter;
-
-  /**
-   * The list of allocation sites that {@link CloseGuard} has reported as not being released.
-   *
-   * <p>Is thread safe as this will be called during finalization and so there are no guarantees
-   * as to whether it will be called concurrently or not.
-   */
-  private final List<Throwable> closeGuardAllocationSites = new CopyOnWriteArrayList<>();
-
-  /**
-   * Default constructor required for reflection.
-   */
-  public CloseGuardMonitor() {
-    System.logI("Creating CloseGuard monitor");
-
-    // Save current reporter.
-    closeGuardReporter = CloseGuard.getReporter();
-
-    // Override the reporter with our own which collates the allocation sites.
-    CloseGuard.setReporter(new Reporter() {
-      @Override
-      public void report(String message, Throwable allocationSite) {
-        // Ignore message as it's always the same.
-        closeGuardAllocationSites.add(allocationSite);
-      }
-    });
-  }
-
-  /**
-   * Check to see whether any resources monitored by {@link CloseGuard} were not released before
-   * they were garbage collected.
-   */
-  @Override
-  public void run() {
-    // Create a weak reference to an object so that we can detect when it is garbage collected.
-    WeakReference<Object> reference = new WeakReference<>(new Object());
-
-    try {
-      // 'Force' a GC and finalize to cause CloseGuards to report warnings. Doesn't loop
-      // forever as there are no guarantees that the following code does anything at all so
-      // don't want a potential infinite loop.
-      Runtime runtime = Runtime.getRuntime();
-      for (int i = 0; i < 20; ++i) {
-        runtime.gc();
-        System.runFinalization();
-        try {
-          Thread.sleep(1);
-        } catch (InterruptedException e) {
-          throw new AssertionError(e);
-        }
-
-        // Check to see if the weak reference has been garbage collected.
-        if (reference.get() == null) {
-          System.logI("Sentry object has been freed so assuming CloseGuards have reported"
-              + " any resource leakages");
-          break;
-        }
-      }
-    } finally {
-      // Restore the reporter.
-      CloseGuard.setReporter(closeGuardReporter);
-    }
-
-    if (!closeGuardAllocationSites.isEmpty()) {
-      StringWriter writer = new StringWriter();
-      PrintWriter printWriter = new PrintWriter(writer);
-      int i = 0;
-      for (Throwable allocationSite : closeGuardAllocationSites) {
-        printWriter.print(++i);
-        printWriter.print(") ");
-        allocationSite.printStackTrace(printWriter);
-        printWriter.println("    --------------------------------");
-      }
-      throw new AssertionError("Potential resource leakage detected:\n" + writer);
-    }
-  }
-}
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardTest.java b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
new file mode 100644
index 0000000..a1d1f42
--- /dev/null
+++ b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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 dalvik.system;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Tests {@link CloseGuard}.
+ */
+public class CloseGuardTest {
+
+    /**
+     * Resets the {@link CloseGuard#ENABLED} state back to the value it had when the test started.
+     */
+    @Rule
+    public TestRule rule = this::preserveEnabledState;
+
+    private Statement preserveEnabledState(final Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                boolean oldEnabledState = CloseGuard.isEnabled();
+                try {
+                    base.evaluate();
+                } finally {
+                    CloseGuard.setEnabled(oldEnabledState);
+                }
+            }
+        };
+    }
+
+    @Test
+    public void testEnabled_NotOpen() throws Throwable {
+        CloseGuard.setEnabled(true);
+        ResourceOwner owner = new ResourceOwner();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testEnabled_OpenNotClosed() throws Throwable {
+        CloseGuard.setEnabled(true);
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        assertUnreleasedResources(owner, 1);
+    }
+
+    @Test
+    public void testEnabled_OpenThenClosed() throws Throwable {
+        CloseGuard.setEnabled(true);
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        owner.close();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable {
+        CloseGuard.setEnabled(true);
+        ResourceOwner owner = new ResourceOwner();
+        CloseGuard.setEnabled(false);
+        owner.open();
+
+        // Although the resource was not released it should not report it because CloseGuard was
+        // not enabled when the CloseGuard was opened.
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testEnabledWhenOpened_DisabledWhenFinalized() throws Throwable {
+        CloseGuard.setEnabled(true);
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        CloseGuard.setEnabled(false);
+
+        // Although the resource was not released it should not report it because CloseGuard was
+        // not enabled when the CloseGuard was finalized.
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testDisabled_NotOpen() throws Throwable {
+        CloseGuard.setEnabled(false);
+        ResourceOwner owner = new ResourceOwner();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testDisabled_OpenNotClosed() throws Throwable {
+        CloseGuard.setEnabled(false);
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testDisabled_OpenThenClosed() throws Throwable {
+        CloseGuard.setEnabled(false);
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        owner.close();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable {
+        CloseGuard.setEnabled(false);
+        ResourceOwner owner = new ResourceOwner();
+        CloseGuard.setEnabled(true);
+        owner.open();
+
+        // Although the resource was not released it should not report it because CloseGuard was
+        // not enabled when the CloseGuard was created.
+        assertUnreleasedResources(owner, 0);
+    }
+
+    private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
+            throws Throwable {
+        try {
+            CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
+        } finally {
+            // Close the resource so that CloseGuard does not generate a warning for real when it
+            // is actually finalized.
+            owner.close();
+        }
+    }
+
+    /**
+     * A test user of {@link CloseGuard}.
+     */
+    private static class ResourceOwner {
+
+        private final CloseGuard closeGuard;
+
+        ResourceOwner() {
+            closeGuard = CloseGuard.get();
+        }
+
+        public void open() {
+            closeGuard.open("close");
+        }
+
+        public void close() {
+            closeGuard.close();
+        }
+
+        /**
+         * Make finalize public so that it can be tested directly without relying on garbage
+         * collection to trigger it.
+         */
+        @Override
+        public void finalize() throws Throwable {
+            closeGuard.warnIfOpen();
+            super.finalize();
+        }
+    }
+}
diff --git a/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
new file mode 100644
index 0000000..7871795
--- /dev/null
+++ b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
@@ -0,0 +1,286 @@
+/*
+ * 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 dalvik.system;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that use {@link CloseGuard} in order to detect resource
+ * leakages.
+ *
+ * <p>This class should not be used directly by tests as that will prevent them from being
+ * compilable and testable on OpenJDK platform. Instead they should use
+ * {@code libcore.junit.util.ResourceLeakageDetector} which accesses the capabilities of this using
+ * reflection and if it cannot find it (because it is running on OpenJDK) then it will just skip
+ * leakage detection.
+ *
+ * <p>This provides two entry points that are accessed reflectively:
+ * <ul>
+ * <li>
+ * <p>The {@link #getRule()} method. This returns a {@link TestRule} that will fail a test if it
+ * detects any resources that were allocated during the test but were not released.
+ *
+ * <p>This only tracks resources that were allocated on the test thread, although it does not care
+ * what thread they were released on. This avoids flaky false positives where a background thread
+ * allocates a resource during a test but releases it after the test.
+ *
+ * <p>It is still possible to have a false positive in the case where the test causes a caching
+ * mechanism to open a resource and hold it open past the end of the test. In that case if there is
+ * no way to clear the cached data then it should be relatively simple to move the code that invokes
+ * the caching mechanism to outside the scope of this rule. i.e.
+ *
+ * <pre>{@code
+ *     @Rule
+ *     public final TestRule ruleChain = org.junit.rules.RuleChain
+ *         .outerRule(new ...invoke caching mechanism...)
+ *         .around(CloseGuardSupport.getRule());
+ * }</pre>
+ * </li>
+ * <li>
+ * <p>The {@link #getFinalizerChecker()} method. This returns a {@link BiConsumer} that takes an
+ * object that owns resources and an expected number of unreleased resources. It will call the
+ * {@link Object#finalize()} method on the object using reflection and throw an
+ * {@link AssertionError} if the number of reported unreleased resources does not match the
+ * expected number.
+ * </li>
+ * </ul>
+ */
+public class CloseGuardSupport {
+
+    private static final TestRule CLOSE_GUARD_RULE = new FailTestWhenResourcesNotClosedRule();
+
+    /**
+     * Get a {@link TestRule} that will detect when resources that use the {@link CloseGuard}
+     * mechanism are not cleaned up properly by a test.
+     *
+     * <p>If the {@link CloseGuard} mechanism is not supported, e.g. on OpenJDK, then the returned
+     * rule does nothing.
+     */
+    public static TestRule getRule() {
+        return CLOSE_GUARD_RULE;
+    }
+
+    private CloseGuardSupport() {
+    }
+
+    /**
+     * Fails a test when resources are not cleaned up properly.
+     */
+    private static class FailTestWhenResourcesNotClosedRule implements TestRule {
+        /**
+         * Returns a {@link Statement} that will fail the test if it ends with unreleased resources.
+         * @param base the test to be run.
+         */
+        public Statement apply(Statement base, Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    // Get the previous tracker so that it can be restored afterwards.
+                    CloseGuard.Tracker previousTracker = CloseGuard.getTracker();
+                    // Get the previous enabled state so that it can be restored afterwards.
+                    boolean previousEnabled = CloseGuard.isEnabled();
+                    TestCloseGuardTracker tracker = new TestCloseGuardTracker();
+                    Throwable thrown = null;
+                    try {
+                        // Set the test tracker and enable close guard detection.
+                        CloseGuard.setTracker(tracker);
+                        CloseGuard.setEnabled(true);
+                        base.evaluate();
+                    } catch (Throwable throwable) {
+                        // Catch and remember the throwable so that it can be rethrown in the
+                        // finally block.
+                        thrown = throwable;
+                    } finally {
+                        // Restore the previous tracker and enabled state.
+                        CloseGuard.setEnabled(previousEnabled);
+                        CloseGuard.setTracker(previousTracker);
+
+                        Collection<Throwable> allocationSites =
+                                tracker.getAllocationSitesForUnreleasedResources();
+                        if (!allocationSites.isEmpty()) {
+                            if (thrown == null) {
+                                thrown = new IllegalStateException(
+                                        "Unreleased resources found in test");
+                            }
+                            for (Throwable allocationSite : allocationSites) {
+                                thrown.addSuppressed(allocationSite);
+                            }
+                        }
+                        if (thrown != null) {
+                            throw thrown;
+                        }
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * A tracker that keeps a record of the allocation sites for all resources allocated but not
+     * yet released.
+     *
+     * <p>It only tracks resources allocated for the test thread.
+     */
+    private static class TestCloseGuardTracker implements CloseGuard.Tracker {
+
+        /**
+         * A set would be preferable but this is the closest that matches the concurrency
+         * requirements for the use case which prioritise speed of addition and removal over
+         * iteration and access.
+         */
+        private final Set<Throwable> allocationSites =
+                Collections.newSetFromMap(new ConcurrentHashMap<>());
+
+        private final Thread testThread = Thread.currentThread();
+
+        @Override
+        public void open(Throwable allocationSite) {
+            if (Thread.currentThread() == testThread) {
+                allocationSites.add(allocationSite);
+            }
+        }
+
+        @Override
+        public void close(Throwable allocationSite) {
+            // Closing the resource twice could pass null into here.
+            if (allocationSite != null) {
+                allocationSites.remove(allocationSite);
+            }
+        }
+
+        /**
+         * Get the collection of allocation sites for any unreleased resources.
+         */
+        Collection<Throwable> getAllocationSitesForUnreleasedResources() {
+            return new ArrayList<>(allocationSites);
+        }
+    }
+
+    private static final BiConsumer<Object, Integer> FINALIZER_CHECKER
+            = new BiConsumer<Object, Integer>() {
+        @Override
+        public void accept(Object resourceOwner, Integer expectedCount) {
+            finalizerChecker(resourceOwner, expectedCount);
+        }
+    };
+
+    /**
+     * Get access to a {@link BiConsumer} that will determine how many unreleased resources the
+     * first parameter owns and throw a {@link AssertionError} if that does not match the
+     * expected number of resources specified by the second parameter.
+     *
+     * <p>This uses a {@link BiConsumer} as it is a standard interface that is available in all
+     * environments. That helps avoid the caller from having compile time dependencies on this
+     * class which will not be available on OpenJDK.
+     */
+    public static BiConsumer<Object, Integer> getFinalizerChecker() {
+        return FINALIZER_CHECKER;
+    }
+
+    /**
+     * Checks that the supplied {@code resourceOwner} has overridden the {@link Object#finalize()}
+     * method and uses {@link CloseGuard#warnIfOpen()} correctly to detect when the resource is
+     * not released.
+     *
+     * @param resourceOwner the owner of the resource protected by {@link CloseGuard}.
+     * @param expectedCount the expected number of unreleased resources to be held by the owner.
+     *
+     */
+    private static void finalizerChecker(Object resourceOwner, int expectedCount) {
+        Class<?> clazz = resourceOwner.getClass();
+        Method finalizer = null;
+        while (clazz != null && clazz != Object.class) {
+            try {
+                finalizer = clazz.getDeclaredMethod("finalize");
+                break;
+            } catch (NoSuchMethodException e) {
+                // Carry on up the class hierarchy.
+                clazz = clazz.getSuperclass();
+            }
+        }
+
+        if (finalizer == null) {
+            // No finalizer method could be found.
+            throw new AssertionError("Class " + resourceOwner.getClass().getName()
+                    + " does not have a finalize() method");
+        }
+
+        // Make the method accessible.
+        finalizer.setAccessible(true);
+
+        CloseGuard.Reporter oldReporter = CloseGuard.getReporter();
+        try {
+            CollectingReporter reporter = new CollectingReporter();
+            CloseGuard.setReporter(reporter);
+
+            // Invoke the finalizer to cause it to get CloseGuard to report a problem if it has
+            // not yet been closed.
+            try {
+                finalizer.invoke(resourceOwner);
+            } catch (ReflectiveOperationException e) {
+                throw new AssertionError(
+                        "Could not invoke the finalizer() method on " + resourceOwner, e);
+            }
+
+            reporter.assertUnreleasedResources(expectedCount);
+        } finally {
+            CloseGuard.setReporter(oldReporter);
+        }
+    }
+
+    /**
+     * A {@link CloseGuard.Reporter} that collects any reports about unreleased resources.
+     */
+    private static class CollectingReporter implements CloseGuard.Reporter {
+
+        private final Thread callingThread = Thread.currentThread();
+
+        private final List<Throwable> unreleasedResourceAllocationSites = new ArrayList<>();
+
+        @Override
+        public void report(String message, Throwable allocationSite) {
+            // Only care about resources that are not reported on this thread.
+            if (callingThread == Thread.currentThread()) {
+                unreleasedResourceAllocationSites.add(allocationSite);
+            }
+        }
+
+        void assertUnreleasedResources(int expectedCount) {
+            int unreleasedResourceCount = unreleasedResourceAllocationSites.size();
+            if (unreleasedResourceCount == expectedCount) {
+                return;
+            }
+
+            AssertionError error = new AssertionError(
+                    "Expected " + expectedCount + " unreleased resources, found "
+                            + unreleasedResourceCount + "; see suppressed exceptions for details");
+            for (Throwable unreleasedResourceAllocationSite : unreleasedResourceAllocationSites) {
+                error.addSuppressed(unreleasedResourceAllocationSite);
+            }
+            throw error;
+        }
+    }
+}
diff --git a/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
new file mode 100644
index 0000000..fe05710
--- /dev/null
+++ b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
@@ -0,0 +1,182 @@
+/*
+ * 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 dalvik.system;
+
+import java.util.Collections;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.junit.runners.JUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JUnit4.class)
+public class CloseGuardSupportTest {
+
+    @Test
+    public void testDoesReleaseResource() {
+        List<Failure> failures = JUnitCore.runClasses(DoesReleaseResource.class).getFailures();
+        assertEquals(Collections.emptyList(), failures);
+    }
+
+    public static class DoesReleaseResource {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test public void test() {
+            CloseGuard closeGuard = CloseGuard.get();
+            closeGuard.open("test resource");
+            closeGuard.close();
+        }
+    }
+
+    @Test
+    public void testDoesReleaseResourceTwice() {
+        List<Failure> failures = JUnitCore.runClasses(DoesReleaseResourceTwice.class).getFailures();
+        assertEquals(Collections.emptyList(), failures);
+    }
+
+    public static class DoesReleaseResourceTwice {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test public void test() {
+            CloseGuard closeGuard = CloseGuard.get();
+            closeGuard.open("test resource");
+            closeGuard.close();
+            closeGuard.close();
+        }
+    }
+
+    @Test
+    public void testDoesNotReleaseResource() {
+        List<Failure> failures = JUnitCore.runClasses(DoesNotReleaseResource.class).getFailures();
+        assertEquals("Failure count", 1, failures.size());
+        Failure failure = failures.get(0);
+        checkResourceNotReleased(failure, "Unreleased resources found in test");
+    }
+
+    public static class DoesNotReleaseResource {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test public void test() {
+            CloseGuard closeGuard = CloseGuard.get();
+            closeGuard.open("test resource");
+        }
+    }
+
+    @Test
+    public void testDoesNotReleaseResourceDueToFailure() {
+        List<Failure> failures = JUnitCore
+                .runClasses(DoesNotReleaseResourceDueToFailure.class)
+                .getFailures();
+        assertEquals("Failure count", 1, failures.size());
+        Failure failure = failures.get(0);
+        checkResourceNotReleased(failure, "failure");
+    }
+
+    public static class DoesNotReleaseResourceDueToFailure {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test public void test() {
+            CloseGuard closeGuard = CloseGuard.get();
+            closeGuard.open("test resource");
+            fail("failure");
+        }
+    }
+
+    @Test
+    public void testResourceOwnerDoesNotOverrideFinalize() {
+        List<Failure> failures = JUnitCore
+                .runClasses(ResourceOwnerDoesNotOverrideFinalize.class)
+                .getFailures();
+        assertEquals("Failure count", 1, failures.size());
+        Failure failure = failures.get(0);
+        assertEquals("Class java.lang.String does not have a finalize() method",
+                failure.getMessage());
+    }
+
+    public static class ResourceOwnerDoesNotOverrideFinalize {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test
+        public void test() {
+            CloseGuardSupport.getFinalizerChecker().accept("not resource owner", 0);
+        }
+    }
+
+    @Test
+    public void testResourceOwnerOverridesFinalizeButDoesNotReportLeak() {
+        List<Failure> failures = JUnitCore
+                .runClasses(ResourceOwnerOverridesFinalizeButDoesNotReportLeak.class)
+                .getFailures();
+        assertEquals("Failure count", 1, failures.size());
+        Failure failure = failures.get(0);
+        assertEquals("Expected 1 unreleased resources, found 0;"
+                        + " see suppressed exceptions for details",
+                failure.getMessage());
+    }
+
+    public static class ResourceOwnerOverridesFinalizeButDoesNotReportLeak {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test
+        public void test() {
+            CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+                @Override
+                protected void finalize() throws Throwable {
+                    super.finalize();
+                }
+            }, 1);
+        }
+    }
+
+    @Test
+    public void testResourceOwnerOverridesFinalizeAndReportsLeak() {
+        List<Failure> failures = JUnitCore
+                .runClasses(ResourceOwnerOverridesFinalizeAndReportsLeak.class)
+                .getFailures();
+        assertEquals("Failure count", 1, failures.size());
+        Failure failure = failures.get(0);
+        checkResourceNotReleased(failure, "Unreleased resources found in test");
+    }
+
+    public static class ResourceOwnerOverridesFinalizeAndReportsLeak {
+        @Rule public TestRule rule = CloseGuardSupport.getRule();
+        @Test
+        public void test() {
+            CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+                private CloseGuard guard = CloseGuard.get();
+                {
+                    guard.open("test resource");
+                }
+                @Override
+                protected void finalize() throws Throwable {
+                    guard.warnIfOpen();
+                    super.finalize();
+                }
+            }, 1);
+        }
+    }
+
+    private void checkResourceNotReleased(Failure failure, String expectedMessage) {
+        @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+        Throwable exception = failure.getException();
+        assertEquals(expectedMessage, exception.getMessage());
+        Throwable[] suppressed = exception.getSuppressed();
+        assertEquals("Suppressed count", 1, suppressed.length);
+        exception = suppressed[0];
+        assertEquals("Explicit termination method 'test resource' not called",
+                exception.getMessage());
+    }
+}
diff --git a/luni/src/main/native/ExecStrings.cpp b/luni/src/main/native/ExecStrings.cpp
index a6a62e2..4f90431 100644
--- a/luni/src/main/native/ExecStrings.cpp
+++ b/luni/src/main/native/ExecStrings.cpp
@@ -20,7 +20,8 @@
 
 #include <stdlib.h>
 
-#include "cutils/log.h"
+#include <android/log.h>
+
 #include "ScopedLocalRef.h"
 
 ExecStrings::ExecStrings(JNIEnv* env, jobjectArray java_string_array)
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index 98648a5..6b29e67 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -16,16 +16,17 @@
 
 #define LOG_TAG "IcuUtilities"
 
+#include <android/log.h>
+
 #include "IcuUtilities.h"
 
 #include "JniConstants.h"
 #include "JniException.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
-#include "cutils/log.h"
 #include "unicode/strenum.h"
-#include "unicode/uloc.h"
 #include "unicode/ustring.h"
+#include "unicode/uloc.h"
 
 jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration* se) {
   if (maybeThrowIcuException(env, provider, status)) {
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 52df40e..ec9d878 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -16,12 +16,13 @@
 
 #define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
 
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include "android/log.h"
+
 #include "JniConstants.h"
 #include "ScopedLocalFrame.h"
 
-#include <stdlib.h>
-
 // DalvikVM calls this on startup, so we can statically register all our native methods.
 jint JNI_OnLoad(JavaVM* vm, void*) {
     JNIEnv* env;
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index e6f378e..7456028 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -16,6 +16,24 @@
 
 #define LOG_TAG "ICU"
 
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+#include <android-base/unique_fd.h>
+
 #include "IcuUtilities.h"
 #include "JNIHelp.h"
 #include "JniConstants.h"
@@ -24,7 +42,6 @@
 #include "ScopedJavaUnicodeString.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
-#include "cutils/log.h"
 #include "toStringArray.h"
 #include "unicode/brkiter.h"
 #include "unicode/calendar.h"
@@ -51,22 +68,6 @@
 #include "ureslocs.h"
 #include "valueOf.h"
 
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <memory>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
 class ScopedResourceBundle {
  public:
   explicit ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) {
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index bf938d1..f78ca19 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -15,6 +15,14 @@
 
 #define LOG_TAG "NativeConverter"
 
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+
 #include "IcuUtilities.h"
 #include "JNIHelp.h"
 #include "JniConstants.h"
@@ -23,7 +31,6 @@
 #include "ScopedPrimitiveArray.h"
 #include "ScopedStringChars.h"
 #include "ScopedUtfChars.h"
-#include "cutils/log.h"
 #include "toStringArray.h"
 #include "unicode/ucnv.h"
 #include "unicode/ucnv_cb.h"
@@ -31,12 +38,6 @@
 #include "unicode/ustring.h"
 #include "unicode/utypes.h"
 
-#include <memory>
-#include <vector>
-
-#include <stdlib.h>
-#include <string.h>
-
 #define NativeConverter_REPORT 0
 #define NativeConverter_IGNORE 1
 #define NativeConverter_REPLACE 2
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index d0b3924..f8fd199 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -16,20 +16,6 @@
 
 #define LOG_TAG "Posix"
 
-#include "AsynchronousCloseMonitor.h"
-#include "cutils/log.h"
-#include "ExecStrings.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "NetworkUtilities.h"
-#include "Portability.h"
-#include "ScopedBytes.h"
-#include "ScopedLocalRef.h"
-#include "ScopedPrimitiveArray.h"
-#include "ScopedUtfChars.h"
-#include "toStringArray.h"
-
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -58,11 +44,26 @@
 #include <sys/xattr.h>
 #include <termios.h>
 #include <unistd.h>
+
 #include <memory>
 
+#include <android/log.h>
 #include <android-base/file.h>
 #include <android-base/strings.h>
 
+#include "AsynchronousCloseMonitor.h"
+#include "ExecStrings.h"
+#include "JNIHelp.h"
+#include "JniConstants.h"
+#include "JniException.h"
+#include "NetworkUtilities.h"
+#include "Portability.h"
+#include "ScopedBytes.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+#include "toStringArray.h"
+
 #ifndef __unused
 #define __unused __attribute__((__unused__))
 #endif
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index e27af69..aaf3ca1 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -16,6 +16,14 @@
 
 #define LOG_TAG "ExpatParser"
 
+#include <expat.h>
+#include <string.h>
+
+#include <memory>
+
+#include <android/log.h>
+#include <android-base/stringprintf.h>
+
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "JniException.h"
@@ -24,15 +32,8 @@
 #include "ScopedStringChars.h"
 #include "ScopedUtfChars.h"
 #include "jni.h"
-#include "cutils/log.h"
 #include "unicode/unistr.h"
 
-#include <memory>
-
-#include <string.h>
-#include <expat.h>
-
-#include <android-base/stringprintf.h>
 
 #define BUCKET_COUNT 128
 
diff --git a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
index bc4fe80..9254b8d 100644
--- a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
+++ b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
@@ -17,7 +17,6 @@
 package libcore.java.lang;
 
 import android.system.Os;
-
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -38,13 +37,13 @@
 import java.util.concurrent.FutureTask;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import junit.framework.TestCase;
 import libcore.io.IoUtils;
-import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
 
 import static java.lang.ProcessBuilder.Redirect.INHERIT;
 import static java.lang.ProcessBuilder.Redirect.PIPE;
 
-public class ProcessBuilderTest extends AbstractResourceLeakageDetectorTestCase {
+public class ProcessBuilderTest extends TestCase {
     private static final String TAG = ProcessBuilderTest.class.getSimpleName();
 
     private static String shell() {
diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java
new file mode 100644
index 0000000..8e215ab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.text;
+
+import junit.framework.TestCase;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateFormatTest extends TestCase {
+
+    // Regression test for http://b/31762542. If this test fails it implies that changes to
+    // DateFormat.is24Hour will not be effective.
+    public void testIs24Hour_notCached() throws Exception {
+        Boolean originalIs24Hour = DateFormat.is24Hour;
+        try {
+            // These tests hardcode expectations for Locale.US.
+            DateFormat.is24Hour = null; // null == locale default (12 hour for US)
+            checkTimePattern(DateFormat.SHORT, "h:mm a");
+            checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+
+            DateFormat.is24Hour = true; // Explicit 24 hour.
+            checkTimePattern(DateFormat.SHORT, "HH:mm");
+            checkTimePattern(DateFormat.MEDIUM, "HH:mm:ss");
+
+            DateFormat.is24Hour = false; // Explicit 12 hour.
+            checkTimePattern(DateFormat.SHORT, "h:mm a");
+            checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+        } finally {
+            DateFormat.is24Hour = originalIs24Hour;
+        }
+    }
+
+    private static void checkTimePattern(int style, String expectedPattern) {
+        final Locale locale = Locale.US;
+        final Date current = new Date(1468250177000L); // 20160711 15:16:17 GMT
+        DateFormat format = DateFormat.getTimeInstance(style, locale);
+        String actualDateString = format.format(current);
+        SimpleDateFormat sdf = new SimpleDateFormat(expectedPattern, locale);
+        String expectedDateString = sdf.format(current);
+        assertEquals(expectedDateString, actualDateString);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java b/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
deleted file mode 100644
index 5ea67d3..0000000
--- a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-/**
- * Ensures that resources used within a test are cleaned up; will detect problems with tests and
- * also with runtime.
- */
-public abstract class AbstractResourceLeakageDetectorTestCase extends TestCase {
-  /**
-   * The leakage detector.
-   */
-  private ResourceLeakageDetector detector;
-
-  @Override
-  protected void setUp() throws Exception {
-    detector = ResourceLeakageDetector.newDetector();
-  }
-
-  @Override
-  protected void tearDown() throws Exception {
-    // If available check for resource leakage. At this point it is impossible to determine
-    // whether the test has thrown an exception. If it has then the exception thrown by this
-    // could hide that test failure; it largely depends on the test runner.
-    if (detector != null) {
-      detector.checkForLeaks();
-    }
-  }
-}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
deleted file mode 100644
index 954665a..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-/**
- * Detects resource leakages for resources that are protected by <code>CloseGuard</code> mechanism.
- *
- * <p>If multiple instances of this are active at the same time, i.e. have been created but not yet
- * had their {@link #checkForLeaks()} method called then while they will report all the leakages
- * detected they may report the leakages caused by the code being tested by another detector.
- *
- * <p>The underlying CloseGuardMonitor is loaded using reflection to ensure that this will run,
- * albeit doing nothing, on the reference implementation.
- */
-public class ResourceLeakageDetector {
-  /** The class for the CloseGuardMonitor, null if not supported. */
-  private static final Class<?> CLOSE_GUARD_MONITOR_CLASS;
-
-  static {
-    ClassLoader classLoader = ResourceLeakageDetector.class.getClassLoader();
-    Class<?> clazz;
-    try {
-      // Make sure that the CloseGuard class exists; this ensures that this is not running
-      // on a RI JVM.
-      classLoader.loadClass("dalvik.system.CloseGuard");
-
-      // Load the monitor class for later instantiation.
-      clazz = classLoader.loadClass("dalvik.system.CloseGuardMonitor");
-
-    } catch (ClassNotFoundException e) {
-      System.err.println("Resource leakage will not be detected; "
-          + "this is expected in the reference implementation");
-      e.printStackTrace(System.err);
-
-      // Ignore, probably running in reference implementation.
-      clazz = null;
-    }
-
-    CLOSE_GUARD_MONITOR_CLASS = clazz;
-  }
-
-  /**
-   * The underlying CloseGuardMonitor that will perform the post test checks for resource
-   * leakage.
-   */
-  private Runnable postTestChecker;
-
-  /**
-   * Create a new detector.
-   *
-   * @return The new {@link ResourceLeakageDetector}, its {@link #checkForLeaks()} method must be
-   * called otherwise it will not clean up properly after itself.
-   */
-  public static ResourceLeakageDetector newDetector()
-      throws Exception {
-    return new ResourceLeakageDetector();
-  }
-
-  private ResourceLeakageDetector()
-      throws Exception {
-    if (CLOSE_GUARD_MONITOR_CLASS != null) {
-      postTestChecker = (Runnable) CLOSE_GUARD_MONITOR_CLASS.newInstance();
-    }
-  }
-
-  /**
-   * Detect any leaks that have arisen since this was created.
-   *
-   * @throws Exception If any leaks were detected.
-   */
-  public void checkForLeaks() throws Exception {
-    // If available check for resource leakage.
-    if (postTestChecker != null) {
-      postTestChecker.run();
-    }
-  }
-}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
deleted file mode 100644
index 5509f73..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 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 dalvik.system.CloseGuard;
-import junit.framework.TestCase;
-
-/**
- * Test for {@link ResourceLeakageDetector}
- */
-public class ResourceLeakageDetectorTest extends TestCase {
-  /**
-   * This test will not work on RI as it does not support the <code>CloseGuard</code> or similar
-   * mechanism.
-   */
-  // TODO(paulduffin): b/31542223 - Work out why this is failing in CTS, fix and reenable.
-  public void notestDetectsUnclosedCloseGuard() throws Exception {
-    ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
-    try {
-      CloseGuard closeGuard = createCloseGuard();
-      closeGuard.open("open");
-    } finally {
-      boolean leaksDetected = true;
-      try {
-        System.logI("Checking for leaks");
-        detector.checkForLeaks();
-        leaksDetected = false;
-      } catch (AssertionError expected) {
-        // The leak detector should throw this error.
-      }
-
-      if (!leaksDetected) {
-        fail("Did not detect any leaks");
-      }
-    }
-  }
-
-  public void testIgnoresClosedCloseGuard() throws Exception {
-    ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
-    try {
-      CloseGuard closeGuard = createCloseGuard();
-      closeGuard.open("open");
-      closeGuard.close();
-    } finally {
-      detector.checkForLeaks();
-    }
-  }
-
-  /**
-   * Private method to ensure that the CloseGuard object is garbage collected.
-   */
-  private CloseGuard createCloseGuard() {
-    final CloseGuard closeGuard = CloseGuard.get();
-    new Object() {
-      @Override
-      protected void finalize() throws Throwable {
-        try {
-          closeGuard.warnIfOpen();
-        } finally {
-          super.finalize();
-        }
-      }
-    };
-
-    return closeGuard;
-  }
-}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index 61c6d03..9c562ee 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
@@ -531,7 +531,7 @@
         try {
             uc2.getInputStream();
             fail();
-        } catch (Throwable expected) {
+        } catch (IOException expected) {
         }
     }
 
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 0d66339..f562fe4 100644
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -1832,6 +1832,8 @@
         throws IOException
     {
         SerialCallbackContext oldContext = curContext;
+        if (oldContext != null)
+            oldContext.check();
         curContext = null;
         try {
             boolean blocked = desc.hasBlockExternalData();
@@ -1856,6 +1858,8 @@
                 skipCustomData();
             }
         } finally {
+            if (oldContext != null)
+                oldContext.check();
             curContext = oldContext;
         }
         /*
@@ -1884,13 +1888,14 @@
         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
         for (int i = 0; i < slots.length; i++) {
             ObjectStreamClass slotDesc = slots[i].desc;
-            if (slots[i].hasData) {
-                if (obj != null &&
-                    slotDesc.hasReadObjectMethod() &&
-                    handles.lookupException(passHandle) == null)
-                {
-                    SerialCallbackContext oldContext = curContext;
 
+            if (slots[i].hasData) {
+                if (obj == null || handles.lookupException(passHandle) != null) {
+                    defaultReadFields(null, slotDesc); // skip field values
+                } else if (slotDesc.hasReadObjectMethod()) {
+                    SerialCallbackContext oldContext = curContext;
+                    if (oldContext != null)
+                        oldContext.check();
                     try {
                         curContext = new SerialCallbackContext(obj, slotDesc);
 
@@ -1907,6 +1912,8 @@
                         handles.markException(passHandle, ex);
                     } finally {
                         curContext.setUsed();
+                        if (oldContext!= null)
+                            oldContext.check();
                         curContext = oldContext;
                     }
 
@@ -1919,6 +1926,7 @@
                 } else {
                     defaultReadFields(obj, slotDesc);
                 }
+
                 if (slotDesc.hasWriteObjectData()) {
                     skipCustomData();
                 } else {
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index 5de2175..1503112 100644
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -1298,7 +1298,7 @@
         }
 
         bout.setBlockDataMode(true);
-        if (isCustomSubclass()) {
+        if (cl != null && isCustomSubclass()) {
             ReflectUtil.checkPackageAccess(cl);
         }
         annotateProxyClass(cl);
@@ -1327,7 +1327,7 @@
 
         Class<?> cl = desc.forClass();
         bout.setBlockDataMode(true);
-        if (isCustomSubclass()) {
+        if (cl != null && isCustomSubclass()) {
             ReflectUtil.checkPackageAccess(cl);
         }
         annotateClass(cl);
@@ -1562,7 +1562,11 @@
     private void defaultWriteFields(Object obj, ObjectStreamClass desc)
         throws IOException
     {
-        // REMIND: perform conservative isInstance check here?
+        Class<?> cl = desc.forClass();
+        if (cl != null && obj != null && !cl.isInstance(obj)) {
+            throw new ClassCastException();
+        }
+
         desc.checkDefaultSerialize();
 
         int primDataSize = desc.getPrimDataSize();
diff --git a/ojluni/src/main/java/java/io/PipedInputStream.java b/ojluni/src/main/java/java/io/PipedInputStream.java
index 66cf19d..d7fb790 100644
--- a/ojluni/src/main/java/java/io/PipedInputStream.java
+++ b/ojluni/src/main/java/java/io/PipedInputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, 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
@@ -45,7 +45,7 @@
  * The piped input stream contains a buffer,
  * decoupling read operations from write operations,
  * within limits.
- * A pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a
+ * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
  * thread that was providing data bytes to the connected
  * piped output stream is no longer alive.
  *
@@ -123,7 +123,7 @@
      * @param      src   the stream to connect to.
      * @param      pipeSize the size of the pipe's buffer.
      * @exception  IOException  if an I/O error occurs.
-     * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
+     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
      * @since      1.6
      */
     public PipedInputStream(PipedOutputStream src, int pipeSize)
@@ -153,7 +153,7 @@
      * connected} to a <code>PipedOutputStream</code> before being used.
      *
      * @param      pipeSize the size of the pipe's buffer.
-     * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
+     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
      * @since      1.6
      */
     public PipedInputStream(int pipeSize) {
@@ -178,15 +178,14 @@
      * unconnected piped output stream and <code>snk</code>
      * is an unconnected piped input stream, they
      * may be connected by either the call:
-     * <p>
+     *
      * <pre><code>snk.connect(src)</code> </pre>
      * <p>
      * or the call:
-     * <p>
+     *
      * <pre><code>src.connect(snk)</code> </pre>
      * <p>
-     * The two
-     * calls have the same effect.
+     * The two calls have the same effect.
      *
      * @param      src   The piped output stream to connect to.
      * @exception  IOException  if an I/O error occurs.
@@ -199,7 +198,7 @@
      * Receives a byte of data.  This method will block if no input is
      * available.
      * @param b the byte being received
-     * @exception IOException If the pipe is <a href=#BROKEN> <code>broken</code></a>,
+     * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
      *          {@link #connect(java.io.PipedOutputStream) unconnected},
      *          closed, or if an I/O error occurs.
      * @since     JDK1.1
@@ -225,7 +224,7 @@
      * @param b the buffer into which the data is received
      * @param off the start offset of the data
      * @param len the maximum number of bytes received
-     * @exception IOException If the pipe is <a href=#BROKEN> broken</a>,
+     * @exception IOException If the pipe is <a href="#BROKEN"> broken</a>,
      *           {@link #connect(java.io.PipedOutputStream) unconnected},
      *           closed,or if an I/O error occurs.
      */
@@ -309,7 +308,7 @@
      *             stream is reached.
      * @exception  IOException  if the pipe is
      *           {@link #connect(java.io.PipedOutputStream) unconnected},
-     *           <a href=#BROKEN> <code>broken</code></a>, closed,
+     *           <a href="#BROKEN"> <code>broken</code></a>, closed,
      *           or if an I/O error occurs.
      */
     public synchronized int read()  throws IOException {
@@ -377,7 +376,7 @@
      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
      * <code>len</code> is negative, or <code>len</code> is greater than
      * <code>b.length - off</code>
-     * @exception  IOException if the pipe is <a href=#BROKEN> <code>broken</code></a>,
+     * @exception  IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,
      *           {@link #connect(java.io.PipedOutputStream) unconnected},
      *           closed, or if an I/O error occurs.
      */
@@ -435,7 +434,7 @@
      *         without blocking, or {@code 0} if this input stream has been
      *         closed by invoking its {@link #close()} method, or if the pipe
      *         is {@link #connect(java.io.PipedOutputStream) unconnected}, or
-     *          <a href=#BROKEN> <code>broken</code></a>.
+     *          <a href="#BROKEN"> <code>broken</code></a>.
      *
      * @exception  IOException  if an I/O error occurs.
      * @since   JDK1.0.2
diff --git a/ojluni/src/main/java/java/io/PipedReader.java b/ojluni/src/main/java/java/io/PipedReader.java
index 93b7205..e4ec566 100644
--- a/ojluni/src/main/java/java/io/PipedReader.java
+++ b/ojluni/src/main/java/java/io/PipedReader.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2006, 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
@@ -96,7 +96,7 @@
      * @param      src       the stream to connect to.
      * @param      pipeSize  the size of the pipe's buffer.
      * @exception  IOException  if an I/O error occurs.
-     * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
+     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
      * @since      1.6
      */
     public PipedReader(PipedWriter src, int pipeSize) throws IOException {
@@ -125,7 +125,7 @@
      * before being used.
      *
      * @param   pipeSize the size of the pipe's buffer.
-     * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
+     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
      * @since      1.6
      */
     public PipedReader(int pipeSize) {
@@ -150,15 +150,14 @@
      * unconnected piped writer and <code>snk</code>
      * is an unconnected piped reader, they
      * may be connected by either the call:
-     * <p>
+     *
      * <pre><code>snk.connect(src)</code> </pre>
      * <p>
      * or the call:
-     * <p>
+     *
      * <pre><code>src.connect(snk)</code> </pre>
      * <p>
-     * The two
-     * calls have the same effect.
+     * The two calls have the same effect.
      *
      * @param      src   The piped writer to connect to.
      * @exception  IOException  if an I/O error occurs.
diff --git a/ojluni/src/main/java/java/io/PrintStream.java b/ojluni/src/main/java/java/io/PrintStream.java
index 6968527..08bb3a3 100644
--- a/ojluni/src/main/java/java/io/PrintStream.java
+++ b/ojluni/src/main/java/java/io/PrintStream.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
@@ -302,7 +302,7 @@
      *          creating the file
      *
      * @throws  SecurityException
-     *          If a security manager is presentand {@link
+     *          If a security manager is present and {@link
      *          SecurityManager#checkWrite checkWrite(file.getPath())}
      *          denies write access to the file
      *
@@ -869,7 +869,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -919,7 +919,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -962,7 +962,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -1019,7 +1019,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PrintWriter.java b/ojluni/src/main/java/java/io/PrintWriter.java
index 102c3a2..9287a19 100644
--- a/ojluni/src/main/java/java/io/PrintWriter.java
+++ b/ojluni/src/main/java/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -784,7 +784,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -835,7 +835,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -879,7 +879,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -939,7 +939,7 @@
      *         <tt>null</tt> argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PushbackInputStream.java b/ojluni/src/main/java/java/io/PushbackInputStream.java
index af0b525..b44848d 100644
--- a/ojluni/src/main/java/java/io/PushbackInputStream.java
+++ b/ojluni/src/main/java/java/io/PushbackInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -85,7 +85,7 @@
      *
      * @param  in    the input stream from which bytes will be read.
      * @param  size  the size of the pushback buffer.
-     * @exception IllegalArgumentException if size is <= 0
+     * @exception IllegalArgumentException if {@code size <= 0}
      * @since  JDK1.1
      */
     public PushbackInputStream(InputStream in, int size) {
diff --git a/ojluni/src/main/java/java/io/PushbackReader.java b/ojluni/src/main/java/java/io/PushbackReader.java
index 2f5b18c..f918621 100644
--- a/ojluni/src/main/java/java/io/PushbackReader.java
+++ b/ojluni/src/main/java/java/io/PushbackReader.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -47,7 +47,7 @@
      *
      * @param   in   The reader from which characters will be read
      * @param   size The size of the pushback buffer
-     * @exception IllegalArgumentException if size is <= 0
+     * @exception IllegalArgumentException if {@code size <= 0}
      */
     public PushbackReader(Reader in, int size) {
         super(in);
diff --git a/ojluni/src/main/java/java/io/Reader.java b/ojluni/src/main/java/java/io/Reader.java
index e2248c4..1c9cca6 100644
--- a/ojluni/src/main/java/java/io/Reader.java
+++ b/ojluni/src/main/java/java/io/Reader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
      *         -1 if this source of characters is at its end
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if target is null
-     * @throws ReadOnlyBufferException if target is a read only buffer
+     * @throws java.nio.ReadOnlyBufferException if target is a read only buffer
      * @since 1.5
      */
     public int read(java.nio.CharBuffer target) throws IOException {
diff --git a/ojluni/src/main/java/java/io/SerialCallbackContext.java b/ojluni/src/main/java/java/io/SerialCallbackContext.java
index 748d38e..4009087 100644
--- a/ojluni/src/main/java/java/io/SerialCallbackContext.java
+++ b/ojluni/src/main/java/java/io/SerialCallbackContext.java
@@ -60,6 +60,13 @@
         return desc;
     }
 
+    public void check() throws NotActiveException {
+        if (thread != null && thread != Thread.currentThread()) {
+            throw new NotActiveException(
+                "expected thread: " + thread + ", but got: " + Thread.currentThread());
+        }
+    }
+
     private void checkAndSetUsed() throws NotActiveException {
         if (thread != Thread.currentThread()) {
              throw new NotActiveException(
diff --git a/ojluni/src/main/java/java/io/Serializable.java b/ojluni/src/main/java/java/io/Serializable.java
index 83bfe03..96ea33c 100644
--- a/ojluni/src/main/java/java/io/Serializable.java
+++ b/ojluni/src/main/java/java/io/Serializable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, 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
@@ -55,7 +55,7 @@
  *
  * Classes that require special handling during the serialization and
  * deserialization process must implement special methods with these exact
- * signatures: <p>
+ * signatures:
  *
  * <PRE>
  * private void writeObject(java.io.ObjectOutputStream out)
@@ -101,7 +101,7 @@
  *
  * <p>Serializable classes that need to designate an alternative object to be
  * used when writing an object to the stream should implement this
- * special method with the exact signature: <p>
+ * special method with the exact signature:
  *
  * <PRE>
  * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
@@ -115,7 +115,7 @@
  *
  * Classes that need to designate a replacement when an instance of it
  * is read from the stream should implement this special method with the
- * exact signature.<p>
+ * exact signature.
  *
  * <PRE>
  * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
@@ -133,7 +133,7 @@
  * deserialization will result in an {@link InvalidClassException}.  A
  * serializable class can declare its own serialVersionUID explicitly by
  * declaring a field named <code>"serialVersionUID"</code> that must be static,
- * final, and of type <code>long</code>:<p>
+ * final, and of type <code>long</code>:
  *
  * <PRE>
  * ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
diff --git a/ojluni/src/main/java/java/io/SerializablePermission.java b/ojluni/src/main/java/java/io/SerializablePermission.java
index ab1ccf4..e11f3ee 100644
--- a/ojluni/src/main/java/java/io/SerializablePermission.java
+++ b/ojluni/src/main/java/java/io/SerializablePermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2005, 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
diff --git a/ojluni/src/main/java/java/io/StreamTokenizer.java b/ojluni/src/main/java/java/io/StreamTokenizer.java
index 81ec5d5..3c7c7cc 100644
--- a/ojluni/src/main/java/java/io/StreamTokenizer.java
+++ b/ojluni/src/main/java/java/io/StreamTokenizer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -28,7 +28,7 @@
 import java.util.Arrays;
 
 /**
- * The <code>StreamTokenizer</code> class takes an input stream and
+ * The {@code StreamTokenizer} class takes an input stream and
  * parses it into "tokens", allowing the tokens to be
  * read one at a time. The parsing process is controlled by a table
  * and a number of flags that can be set to various states. The
@@ -36,7 +36,7 @@
  * strings, and various comment styles.
  * <p>
  * Each byte read from the input stream is regarded as a character
- * in the range <code>'&#92;u0000'</code> through <code>'&#92;u00FF'</code>.
+ * in the range {@code '\u005Cu0000'} through {@code '\u005Cu00FF'}.
  * The character value is used to look up five possible attributes of
  * the character: <i>white space</i>, <i>alphabetic</i>,
  * <i>numeric</i>, <i>string quote</i>, and <i>comment character</i>.
@@ -53,8 +53,8 @@
  * <p>
  * A typical application first constructs an instance of this class,
  * sets up the syntax tables, and then repeatedly loops calling the
- * <code>nextToken</code> method in each iteration of the loop until
- * it returns the value <code>TT_EOF</code>.
+ * {@code nextToken} method in each iteration of the loop until
+ * it returns the value {@code TT_EOF}.
  *
  * @author  James Gosling
  * @see     java.io.StreamTokenizer#nextToken()
@@ -99,19 +99,19 @@
     private static final byte CT_COMMENT = 16;
 
     /**
-     * After a call to the <code>nextToken</code> method, this field
+     * After a call to the {@code nextToken} method, this field
      * contains the type of the token just read. For a single character
      * token, its value is the single character, converted to an integer.
      * For a quoted string token, its value is the quote character.
      * Otherwise, its value is one of the following:
      * <ul>
-     * <li><code>TT_WORD</code> indicates that the token is a word.
-     * <li><code>TT_NUMBER</code> indicates that the token is a number.
-     * <li><code>TT_EOL</code> indicates that the end of line has been read.
+     * <li>{@code TT_WORD} indicates that the token is a word.
+     * <li>{@code TT_NUMBER} indicates that the token is a number.
+     * <li>{@code TT_EOL} indicates that the end of line has been read.
      *     The field can only have this value if the
-     *     <code>eolIsSignificant</code> method has been called with the
-     *     argument <code>true</code>.
-     * <li><code>TT_EOF</code> indicates that the end of the input stream
+     *     {@code eolIsSignificant} method has been called with the
+     *     argument {@code true}.
+     * <li>{@code TT_EOF} indicates that the end of the input stream
      *     has been reached.
      * </ul>
      * <p>
@@ -160,8 +160,8 @@
      * the string.
      * <p>
      * The current token is a word when the value of the
-     * <code>ttype</code> field is <code>TT_WORD</code>. The current token is
-     * a quoted string token when the value of the <code>ttype</code> field is
+     * {@code ttype} field is {@code TT_WORD}. The current token is
+     * a quoted string token when the value of the {@code ttype} field is
      * a quote character.
      * <p>
      * The initial value of this field is null.
@@ -175,7 +175,7 @@
     /**
      * If the current token is a number, this field contains the value
      * of that number. The current token is a number when the value of
-     * the <code>ttype</code> field is <code>TT_NUMBER</code>.
+     * the {@code ttype} field is {@code TT_NUMBER}.
      * <p>
      * The initial value of this field is 0.0.
      *
@@ -201,14 +201,14 @@
      * stream. The stream tokenizer is initialized to the following
      * default state:
      * <ul>
-     * <li>All byte values <code>'A'</code> through <code>'Z'</code>,
-     *     <code>'a'</code> through <code>'z'</code>, and
-     *     <code>'&#92;u00A0'</code> through <code>'&#92;u00FF'</code> are
+     * <li>All byte values {@code 'A'} through {@code 'Z'},
+     *     {@code 'a'} through {@code 'z'}, and
+     *     {@code '\u005Cu00A0'} through {@code '\u005Cu00FF'} are
      *     considered to be alphabetic.
-     * <li>All byte values <code>'&#92;u0000'</code> through
-     *     <code>'&#92;u0020'</code> are considered to be white space.
-     * <li><code>'/'</code> is a comment character.
-     * <li>Single quote <code>'&#92;''</code> and double quote <code>'"'</code>
+     * <li>All byte values {@code '\u005Cu0000'} through
+     *     {@code '\u005Cu0020'} are considered to be white space.
+     * <li>{@code '/'} is a comment character.
+     * <li>Single quote {@code '\u005C''} and double quote {@code '"'}
      *     are string quote characters.
      * <li>Numbers are parsed.
      * <li>Ends of lines are treated as white space, not as separate tokens.
@@ -252,7 +252,7 @@
 
     /**
      * Resets this tokenizer's syntax table so that all characters are
-     * "ordinary." See the <code>ordinaryChar</code> method
+     * "ordinary." See the {@code ordinaryChar} method
      * for more information on a character being ordinary.
      *
      * @see     java.io.StreamTokenizer#ordinaryChar(int)
@@ -305,7 +305,7 @@
      * Specifies that all characters <i>c</i> in the range
      * <code>low&nbsp;&lt;=&nbsp;<i>c</i>&nbsp;&lt;=&nbsp;high</code>
      * are "ordinary" in this tokenizer. See the
-     * <code>ordinaryChar</code> method for more information on a
+     * {@code ordinaryChar} method for more information on a
      * character being ordinary.
      *
      * @param   low   the low end of the range.
@@ -327,12 +327,12 @@
      * character has as a comment character, word component, string
      * delimiter, white space, or number character. When such a character
      * is encountered by the parser, the parser treats it as a
-     * single-character token and sets <code>ttype</code> field to the
+     * single-character token and sets {@code ttype} field to the
      * character value.
      *
      * <p>Making a line terminator character "ordinary" may interfere
-     * with the ability of a <code>StreamTokenizer</code> to count
-     * lines. The <code>lineno</code> method may no longer reflect
+     * with the ability of a {@code StreamTokenizer} to count
+     * lines. The {@code lineno} method may no longer reflect
      * the presence of such terminator characters in its line count.
      *
      * @param   ch   the character.
@@ -361,9 +361,9 @@
      * Specifies that matching pairs of this character delimit string
      * constants in this tokenizer.
      * <p>
-     * When the <code>nextToken</code> method encounters a string
-     * constant, the <code>ttype</code> field is set to the string
-     * delimiter and the <code>sval</code> field is set to the body of
+     * When the {@code nextToken} method encounters a string
+     * constant, the {@code ttype} field is set to the string
+     * delimiter and the {@code sval} field is set to the body of
      * the string.
      * <p>
      * If a string quote character is encountered, then a string is
@@ -371,7 +371,7 @@
      * the string quote character, up to (but not including) the next
      * occurrence of that same string quote character, or a line
      * terminator, or end of file. The usual escape sequences such as
-     * <code>"&#92;n"</code> and <code>"&#92;t"</code> are recognized and
+     * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and
      * converted to single characters as the string is parsed.
      *
      * <p>Any other attribute settings for the specified character are cleared.
@@ -398,9 +398,9 @@
      * <p>
      * When the parser encounters a word token that has the format of a
      * double precision floating-point number, it treats the token as a
-     * number rather than a word, by setting the <code>ttype</code>
-     * field to the value <code>TT_NUMBER</code> and putting the numeric
-     * value of the token into the <code>nval</code> field.
+     * number rather than a word, by setting the {@code ttype}
+     * field to the value {@code TT_NUMBER} and putting the numeric
+     * value of the token into the {@code nval} field.
      *
      * @see     java.io.StreamTokenizer#nval
      * @see     java.io.StreamTokenizer#TT_NUMBER
@@ -416,21 +416,21 @@
     /**
      * Determines whether or not ends of line are treated as tokens.
      * If the flag argument is true, this tokenizer treats end of lines
-     * as tokens; the <code>nextToken</code> method returns
-     * <code>TT_EOL</code> and also sets the <code>ttype</code> field to
+     * as tokens; the {@code nextToken} method returns
+     * {@code TT_EOL} and also sets the {@code ttype} field to
      * this value when an end of line is read.
      * <p>
      * A line is a sequence of characters ending with either a
-     * carriage-return character (<code>'&#92;r'</code>) or a newline
-     * character (<code>'&#92;n'</code>). In addition, a carriage-return
+     * carriage-return character ({@code '\u005Cr'}) or a newline
+     * character ({@code '\u005Cn'}). In addition, a carriage-return
      * character followed immediately by a newline character is treated
      * as a single end-of-line token.
      * <p>
-     * If the <code>flag</code> is false, end-of-line characters are
+     * If the {@code flag} is false, end-of-line characters are
      * treated as white space and serve only to separate tokens.
      *
-     * @param   flag   <code>true</code> indicates that end-of-line characters
-     *                 are separate tokens; <code>false</code> indicates that
+     * @param   flag   {@code true} indicates that end-of-line characters
+     *                 are separate tokens; {@code false} indicates that
      *                 end-of-line characters are white space.
      * @see     java.io.StreamTokenizer#nextToken()
      * @see     java.io.StreamTokenizer#ttype
@@ -442,14 +442,14 @@
 
     /**
      * Determines whether or not the tokenizer recognizes C-style comments.
-     * If the flag argument is <code>true</code>, this stream tokenizer
+     * If the flag argument is {@code true}, this stream tokenizer
      * recognizes C-style comments. All text between successive
-     * occurrences of <code>/*</code> and <code>*&#47;</code> are discarded.
+     * occurrences of {@code /*} and <code>*&#47;</code> are discarded.
      * <p>
-     * If the flag argument is <code>false</code>, then C-style comments
+     * If the flag argument is {@code false}, then C-style comments
      * are not treated specially.
      *
-     * @param   flag   <code>true</code> indicates to recognize and ignore
+     * @param   flag   {@code true} indicates to recognize and ignore
      *                 C-style comments.
      */
     public void slashStarComments(boolean flag) {
@@ -458,15 +458,15 @@
 
     /**
      * Determines whether or not the tokenizer recognizes C++-style comments.
-     * If the flag argument is <code>true</code>, this stream tokenizer
+     * If the flag argument is {@code true}, this stream tokenizer
      * recognizes C++-style comments. Any occurrence of two consecutive
-     * slash characters (<code>'/'</code>) is treated as the beginning of
+     * slash characters ({@code '/'}) is treated as the beginning of
      * a comment that extends to the end of the line.
      * <p>
-     * If the flag argument is <code>false</code>, then C++-style
+     * If the flag argument is {@code false}, then C++-style
      * comments are not treated specially.
      *
-     * @param   flag   <code>true</code> indicates to recognize and ignore
+     * @param   flag   {@code true} indicates to recognize and ignore
      *                 C++-style comments.
      */
     public void slashSlashComments(boolean flag) {
@@ -475,16 +475,16 @@
 
     /**
      * Determines whether or not word token are automatically lowercased.
-     * If the flag argument is <code>true</code>, then the value in the
-     * <code>sval</code> field is lowercased whenever a word token is
-     * returned (the <code>ttype</code> field has the
-     * value <code>TT_WORD</code> by the <code>nextToken</code> method
+     * If the flag argument is {@code true}, then the value in the
+     * {@code sval} field is lowercased whenever a word token is
+     * returned (the {@code ttype} field has the
+     * value {@code TT_WORD} by the {@code nextToken} method
      * of this tokenizer.
      * <p>
-     * If the flag argument is <code>false</code>, then the
-     * <code>sval</code> field is not modified.
+     * If the flag argument is {@code false}, then the
+     * {@code sval} field is not modified.
      *
-     * @param   fl   <code>true</code> indicates that all word tokens should
+     * @param   fl   {@code true} indicates that all word tokens should
      *               be lowercased.
      * @see     java.io.StreamTokenizer#nextToken()
      * @see     java.io.StreamTokenizer#ttype
@@ -506,9 +506,9 @@
 
     /**
      * Parses the next token from the input stream of this tokenizer.
-     * The type of the next token is returned in the <code>ttype</code>
+     * The type of the next token is returned in the {@code ttype}
      * field. Additional information about the token may be in the
-     * <code>nval</code> field or the <code>sval</code> field of this
+     * {@code nval} field or the {@code sval} field of this
      * tokenizer.
      * <p>
      * Typical clients of this
@@ -516,7 +516,7 @@
      * calling nextToken to parse successive tokens until TT_EOF
      * is returned.
      *
-     * @return     the value of the <code>ttype</code> field.
+     * @return     the value of the {@code ttype} field.
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.StreamTokenizer#nval
      * @see        java.io.StreamTokenizer#sval
@@ -752,10 +752,10 @@
     }
 
     /**
-     * Causes the next call to the <code>nextToken</code> method of this
-     * tokenizer to return the current value in the <code>ttype</code>
-     * field, and not to modify the value in the <code>nval</code> or
-     * <code>sval</code> field.
+     * Causes the next call to the {@code nextToken} method of this
+     * tokenizer to return the current value in the {@code ttype}
+     * field, and not to modify the value in the {@code nval} or
+     * {@code sval} field.
      *
      * @see     java.io.StreamTokenizer#nextToken()
      * @see     java.io.StreamTokenizer#nval
diff --git a/ojluni/src/main/java/java/io/StringReader.java b/ojluni/src/main/java/java/io/StringReader.java
index 3778408..ce9ff60 100644
--- a/ojluni/src/main/java/java/io/StringReader.java
+++ b/ojluni/src/main/java/java/io/StringReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, 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
@@ -163,7 +163,7 @@
      *                         is no actual limit, so this argument must not
      *                         be negative, but is otherwise ignored.
      *
-     * @exception  IllegalArgumentException  If readAheadLimit is < 0
+     * @exception  IllegalArgumentException  If {@code readAheadLimit < 0}
      * @exception  IOException  If an I/O error occurs
      */
     public void mark(int readAheadLimit) throws IOException {
diff --git a/ojluni/src/main/java/java/io/UnixFileSystem.java b/ojluni/src/main/java/java/io/UnixFileSystem.java
index 6ce3f6f..1659b17 100644
--- a/ojluni/src/main/java/java/io/UnixFileSystem.java
+++ b/ojluni/src/main/java/java/io/UnixFileSystem.java
@@ -236,6 +236,7 @@
 
     private native int getBooleanAttributes0(String abspath);
 
+    // Android-changed: Added thread policy check
     public int getBooleanAttributes(File f) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
 
@@ -245,43 +246,43 @@
         return rv | (hidden ? BA_HIDDEN : 0);
     }
 
+    // Android-changed: Added thread policy check
     public boolean checkAccess(File f, int access) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
         return checkAccess0(f, access);
     }
-
     private native boolean checkAccess0(File f, int access);
 
+    // Android-changed: Added thread policy check
     public long getLastModifiedTime(File f) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
         return getLastModifiedTime0(f);
     }
-
     private native long getLastModifiedTime0(File f);
 
+    // Android-changed: Added thread policy check
     public long getLength(File f) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
         return getLength0(f);
     }
-
     private native long getLength0(File f);
 
+    // Android-changed: Added thread policy check
     public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
         BlockGuard.getThreadPolicy().onWriteToDisk();
         return setPermission0(f, access, enable, owneronly);
     }
-
     private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
 
     /* -- File operations -- */
-
+    // Android-changed: Added thread policy check
     public boolean createFileExclusively(String path) throws IOException {
         BlockGuard.getThreadPolicy().onWriteToDisk();
         return createFileExclusively0(path);
     }
-
     private native boolean createFileExclusively0(String path) throws IOException;
 
+    // Android-changed: Added thread policy check
     public boolean delete(File f) {
         // Keep canonicalization caches in sync after file deletion
         // and renaming operations. Could be more clever than this
@@ -296,20 +297,21 @@
 
     private native boolean delete0(File f);
 
+    // Android-changed: Added thread policy check
     public String[] list(File f) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
         return list0(f);
     }
-
     private native String[] list0(File f);
 
+    // Android-changed: Added thread policy check
     public boolean createDirectory(File f) {
         BlockGuard.getThreadPolicy().onWriteToDisk();
         return createDirectory0(f);
     }
-
     private native boolean createDirectory0(File f);
 
+    // Android-changed: Added thread policy check
     public boolean rename(File f1, File f2) {
         // Keep canonicalization caches in sync after file deletion
         // and renaming operations. Could be more clever than this
@@ -324,18 +326,18 @@
 
     private native boolean rename0(File f1, File f2);
 
+    // Android-changed: Added thread policy check
     public boolean setLastModifiedTime(File f, long time) {
         BlockGuard.getThreadPolicy().onWriteToDisk();
         return setLastModifiedTime0(f, time);
     }
-
     private native boolean setLastModifiedTime0(File f, long time);
 
+    // Android-changed: Added thread policy check
     public boolean setReadOnly(File f) {
         BlockGuard.getThreadPolicy().onWriteToDisk();
         return setReadOnly0(f);
     }
-
     private native boolean setReadOnly0(File f);
 
 
@@ -354,12 +356,12 @@
     }
 
     /* -- Disk usage -- */
+    // Android-changed: Added thread policy check
     public long getSpace(File f, int t) {
         BlockGuard.getThreadPolicy().onReadFromDisk();
 
         return getSpace0(f, t);
     }
-
     private native long getSpace0(File f, int t);
 
     /* -- Basic infrastructure -- */
diff --git a/ojluni/src/main/java/java/io/Writer.java b/ojluni/src/main/java/java/io/Writer.java
index f0c6db4..8747a13 100644
--- a/ojluni/src/main/java/java/io/Writer.java
+++ b/ojluni/src/main/java/java/io/Writer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -57,7 +57,7 @@
     /**
      * Size of writeBuffer, must be >= 1
      */
-    private final int writeBufferSize = 1024;
+    private static final int WRITE_BUFFER_SIZE = 1024;
 
     /**
      * The object used to synchronize operations on this stream.  For
@@ -107,7 +107,7 @@
     public void write(int c) throws IOException {
         synchronized (lock) {
             if (writeBuffer == null){
-                writeBuffer = new char[writeBufferSize];
+                writeBuffer = new char[WRITE_BUFFER_SIZE];
             }
             writeBuffer[0] = (char) c;
             write(writeBuffer, 0, 1);
@@ -180,9 +180,9 @@
     public void write(String str, int off, int len) throws IOException {
         synchronized (lock) {
             char cbuf[];
-            if (len <= writeBufferSize) {
+            if (len <= WRITE_BUFFER_SIZE) {
                 if (writeBuffer == null) {
-                    writeBuffer = new char[writeBufferSize];
+                    writeBuffer = new char[WRITE_BUFFER_SIZE];
                 }
                 cbuf = writeBuffer;
             } else {    // Don't permanently allocate very large buffers.
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
index ef4f7fe..0c27b99 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
@@ -455,16 +455,16 @@
      * field_id in the equivalent instruction.
      */
 
-    /** @hide */ public static final int INVOKE_VIRTUAL = 0x6e;
-    /** @hide */ public static final int INVOKE_SUPER = 0x6f;
-    /** @hide */ public static final int INVOKE_DIRECT = 0x70;
-    /** @hide */ public static final int INVOKE_STATIC = 0x71;
-    /** @hide */ public static final int INVOKE_INTERFACE = 0x72;
+    /** @hide */ public static final int INVOKE_VIRTUAL = 0;
+    /** @hide */ public static final int INVOKE_SUPER = 1;
+    /** @hide */ public static final int INVOKE_DIRECT = 2;
+    /** @hide */ public static final int INVOKE_STATIC = 3;
+    /** @hide */ public static final int INVOKE_INTERFACE = 4;
 
-    /** @hide */ public static final int SGET = 0x60;
-    /** @hide */ public static final int SPUT = 0x67;
-    /** @hide */ public static final int IGET = 0x52;
-    /** @hide */ public static final int IPUT = 0x59;
+    /** @hide */ public static final int SGET = 5;
+    /** @hide */ public static final int SPUT = 6;
+    /** @hide */ public static final int IGET = 7;
+    /** @hide */ public static final int IPUT = 8;
 
     // The kind of this method handle (used by the runtime). This is one of the INVOKE_*
     // constants or SGET/SPUT, IGET/IPUT.
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 203ccb8..3029acc 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -28,13 +28,17 @@
 import android.system.GaiException;
 import android.system.StructAddrinfo;
 import dalvik.system.BlockGuard;
+
+import libcore.io.IoBridge;
 import libcore.io.Libcore;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 
 import static android.system.OsConstants.AF_UNSPEC;
 import static android.system.OsConstants.AI_ADDRCONFIG;
 import static android.system.OsConstants.EACCES;
+import static android.system.OsConstants.ECONNREFUSED;
 import static android.system.OsConstants.SOCK_STREAM;
 
 /*
@@ -140,9 +144,12 @@
 
     @Override
     public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
-        byte[] ifaddr = null;
-        int scope = -1;
-        int netif_scope = -1;
+        // Android-changed: rewritten on the top of IoBridge and Libcore.os
+        // TODO (b/31926888): try ICMP first (http://code.google.com/p/android/issues/detail?id=20106)
+
+        // No good, let's fall back to TCP
+        FileDescriptor fd = IoBridge.socket(true);
+        InetAddress sourceAddr = null;
         if (netif != null) {
             /*
              * Let's make sure we bind to an address of the proper family.
@@ -155,31 +162,32 @@
             while (it.hasMoreElements()) {
                 inetaddr = it.nextElement();
                 if (inetaddr.getClass().isInstance(addr)) {
-                    ifaddr = inetaddr.getAddress();
-                    if (inetaddr instanceof Inet6Address) {
-                        netif_scope = ((Inet6Address) inetaddr).getScopeId();
-                    }
+                    sourceAddr = inetaddr;
                     break;
                 }
             }
-            if (ifaddr == null) {
+
+            if (sourceAddr == null) {
                 // Interface doesn't support the address family of
                 // the destination
                 return false;
             }
         }
-        if (addr instanceof Inet6Address)
-            scope = ((Inet6Address) addr).getScopeId();
 
-        BlockGuard.getThreadPolicy().onNetwork();
-
-        // Never throw an IOException from isReachable. If something terrible happens either
-        // with the network interface in question (or with the destination), then just return
-        // false (i.e, state that the address is unreachable.
         try {
-            return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
-        } catch (IOException ioe) {
-            return false;
+            if (sourceAddr != null) {
+                IoBridge.bind(fd, sourceAddr, 0);
+            }
+            IoBridge.connect(fd, addr, 7 /* Echo-protocol port */, timeout);
+            return true;
+        } catch (IOException e) {
+            // Connection refused by remote (ECONNREFUSED) implies reachable. Otherwise silently
+            // ignore the exception and return false.
+            Throwable cause = e.getCause();
+            return cause instanceof ErrnoException
+                    && ((ErrnoException) cause).errno == ECONNREFUSED;
+        } finally {
+            IoBridge.closeAndSignalBlockedThreads(fd);
         }
     }
 
@@ -216,5 +224,4 @@
     }
 
     private native String getHostByAddr0(byte[] addr) throws UnknownHostException;
-    private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
 }
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index b17245f..de2a93e 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -534,12 +534,6 @@
     private static final String GMT = "GMT";
 
     /**
-     * Cache to hold the DateTimePatterns of a Locale.
-     */
-    private static final ConcurrentMap<Locale, String[]> cachedLocaleData
-        = new ConcurrentHashMap<Locale, String[]>(3);
-
-    /**
      * Cache NumberFormat instances with Locale key.
      */
     private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
@@ -662,33 +656,20 @@
         // initialize calendar and related fields
         initializeCalendar(loc);
 
-        /* try the cache first */
-        String[] dateTimePatterns = cachedLocaleData.get(loc);
-        if (dateTimePatterns == null) { /* cache miss */
-            LocaleData localeData = LocaleData.get(loc);
-            dateTimePatterns = new String[9];
-            dateTimePatterns[DateFormat.SHORT + 4] = localeData.getDateFormat(DateFormat.SHORT);
-            dateTimePatterns[DateFormat.MEDIUM + 4] = localeData.getDateFormat(DateFormat.MEDIUM);
-            dateTimePatterns[DateFormat.LONG + 4] = localeData.getDateFormat(DateFormat.LONG);
-            dateTimePatterns[DateFormat.FULL + 4] = localeData.getDateFormat(DateFormat.FULL);
-            dateTimePatterns[DateFormat.SHORT] = localeData.getTimeFormat(DateFormat.SHORT);
-            dateTimePatterns[DateFormat.MEDIUM] = localeData.getTimeFormat(DateFormat.MEDIUM);
-            dateTimePatterns[DateFormat.LONG] = localeData.getTimeFormat(DateFormat.LONG);
-            dateTimePatterns[DateFormat.FULL] = localeData.getTimeFormat(DateFormat.FULL);
-            dateTimePatterns[8] = "{0} {1}";
-            /* update cache */
-            cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
-        }
         formatData = DateFormatSymbols.getInstanceRef(loc);
+        LocaleData localeData = LocaleData.get(loc);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
-            Object[] dateTimeArgs = {dateTimePatterns[dateStyle + 4], dateTimePatterns[timeStyle]};
-            pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
+            Object[] dateTimeArgs = {
+                localeData.getDateFormat(dateStyle),
+                localeData.getTimeFormat(timeStyle),
+            };
+            pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
         }
         else if (timeStyle >= 0) {
-            pattern = dateTimePatterns[timeStyle];
+            pattern = localeData.getTimeFormat(timeStyle);
         }
         else if (dateStyle >= 0) {
-            pattern = dateTimePatterns[dateStyle + 4];
+            pattern = localeData.getDateFormat(dateStyle);
         }
         else {
             throw new IllegalArgumentException("No date or time style specified");
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index df3f769..0f175c3 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -26,7 +26,7 @@
 
 package java.util;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
 import java.util.concurrent.ForkJoinPool;
 import java.util.function.BinaryOperator;
 import java.util.function.Consumer;
@@ -80,6 +80,8 @@
      */
     public static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
 
+    // Suppresses default constructor, ensuring non-instantiability.
+    private Arrays() {}
 
     /**
      * A comparator that implements the natural ordering of a group of
@@ -104,11 +106,43 @@
         static final NaturalOrder INSTANCE = new NaturalOrder();
     }
 
-    // Suppresses default constructor, ensuring non-instantiability.
-    private Arrays() {}
+    /**
+     * Checks that {@code fromIndex} and {@code toIndex} are in
+     * the range and throws an appropriate exception, if they aren't.
+     */
+    private static void rangeCheck(int length, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException(
+                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex < 0) {
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        }
+        if (toIndex > length) {
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+        }
+    }
+
+    /**
+     * Checks that the range described by {@code offset} and {@code count} doesn't exceed
+     * {@code arrayLength}.
+     *
+     * Android changed.
+     * @hide
+     */
+    public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
+        if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
+            throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
+                    count);
+        }
+    }
 
     /*
-     * Sorting of primitive type arrays.
+     * Sorting methods. Note that all public "sort" methods take the
+     * same form: Performing argument checks if necessary, and then
+     * expanding arguments into those required for the internal
+     * implementation methods residing in other package-private
+     * classes (except for legacyMergeSort, included in this class).
      */
 
     /**
@@ -1167,50 +1201,6 @@
      */
 
     /**
-     * Old merge sort implementation can be selected (for
-     * compatibility with broken comparators) using a system property.
-     * Cannot be a static boolean in the enclosing class due to
-     * circular dependencies. To be removed in a future release.
-     */
-    static final class LegacyMergeSort {
-        // Android-changed: Never use circular merge sort.
-        private static final boolean userRequested = false;
-    }
-
-    /*
-     * If this platform has an optimizing VM, check whether ComparableTimSort
-     * offers any performance benefit over TimSort in conjunction with a
-     * comparator that returns:
-     *    {@code ((Comparable)first).compareTo(Second)}.
-     * If not, you are better off deleting ComparableTimSort to
-     * eliminate the code duplication.  In other words, the commented
-     * out code below is the preferable implementation for sorting
-     * arrays of Comparables if it offers sufficient performance.
-     */
-
-//    /**
-//     * A comparator that implements the natural ordering of a group of
-//     * mutually comparable elements.  Using this comparator saves us
-//     * from duplicating most of the code in this file (one version for
-//     * Comparables, one for explicit Comparators).
-//     */
-//    private static final Comparator<Object> NATURAL_ORDER =
-//            new Comparator<Object>() {
-//        @SuppressWarnings("unchecked")
-//        public int compare(Object first, Object second) {
-//            return ((Comparable<Object>)first).compareTo(second);
-//        }
-//    };
-//
-//    public static void sort(Object[] a) {
-//        sort(a, 0, a.length, NATURAL_ORDER);
-//    }
-//
-//    public static void sort(Object[] a, int fromIndex, int toIndex) {
-//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
-//    }
-
-    /**
      * Sorts the specified array of objects into ascending order, according
      * to the {@linkplain Comparable natural ordering} of its elements.
      * All elements in the array must implement the {@link Comparable}
@@ -1240,7 +1230,7 @@
      *
      * <p>The implementation was adapted from Tim Peters's list sort for Python
      * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
-     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * TimSort</a>).  It uses techniques from Peter McIlroy's "Optimistic
      * Sorting and Information Theoretic Complexity", in Proceedings of the
      * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
      * January 1993.
@@ -1253,18 +1243,13 @@
      *         {@link Comparable} contract
      */
     public static void sort(Object[] a) {
-        if (LegacyMergeSort.userRequested)
-            legacyMergeSort(a);
-        else
+        // Android-changed: LegacyMergeSort is no longer supported
+        // if (LegacyMergeSort.userRequested)
+        //     legacyMergeSort(a);
+        // else
             ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
     }
 
-    /** To be removed in a future release. */
-    private static void legacyMergeSort(Object[] a) {
-        Object[] aux = a.clone();
-        mergeSort(aux, a, 0, a.length, 0);
-    }
-
     /**
      * Sorts the specified range of the specified array of objects into
      * ascending order, according to the
@@ -1299,7 +1284,7 @@
      *
      * <p>The implementation was adapted from Tim Peters's list sort for Python
      * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
-     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * TimSort</a>).  It uses techniques from Peter McIlroy's "Optimistic
      * Sorting and Information Theoretic Complexity", in Proceedings of the
      * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
      * January 1993.
@@ -1319,20 +1304,13 @@
      */
     public static void sort(Object[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        if (LegacyMergeSort.userRequested)
-            legacyMergeSort(a, fromIndex, toIndex);
-        else
+        // Android-changed: LegacyMergeSort is no longer supported
+        // if (LegacyMergeSort.userRequested)
+        //     legacyMergeSort(a, fromIndex, toIndex);
+        // else
             ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
     }
 
-    /** To be removed in a future release. */
-    private static void legacyMergeSort(Object[] a,
-                                        int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        Object[] aux = copyOfRange(a, fromIndex, toIndex);
-        mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
-    }
-
     /**
      * Tuning parameter: list size at or below which insertion sort will be
      * used in preference to mergesort.
@@ -1348,6 +1326,7 @@
      * off is the offset to generate corresponding low, high in src
      * To be removed in a future release.
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private static void mergeSort(Object[] src,
                                   Object[] dest,
                                   int low,
@@ -1426,11 +1405,12 @@
      *
      * <p>The implementation was adapted from Tim Peters's list sort for Python
      * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
-     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * TimSort</a>).  It uses techniques from Peter McIlroy's "Optimistic
      * Sorting and Information Theoretic Complexity", in Proceedings of the
      * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
      * January 1993.
      *
+     * @param <T> the class of the objects to be sorted
      * @param a the array to be sorted
      * @param c the comparator to determine the order of the array.  A
      *        {@code null} value indicates that the elements'
@@ -1444,22 +1424,14 @@
         if (c == null) {
             sort(a);
         } else {
-            if (LegacyMergeSort.userRequested)
-                legacyMergeSort(a, c);
-            else
+            // Android-changed: LegacyMergeSort is no longer supported
+            // if (LegacyMergeSort.userRequested)
+            //     legacyMergeSort(a, c);
+            // else
                 TimSort.sort(a, 0, a.length, c, null, 0, 0);
         }
     }
 
-    /** To be removed in a future release. */
-    private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
-        T[] aux = a.clone();
-        if (c==null)
-            mergeSort(aux, a, 0, a.length, 0);
-        else
-            mergeSort(aux, a, 0, a.length, 0, c);
-    }
-
     /**
      * Sorts the specified range of the specified array of objects according
      * to the order induced by the specified comparator.  The range to be
@@ -1491,11 +1463,12 @@
      *
      * <p>The implementation was adapted from Tim Peters's list sort for Python
      * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
-     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * TimSort</a>).  It uses techniques from Peter McIlroy's "Optimistic
      * Sorting and Information Theoretic Complexity", in Proceedings of the
      * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
      * January 1993.
      *
+     * @param <T> the class of the objects to be sorted
      * @param a the array to be sorted
      * @param fromIndex the index of the first element (inclusive) to be
      *        sorted
@@ -1517,89 +1490,14 @@
             sort(a, fromIndex, toIndex);
         } else {
             rangeCheck(a.length, fromIndex, toIndex);
-            if (LegacyMergeSort.userRequested)
-                legacyMergeSort(a, fromIndex, toIndex, c);
-            else
+            // Android-changed: LegacyMergeSort is no longer supported
+            // if (LegacyMergeSort.userRequested)
+            //     legacyMergeSort(a, fromIndex, toIndex, c);
+            // else
                 TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
         }
     }
 
-    /** To be removed in a future release. */
-    private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
-                                            Comparator<? super T> c) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        T[] aux = copyOfRange(a, fromIndex, toIndex);
-        if (c==null)
-            mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
-        else
-            mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
-    }
-
-    /**
-     * Src is the source array that starts at index 0
-     * Dest is the (possibly larger) array destination with a possible offset
-     * low is the index in dest to start sorting
-     * high is the end index in dest to end sorting
-     * off is the offset into src corresponding to low in dest
-     * To be removed in a future release.
-     */
-    private static void mergeSort(Object[] src,
-                                  Object[] dest,
-                                  int low, int high, int off,
-                                  Comparator c) {
-        int length = high - low;
-
-        // Insertion sort on smallest arrays
-        if (length < INSERTIONSORT_THRESHOLD) {
-            for (int i=low; i<high; i++)
-                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
-                    swap(dest, j, j-1);
-            return;
-        }
-
-        // Recursively sort halves of dest into src
-        int destLow  = low;
-        int destHigh = high;
-        low  += off;
-        high += off;
-        int mid = (low + high) >>> 1;
-        mergeSort(dest, src, low, mid, -off, c);
-        mergeSort(dest, src, mid, high, -off, c);
-
-        // If list is already sorted, just copy from src to dest.  This is an
-        // optimization that results in faster sorts for nearly ordered lists.
-        if (c.compare(src[mid-1], src[mid]) <= 0) {
-           System.arraycopy(src, low, dest, destLow, length);
-           return;
-        }
-
-        // Merge sorted halves (now in src) into dest
-        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
-            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
-                dest[i] = src[p++];
-            else
-                dest[i] = src[q++];
-        }
-    }
-
-    /**
-     * Checks that {@code fromIndex} and {@code toIndex} are in
-     * the range and throws an appropriate exception, if they aren't.
-     */
-    private static void rangeCheck(int length, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException(
-                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-        if (fromIndex < 0) {
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        }
-        if (toIndex > length) {
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-        }
-    }
-
-
     // Parallel prefix
 
     /**
@@ -2462,7 +2360,9 @@
 
         while (low <= high) {
             int mid = (low + high) >>> 1;
+            @SuppressWarnings("rawtypes")
             Comparable midVal = (Comparable)a[mid];
+            @SuppressWarnings("unchecked")
             int cmp = midVal.compareTo(key);
 
             if (cmp < 0)
@@ -2486,6 +2386,7 @@
      * elements equal to the specified object, there is no guarantee which one
      * will be found.
      *
+     * @param <T> the class of the objects in the array
      * @param a the array to be searched
      * @param key the value to be searched for
      * @param c the comparator by which the array is ordered.  A
@@ -2521,6 +2422,7 @@
      * If the range contains multiple elements equal to the specified object,
      * there is no guarantee which one will be found.
      *
+     * @param <T> the class of the objects in the array
      * @param a the array to be searched
      * @param fromIndex the index of the first element (inclusive) to be
      *          searched
@@ -3192,6 +3094,7 @@
      * is greater than that of the original array.
      * The resulting array is of exactly the same class as the original array.
      *
+     * @param <T> the class of the objects in the array
      * @param original the array to be copied
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with nulls
@@ -3200,6 +3103,7 @@
      * @throws NullPointerException if <tt>original</tt> is null
      * @since 1.6
      */
+    @SuppressWarnings("unchecked")
     public static <T> T[] copyOf(T[] original, int newLength) {
         return (T[]) copyOf(original, newLength, original.getClass());
     }
@@ -3214,6 +3118,8 @@
      * is greater than that of the original array.
      * The resulting array is of the class <tt>newType</tt>.
      *
+     * @param <U> the class of the objects in the original array
+     * @param <T> the class of the objects in the returned array
      * @param original the array to be copied
      * @param newLength the length of the copy to be returned
      * @param newType the class of the copy to be returned
@@ -3227,6 +3133,7 @@
      * @since 1.6
      */
     public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
+        @SuppressWarnings("unchecked")
         T[] copy = ((Object)newType == (Object)Object[].class)
             ? (T[]) new Object[newLength]
             : (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3443,6 +3350,7 @@
      * <p>
      * The resulting array is of exactly the same class as the original array.
      *
+     * @param <T> the class of the objects in the array
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
      * @param to the final index of the range to be copied, exclusive.
@@ -3455,8 +3363,9 @@
      * @throws NullPointerException if <tt>original</tt> is null
      * @since 1.6
      */
+    @SuppressWarnings("unchecked")
     public static <T> T[] copyOfRange(T[] original, int from, int to) {
-        return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
+        return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass());
     }
 
     /**
@@ -3474,6 +3383,8 @@
      * of the returned array will be <tt>to - from</tt>.
      * The resulting array is of the class <tt>newType</tt>.
      *
+     * @param <U> the class of the objects in the original array
+     * @param <T> the class of the objects in the returned array
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
      * @param to the final index of the range to be copied, exclusive.
@@ -3494,6 +3405,7 @@
         int newLength = to - from;
         if (newLength < 0)
             throw new IllegalArgumentException(from + " > " + to);
+        @SuppressWarnings("unchecked")
         T[] copy = ((Object)newType == (Object)Object[].class)
             ? (T[]) new Object[newLength]
             : (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3805,10 +3717,12 @@
      *     List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
      * </pre>
      *
+     * @param <T> the class of the objects in the array
      * @param a the array by which the list will be backed
      * @return a list view of the specified array
      */
     @SafeVarargs
+    @SuppressWarnings("varargs")
     public static <T> List<T> asList(T... a) {
         return new ArrayList<>(a);
     }
@@ -3863,12 +3777,13 @@
 
         @Override
         public int indexOf(Object o) {
-            if (o==null) {
-                for (int i=0; i<a.length; i++)
-                    if (a[i]==null)
+            E[] a = this.a;
+            if (o == null) {
+                for (int i = 0; i < a.length; i++)
+                    if (a[i] == null)
                         return i;
             } else {
-                for (int i=0; i<a.length; i++)
+                for (int i = 0; i < a.length; i++)
                     if (o.equals(a[i]))
                         return i;
             }
@@ -3881,6 +3796,11 @@
         }
 
         @Override
+        public Spliterator<E> spliterator() {
+            return Spliterators.spliterator(a, Spliterator.ORDERED);
+        }
+
+        @Override
         public void forEach(Consumer<? super E> action) {
             Objects.requireNonNull(action);
             for (E e : a) {
@@ -3898,8 +3818,8 @@
         }
 
         @Override
-        public Spliterator<E> spliterator() {
-            return Spliterators.spliterator(a, Spliterator.ORDERED);
+        public void sort(Comparator<? super E> c) {
+            Arrays.sort(a, c);
         }
     }
 
@@ -4192,6 +4112,7 @@
 
         for (Object element : a) {
             int elementHash = 0;
+            // Android-changed: getComponentType() is faster than instanceof()
             if (element != null) {
                 Class<?> cl = element.getClass().getComponentType();
                 if (cl == null)
@@ -4273,6 +4194,7 @@
 
             if (e1 == e2)
                 continue;
+            // Android-changed: Return early if e2 == null
             if (e1 == null || e2 == null)
                 return false;
 
@@ -4286,6 +4208,7 @@
     }
 
     static boolean deepEquals0(Object e1, Object e2) {
+        // Android-changed: getComponentType() is faster than instanceof()
         Class<?> cl1 = e1.getClass().getComponentType();
         Class<?> cl2 = e2.getClass().getComponentType();
 
@@ -4654,7 +4577,7 @@
             if (element == null) {
                 buf.append("null");
             } else {
-                Class eClass = element.getClass();
+                Class<?> eClass = element.getClass();
 
                 if (eClass.isArray()) {
                     if (eClass == byte[].class)
@@ -4691,6 +4614,7 @@
         dejaVu.remove(a);
     }
 
+
     /**
      * Set all elements of the specified array, using the provided
      * generator function to compute each element.
@@ -4846,21 +4770,6 @@
     }
 
     /**
-     * Checks that the range described by {@code offset} and {@code count} doesn't exceed
-     * {@code arrayLength}.
-     *
-     * Android changed.
-     * @hide
-     */
-    public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
-        if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
-            throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
-                    count);
-        }
-    }
-
-
-    /**
      * Returns a {@link Spliterator} covering all of the specified array.
      *
      * <p>The spliterator reports {@link Spliterator#SIZED},
@@ -5019,7 +4928,6 @@
                                         Spliterator.ORDERED | Spliterator.IMMUTABLE);
     }
 
-
     /**
      * Returns a sequential {@link Stream} with the specified array as its
      * source.
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 5a4de2a..65b9b55 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.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
@@ -25,7 +25,8 @@
  */
 
 package java.util;
-
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
@@ -35,11 +36,10 @@
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
-import java.util.function.UnaryOperator;
-
 
 /**
  * This class consists exclusively of static methods that operate on or return
@@ -162,9 +162,16 @@
      * @throws IllegalArgumentException (optional) if the implementation
      *         detects that the natural ordering of the list elements is
      *         found to violate the {@link Comparable} contract
+     * @see List#sort(Comparator)
      */
     @SuppressWarnings("unchecked")
     public static <T extends Comparable<? super T>> void sort(List<T> list) {
+        // Android-changed BEGIN: List.sort() is implemented on top of
+        // Collections.sort() rather than the other way around. For backwards
+        // compatibility, Collections.sort() never changes a List's modCount,
+        // but List.sort() implementations may.
+        // was: list.sort(null);
+
         if (list.getClass() == ArrayList.class) {
             Arrays.sort(((ArrayList) list).elementData, 0, list.size());
             return;
@@ -177,6 +184,7 @@
             i.next();
             i.set((T)a[j]);
         }
+        // Android-changed END
     }
 
     /**
@@ -231,9 +239,16 @@
      *         list-iterator does not support the {@code set} operation.
      * @throws IllegalArgumentException (optional) if the comparator is
      *         found to violate the {@link Comparator} contract
+     * @see List#sort(Comparator)
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
     public static <T> void sort(List<T> list, Comparator<? super T> c) {
+        // Android-changed BEGIN: List.sort() is implemented on top of
+        // Collections.sort() rather than the other way around. For backwards
+        // compatibility, Collections.sort() never changes a List's modCount,
+        // but List.sort() implementations may.
+        // was: list.sort(c);
+
         if (list.getClass() == ArrayList.class) {
             Arrays.sort(((ArrayList) list).elementData, 0, list.size(), (Comparator) c);
             return;
@@ -246,6 +261,7 @@
             i.next();
             i.set((T)a[j]);
         }
+        // Android-changed END
     }
 
 
@@ -1152,12 +1168,10 @@
         public void forEach(Consumer<? super E> action) {
             c.forEach(action);
         }
-
         @Override
         public boolean removeIf(Predicate<? super E> filter) {
             throw new UnsupportedOperationException();
         }
-
         @SuppressWarnings("unchecked")
         @Override
         public Spliterator<E> spliterator() {
@@ -1254,6 +1268,96 @@
     }
 
     /**
+     * Returns an unmodifiable view of the specified navigable set.  This method
+     * allows modules to provide users with "read-only" access to internal
+     * navigable sets.  Query operations on the returned navigable set "read
+     * through" to the specified navigable set.  Attempts to modify the returned
+     * navigable set, whether direct, via its iterator, or via its
+     * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in
+     * an {@code UnsupportedOperationException}.<p>
+     *
+     * The returned navigable set will be serializable if the specified
+     * navigable set is serializable.
+     *
+     * @param  <T> the class of the objects in the set
+     * @param s the navigable set for which an unmodifiable view is to be
+     *        returned
+     * @return an unmodifiable view of the specified navigable set
+     * @since 1.8
+     * @hide
+     */
+    public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s) {
+        return new UnmodifiableNavigableSet<>(s);
+    }
+
+    /**
+     * Wraps a navigable set and disables all of the mutative operations.
+     *
+     * @param <E> type of elements
+     * @serial include
+     */
+    static class UnmodifiableNavigableSet<E>
+                             extends UnmodifiableSortedSet<E>
+                             implements NavigableSet<E>, Serializable {
+
+        private static final long serialVersionUID = -6027448201786391929L;
+
+        /**
+         * A singleton empty unmodifiable navigable set used for
+         * {@link #emptyNavigableSet()}.
+         *
+         * @param <E> type of elements, if there were any, and bounds
+         */
+        private static class EmptyNavigableSet<E> extends UnmodifiableNavigableSet<E>
+            implements Serializable {
+            private static final long serialVersionUID = -6291252904449939134L;
+
+            public EmptyNavigableSet() {
+                super(new TreeSet<E>());
+            }
+
+            private Object readResolve()        { return EMPTY_NAVIGABLE_SET; }
+        }
+
+        @SuppressWarnings("rawtypes")
+        private static final NavigableSet<?> EMPTY_NAVIGABLE_SET =
+                new EmptyNavigableSet<>();
+
+        /**
+         * The instance we are protecting.
+         */
+        private final NavigableSet<E> ns;
+
+        UnmodifiableNavigableSet(NavigableSet<E> s)         {super(s); ns = s;}
+
+        public E lower(E e)                             { return ns.lower(e); }
+        public E floor(E e)                             { return ns.floor(e); }
+        public E ceiling(E e)                         { return ns.ceiling(e); }
+        public E higher(E e)                           { return ns.higher(e); }
+        public E pollFirst()     { throw new UnsupportedOperationException(); }
+        public E pollLast()      { throw new UnsupportedOperationException(); }
+        public NavigableSet<E> descendingSet()
+                 { return new UnmodifiableNavigableSet<>(ns.descendingSet()); }
+        public Iterator<E> descendingIterator()
+                                         { return descendingSet().iterator(); }
+
+        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+            return new UnmodifiableNavigableSet<>(
+                ns.subSet(fromElement, fromInclusive, toElement, toInclusive));
+        }
+
+        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+            return new UnmodifiableNavigableSet<>(
+                ns.headSet(toElement, inclusive));
+        }
+
+        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+            return new UnmodifiableNavigableSet<>(
+                ns.tailSet(fromElement, inclusive));
+        }
+    }
+
+    /**
      * Returns an unmodifiable view of the specified list.  This method allows
      * modules to provide users with "read-only" access to internal
      * lists.  Query operations on the returned list "read through" to the
@@ -1307,6 +1411,7 @@
         public boolean addAll(int index, Collection<? extends E> c) {
             throw new UnsupportedOperationException();
         }
+
         @Override
         public void replaceAll(UnaryOperator<E> operator) {
             throw new UnsupportedOperationException();
@@ -1315,6 +1420,7 @@
         public void sort(Comparator<? super E> c) {
             throw new UnsupportedOperationException();
         }
+
         public ListIterator<E> listIterator()   {return listIterator(0);}
 
         public ListIterator<E> listIterator(final int index) {
@@ -1450,9 +1556,9 @@
             throw new UnsupportedOperationException();
         }
 
-        private transient Set<K> keySet = null;
-        private transient Set<Map.Entry<K,V>> entrySet = null;
-        private transient Collection<V> values = null;
+        private transient Set<K> keySet;
+        private transient Set<Map.Entry<K,V>> entrySet;
+        private transient Collection<V> values;
 
         public Set<K> keySet() {
             if (keySet==null)
@@ -1521,19 +1627,19 @@
 
         @Override
         public V computeIfPresent(K key,
-                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V compute(K key,
-                         BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V merge(K key, V value,
-                       BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
@@ -1559,7 +1665,6 @@
                 return e -> action.accept(new UnmodifiableEntry<>(e));
             }
 
-            // Override default methods in Collection
             public void forEach(Consumer<? super Entry<K, V>> action) {
                 Objects.requireNonNull(action);
                 c.forEach(entryConsumer(action));
@@ -1794,6 +1899,149 @@
         public K lastKey()                             { return sm.lastKey(); }
     }
 
+    /**
+     * Returns an unmodifiable view of the specified navigable map.  This method
+     * allows modules to provide users with "read-only" access to internal
+     * navigable maps.  Query operations on the returned navigable map "read
+     * through" to the specified navigable map.  Attempts to modify the returned
+     * navigable map, whether direct, via its collection views, or via its
+     * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in
+     * an {@code UnsupportedOperationException}.<p>
+     *
+     * The returned navigable map will be serializable if the specified
+     * navigable map is serializable.
+     *
+     * @param <K> the class of the map keys
+     * @param <V> the class of the map values
+     * @param m the navigable map for which an unmodifiable view is to be
+     *        returned
+     * @return an unmodifiable view of the specified navigable map
+     * @since 1.8
+     * @hide
+     */
+    public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m) {
+        return new UnmodifiableNavigableMap<>(m);
+    }
+
+    /**
+     * @serial include
+     */
+    static class UnmodifiableNavigableMap<K,V>
+          extends UnmodifiableSortedMap<K,V>
+          implements NavigableMap<K,V>, Serializable {
+        private static final long serialVersionUID = -4858195264774772197L;
+
+        /**
+         * A class for the {@link EMPTY_NAVIGABLE_MAP} which needs readResolve
+         * to preserve singleton property.
+         *
+         * @param <K> type of keys, if there were any, and of bounds
+         * @param <V> type of values, if there were any
+         */
+        private static class EmptyNavigableMap<K,V> extends UnmodifiableNavigableMap<K,V>
+            implements Serializable {
+
+            private static final long serialVersionUID = -2239321462712562324L;
+
+            EmptyNavigableMap()                       { super(new TreeMap<K,V>()); }
+
+            @Override
+            public NavigableSet<K> navigableKeySet()
+                                                { return emptyNavigableSet(); }
+
+            private Object readResolve()        { return EMPTY_NAVIGABLE_MAP; }
+        }
+
+        /**
+         * Singleton for {@link emptyNavigableMap()} which is also immutable.
+         */
+        private static final EmptyNavigableMap<?,?> EMPTY_NAVIGABLE_MAP =
+            new EmptyNavigableMap<>();
+
+        /**
+         * The instance we wrap and protect.
+         */
+        private final NavigableMap<K, ? extends V> nm;
+
+        UnmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
+                                                            {super(m); nm = m;}
+
+        public K lowerKey(K key)                   { return nm.lowerKey(key); }
+        public K floorKey(K key)                   { return nm.floorKey(key); }
+        public K ceilingKey(K key)               { return nm.ceilingKey(key); }
+        public K higherKey(K key)                 { return nm.higherKey(key); }
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> lowerEntry(K key) {
+            Entry<K,V> lower = (Entry<K, V>) nm.lowerEntry(key);
+            return (null != lower)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(lower)
+                : null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> floorEntry(K key) {
+            Entry<K,V> floor = (Entry<K, V>) nm.floorEntry(key);
+            return (null != floor)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(floor)
+                : null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> ceilingEntry(K key) {
+            Entry<K,V> ceiling = (Entry<K, V>) nm.ceilingEntry(key);
+            return (null != ceiling)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(ceiling)
+                : null;
+        }
+
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> higherEntry(K key) {
+            Entry<K,V> higher = (Entry<K, V>) nm.higherEntry(key);
+            return (null != higher)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(higher)
+                : null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> firstEntry() {
+            Entry<K,V> first = (Entry<K, V>) nm.firstEntry();
+            return (null != first)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(first)
+                : null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Entry<K, V> lastEntry() {
+            Entry<K,V> last = (Entry<K, V>) nm.lastEntry();
+            return (null != last)
+                ? new UnmodifiableEntrySet.UnmodifiableEntry<>(last)
+                : null;
+        }
+
+        public Entry<K, V> pollFirstEntry()
+                                 { throw new UnsupportedOperationException(); }
+        public Entry<K, V> pollLastEntry()
+                                 { throw new UnsupportedOperationException(); }
+        public NavigableMap<K, V> descendingMap()
+                       { return unmodifiableNavigableMap(nm.descendingMap()); }
+        public NavigableSet<K> navigableKeySet()
+                     { return unmodifiableNavigableSet(nm.navigableKeySet()); }
+        public NavigableSet<K> descendingKeySet()
+                    { return unmodifiableNavigableSet(nm.descendingKeySet()); }
+
+        public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+            return unmodifiableNavigableMap(
+                nm.subMap(fromKey, fromInclusive, toKey, toInclusive));
+        }
+
+        public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
+             { return unmodifiableNavigableMap(nm.headMap(toKey, inclusive)); }
+        public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
+           { return unmodifiableNavigableMap(nm.tailMap(fromKey, inclusive)); }
+    }
+
     // Synch Wrappers
 
     /**
@@ -2078,6 +2326,122 @@
     }
 
     /**
+     * Returns a synchronized (thread-safe) navigable set backed by the
+     * specified navigable set.  In order to guarantee serial access, it is
+     * critical that <strong>all</strong> access to the backing navigable set is
+     * accomplished through the returned navigable set (or its views).<p>
+     *
+     * It is imperative that the user manually synchronize on the returned
+     * navigable set when iterating over it or any of its {@code subSet},
+     * {@code headSet}, or {@code tailSet} views.
+     * <pre>
+     *  NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+     *      ...
+     *  synchronized (s) {
+     *      Iterator i = s.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * </pre>
+     * or:
+     * <pre>
+     *  NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+     *  NavigableSet s2 = s.headSet(foo, true);
+     *      ...
+     *  synchronized (s) {  // Note: s, not s2!!!
+     *      Iterator i = s2.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * </pre>
+     * Failure to follow this advice may result in non-deterministic behavior.
+     *
+     * <p>The returned navigable set will be serializable if the specified
+     * navigable set is serializable.
+     *
+     * @param  <T> the class of the objects in the set
+     * @param  s the navigable set to be "wrapped" in a synchronized navigable
+     * set
+     * @return a synchronized view of the specified navigable set
+     * @since 1.8
+     * @hide
+     */
+    public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) {
+        return new SynchronizedNavigableSet<>(s);
+    }
+
+    /**
+     * @serial include
+     */
+    static class SynchronizedNavigableSet<E>
+        extends SynchronizedSortedSet<E>
+        implements NavigableSet<E>
+    {
+        private static final long serialVersionUID = -5505529816273629798L;
+
+        private final NavigableSet<E> ns;
+
+        SynchronizedNavigableSet(NavigableSet<E> s) {
+            super(s);
+            ns = s;
+        }
+
+        SynchronizedNavigableSet(NavigableSet<E> s, Object mutex) {
+            super(s, mutex);
+            ns = s;
+        }
+        public E lower(E e)      { synchronized (mutex) {return ns.lower(e);} }
+        public E floor(E e)      { synchronized (mutex) {return ns.floor(e);} }
+        public E ceiling(E e)  { synchronized (mutex) {return ns.ceiling(e);} }
+        public E higher(E e)    { synchronized (mutex) {return ns.higher(e);} }
+        public E pollFirst()  { synchronized (mutex) {return ns.pollFirst();} }
+        public E pollLast()    { synchronized (mutex) {return ns.pollLast();} }
+
+        public NavigableSet<E> descendingSet() {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.descendingSet(), mutex);
+            }
+        }
+
+        public Iterator<E> descendingIterator()
+                 { synchronized (mutex) { return descendingSet().iterator(); } }
+
+        public NavigableSet<E> subSet(E fromElement, E toElement) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.subSet(fromElement, true, toElement, false), mutex);
+            }
+        }
+        public NavigableSet<E> headSet(E toElement) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.headSet(toElement, false), mutex);
+            }
+        }
+        public NavigableSet<E> tailSet(E fromElement) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex);
+            }
+        }
+
+        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
+            }
+        }
+
+        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.headSet(toElement, inclusive), mutex);
+            }
+        }
+
+        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex);
+            }
+        }
+    }
+
+    /**
      * Returns a synchronized (thread-safe) list backed by the specified
      * list.  In order to guarantee serial access, it is critical that
      * <strong>all</strong> access to the backing list is accomplished
@@ -2327,9 +2691,9 @@
             synchronized (mutex) {m.clear();}
         }
 
-        private transient Set<K> keySet = null;
-        private transient Set<Map.Entry<K,V>> entrySet = null;
-        private transient Collection<V> values = null;
+        private transient Set<K> keySet;
+        private transient Set<Map.Entry<K,V>> entrySet;
+        private transient Collection<V> values;
 
         public Set<K> keySet() {
             synchronized (mutex) {
@@ -2398,22 +2762,22 @@
         }
         @Override
         public V computeIfAbsent(K key,
-                                 Function<? super K, ? extends V> mappingFunction) {
+                Function<? super K, ? extends V> mappingFunction) {
             synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
         }
         @Override
         public V computeIfPresent(K key,
-                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
         }
         @Override
         public V compute(K key,
-                         BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             synchronized (mutex) {return m.compute(key, remappingFunction);}
         }
         @Override
         public V merge(K key, V value,
-                       BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
             synchronized (mutex) {return m.merge(key, value, remappingFunction);}
         }
 
@@ -2519,6 +2883,167 @@
         }
     }
 
+    /**
+     * Returns a synchronized (thread-safe) navigable map backed by the
+     * specified navigable map.  In order to guarantee serial access, it is
+     * critical that <strong>all</strong> access to the backing navigable map is
+     * accomplished through the returned navigable map (or its views).<p>
+     *
+     * It is imperative that the user manually synchronize on the returned
+     * navigable map when iterating over any of its collection views, or the
+     * collections views of any of its {@code subMap}, {@code headMap} or
+     * {@code tailMap} views.
+     * <pre>
+     *  NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+     *      ...
+     *  Set s = m.keySet();  // Needn't be in synchronized block
+     *      ...
+     *  synchronized (m) {  // Synchronizing on m, not s!
+     *      Iterator i = s.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * </pre>
+     * or:
+     * <pre>
+     *  NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+     *  NavigableMap m2 = m.subMap(foo, true, bar, false);
+     *      ...
+     *  Set s2 = m2.keySet();  // Needn't be in synchronized block
+     *      ...
+     *  synchronized (m) {  // Synchronizing on m, not m2 or s2!
+     *      Iterator i = s.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * </pre>
+     * Failure to follow this advice may result in non-deterministic behavior.
+     *
+     * <p>The returned navigable map will be serializable if the specified
+     * navigable map is serializable.
+     *
+     * @param <K> the class of the map keys
+     * @param <V> the class of the map values
+     * @param  m the navigable map to be "wrapped" in a synchronized navigable
+     *              map
+     * @return a synchronized view of the specified navigable map.
+     * @since 1.8
+     * @hide
+     */
+    public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) {
+        return new SynchronizedNavigableMap<>(m);
+    }
+
+    /**
+     * A synchronized NavigableMap.
+     *
+     * @serial include
+     */
+    static class SynchronizedNavigableMap<K,V>
+        extends SynchronizedSortedMap<K,V>
+        implements NavigableMap<K,V>
+    {
+        private static final long serialVersionUID = 699392247599746807L;
+
+        private final NavigableMap<K,V> nm;
+
+        SynchronizedNavigableMap(NavigableMap<K,V> m) {
+            super(m);
+            nm = m;
+        }
+        SynchronizedNavigableMap(NavigableMap<K,V> m, Object mutex) {
+            super(m, mutex);
+            nm = m;
+        }
+
+        public Entry<K, V> lowerEntry(K key)
+                        { synchronized (mutex) { return nm.lowerEntry(key); } }
+        public K lowerKey(K key)
+                          { synchronized (mutex) { return nm.lowerKey(key); } }
+        public Entry<K, V> floorEntry(K key)
+                        { synchronized (mutex) { return nm.floorEntry(key); } }
+        public K floorKey(K key)
+                          { synchronized (mutex) { return nm.floorKey(key); } }
+        public Entry<K, V> ceilingEntry(K key)
+                      { synchronized (mutex) { return nm.ceilingEntry(key); } }
+        public K ceilingKey(K key)
+                        { synchronized (mutex) { return nm.ceilingKey(key); } }
+        public Entry<K, V> higherEntry(K key)
+                       { synchronized (mutex) { return nm.higherEntry(key); } }
+        public K higherKey(K key)
+                         { synchronized (mutex) { return nm.higherKey(key); } }
+        public Entry<K, V> firstEntry()
+                           { synchronized (mutex) { return nm.firstEntry(); } }
+        public Entry<K, V> lastEntry()
+                            { synchronized (mutex) { return nm.lastEntry(); } }
+        public Entry<K, V> pollFirstEntry()
+                       { synchronized (mutex) { return nm.pollFirstEntry(); } }
+        public Entry<K, V> pollLastEntry()
+                        { synchronized (mutex) { return nm.pollLastEntry(); } }
+
+        public NavigableMap<K, V> descendingMap() {
+            synchronized (mutex) {
+                return
+                    new SynchronizedNavigableMap<>(nm.descendingMap(), mutex);
+            }
+        }
+
+        public NavigableSet<K> keySet() {
+            return navigableKeySet();
+        }
+
+        public NavigableSet<K> navigableKeySet() {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(nm.navigableKeySet(), mutex);
+            }
+        }
+
+        public NavigableSet<K> descendingKeySet() {
+            synchronized (mutex) {
+                return new SynchronizedNavigableSet<>(nm.descendingKeySet(), mutex);
+            }
+        }
+
+
+        public SortedMap<K,V> subMap(K fromKey, K toKey) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableMap<>(
+                    nm.subMap(fromKey, true, toKey, false), mutex);
+            }
+        }
+        public SortedMap<K,V> headMap(K toKey) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableMap<>(nm.headMap(toKey, false), mutex);
+            }
+        }
+        public SortedMap<K,V> tailMap(K fromKey) {
+            synchronized (mutex) {
+        return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex);
+            }
+        }
+
+        public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableMap<>(
+                    nm.subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
+            }
+        }
+
+        public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableMap<>(
+                        nm.headMap(toKey, inclusive), mutex);
+            }
+        }
+
+        public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+            synchronized (mutex) {
+                return new SynchronizedNavigableMap<>(
+                    nm.tailMap(fromKey, inclusive), mutex);
+            }
+        }
+    }
+
     // Dynamically typesafe collection wrappers
 
     /**
@@ -2601,9 +3126,11 @@
         final Collection<E> c;
         final Class<E> type;
 
-        void typeCheck(Object o) {
+        @SuppressWarnings("unchecked")
+        E typeCheck(Object o) {
             if (o != null && !type.isInstance(o))
                 throw new ClassCastException(badElementMsg(o));
+            return (E) o;
         }
 
         private String badElementMsg(Object o) {
@@ -2612,10 +3139,8 @@
         }
 
         CheckedCollection(Collection<E> c, Class<E> type) {
-            if (c==null || type == null)
-                throw new NullPointerException();
-            this.c = c;
-            this.type = type;
+            this.c = Objects.requireNonNull(c, "c");
+            this.type = Objects.requireNonNull(type, "type");
         }
 
         public int size()                 { return c.size(); }
@@ -2648,12 +3173,9 @@
             // Android-note: Should we delegate to it for forEachRemaining ?
         }
 
-        public boolean add(E e) {
-            typeCheck(e);
-            return c.add(e);
-        }
+        public boolean add(E e)          { return c.add(typeCheck(e)); }
 
-        private E[] zeroLengthElementArray = null; // Lazily initialized
+        private E[] zeroLengthElementArray; // Lazily initialized
 
         private E[] zeroLengthElementArray() {
             return zeroLengthElementArray != null ? zeroLengthElementArray :
@@ -2662,7 +3184,7 @@
 
         @SuppressWarnings("unchecked")
         Collection<E> checkedCopyOf(Collection<? extends E> coll) {
-            Object[] a = null;
+            Object[] a;
             try {
                 E[] z = zeroLengthElementArray();
                 a = coll.toArray(z);
@@ -2704,7 +3226,62 @@
         public Stream<E> stream()           {return c.stream();}
         @Override
         public Stream<E> parallelStream()   {return c.parallelStream();}
+    }
 
+    /**
+     * Returns a dynamically typesafe view of the specified queue.
+     * Any attempt to insert an element of the wrong type will result in
+     * an immediate {@link ClassCastException}.  Assuming a queue contains
+     * no incorrectly typed elements prior to the time a dynamically typesafe
+     * view is generated, and that all subsequent access to the queue
+     * takes place through the view, it is <i>guaranteed</i> that the
+     * queue cannot contain an incorrectly typed element.
+     *
+     * <p>A discussion of the use of dynamically typesafe views may be
+     * found in the documentation for the {@link #checkedCollection
+     * checkedCollection} method.
+     *
+     * <p>The returned queue will be serializable if the specified queue
+     * is serializable.
+     *
+     * <p>Since {@code null} is considered to be a value of any reference
+     * type, the returned queue permits insertion of {@code null} elements
+     * whenever the backing queue does.
+     *
+     * @param <E> the class of the objects in the queue
+     * @param queue the queue for which a dynamically typesafe view is to be
+     *             returned
+     * @param type the type of element that {@code queue} is permitted to hold
+     * @return a dynamically typesafe view of the specified queue
+     * @since 1.8
+     * @hide
+     */
+    public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
+        return new CheckedQueue<>(queue, type);
+    }
+
+    /**
+     * @serial include
+     */
+    static class CheckedQueue<E>
+        extends CheckedCollection<E>
+        implements Queue<E>, Serializable
+    {
+        private static final long serialVersionUID = 1433151992604707767L;
+        final Queue<E> queue;
+
+        CheckedQueue(Queue<E> queue, Class<E> elementType) {
+            super(queue, elementType);
+            this.queue = queue;
+        }
+
+        public E element()              {return queue.element();}
+        public boolean equals(Object o) {return o == this || c.equals(o);}
+        public int hashCode()           {return c.hashCode();}
+        public E peek()                 {return queue.peek();}
+        public E poll()                 {return queue.poll();}
+        public E remove()               {return queue.remove();}
+        public boolean offer(E e)       {return queue.offer(typeCheck(e));}
     }
 
     /**
@@ -2815,6 +3392,89 @@
         }
     }
 
+/**
+     * Returns a dynamically typesafe view of the specified navigable set.
+     * Any attempt to insert an element of the wrong type will result in an
+     * immediate {@link ClassCastException}.  Assuming a navigable set
+     * contains no incorrectly typed elements prior to the time a
+     * dynamically typesafe view is generated, and that all subsequent
+     * access to the navigable set takes place through the view, it is
+     * <em>guaranteed</em> that the navigable set cannot contain an incorrectly
+     * typed element.
+     *
+     * <p>A discussion of the use of dynamically typesafe views may be
+     * found in the documentation for the {@link #checkedCollection
+     * checkedCollection} method.
+     *
+     * <p>The returned navigable set will be serializable if the specified
+     * navigable set is serializable.
+     *
+     * <p>Since {@code null} is considered to be a value of any reference
+     * type, the returned navigable set permits insertion of null elements
+     * whenever the backing sorted set does.
+     *
+     * @param <E> the class of the objects in the set
+     * @param s the navigable set for which a dynamically typesafe view is to be
+     *          returned
+     * @param type the type of element that {@code s} is permitted to hold
+     * @return a dynamically typesafe view of the specified navigable set
+     * @since 1.8
+     * @hide
+     */
+    public static <E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s,
+                                                    Class<E> type) {
+        return new CheckedNavigableSet<>(s, type);
+    }
+
+    /**
+     * @serial include
+     */
+    static class CheckedNavigableSet<E> extends CheckedSortedSet<E>
+        implements NavigableSet<E>, Serializable
+    {
+        private static final long serialVersionUID = -5429120189805438922L;
+
+        private final NavigableSet<E> ns;
+
+        CheckedNavigableSet(NavigableSet<E> s, Class<E> type) {
+            super(s, type);
+            ns = s;
+        }
+
+        public E lower(E e)                             { return ns.lower(e); }
+        public E floor(E e)                             { return ns.floor(e); }
+        public E ceiling(E e)                         { return ns.ceiling(e); }
+        public E higher(E e)                           { return ns.higher(e); }
+        public E pollFirst()                         { return ns.pollFirst(); }
+        public E pollLast()                            {return ns.pollLast(); }
+        public NavigableSet<E> descendingSet()
+                      { return checkedNavigableSet(ns.descendingSet(), type); }
+        public Iterator<E> descendingIterator()
+            {return checkedNavigableSet(ns.descendingSet(), type).iterator(); }
+
+        public NavigableSet<E> subSet(E fromElement, E toElement) {
+            return checkedNavigableSet(ns.subSet(fromElement, true, toElement, false), type);
+        }
+        public NavigableSet<E> headSet(E toElement) {
+            return checkedNavigableSet(ns.headSet(toElement, false), type);
+        }
+        public NavigableSet<E> tailSet(E fromElement) {
+            return checkedNavigableSet(ns.tailSet(fromElement, true), type);
+        }
+
+        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+            return checkedNavigableSet(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), type);
+        }
+
+        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+            return checkedNavigableSet(ns.headSet(toElement, inclusive), type);
+        }
+
+        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+            return checkedNavigableSet(ns.tailSet(fromElement, inclusive), type);
+        }
+    }
+
     /**
      * Returns a dynamically typesafe view of the specified list.
      * Any attempt to insert an element of the wrong type will result in
@@ -2871,13 +3531,11 @@
         public int lastIndexOf(Object o) { return list.lastIndexOf(o); }
 
         public E set(int index, E element) {
-            typeCheck(element);
-            return list.set(index, element);
+            return list.set(index, typeCheck(element));
         }
 
         public void add(int index, E element) {
-            typeCheck(element);
-            list.add(index, element);
+            list.add(index, typeCheck(element));
         }
 
         public boolean addAll(int index, Collection<? extends E> c) {
@@ -2898,13 +3556,11 @@
                 public void remove()         {        i.remove(); }
 
                 public void set(E e) {
-                    typeCheck(e);
-                    i.set(e);
+                    i.set(typeCheck(e));
                 }
 
                 public void add(E e) {
-                    typeCheck(e);
-                    i.add(e);
+                    i.add(typeCheck(e));
                 }
 
                 @Override
@@ -2929,14 +3585,7 @@
         @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;
-            });
+            list.replaceAll(e -> typeCheck(operator.apply(e)));
         }
 
         @Override
@@ -3038,12 +3687,12 @@
 
         private String badKeyMsg(Object key) {
             return "Attempt to insert " + key.getClass() +
-                " key into map with key type " + keyType;
+                    " key into map with key type " + keyType;
         }
 
         private String badValueMsg(Object value) {
             return "Attempt to insert " + value.getClass() +
-                " value into map with value type " + valueType;
+                    " value into map with value type " + valueType;
         }
 
         CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
@@ -3091,7 +3740,7 @@
                 m.put(e.getKey(), e.getValue());
         }
 
-        private transient Set<Map.Entry<K,V>> entrySet = null;
+        private transient Set<Map.Entry<K,V>> entrySet;
 
         public Set<Map.Entry<K,V>> entrySet() {
             if (entrySet==null)
@@ -3434,6 +4083,178 @@
         }
     }
 
+    /**
+     * Returns a dynamically typesafe view of the specified navigable map.
+     * Any attempt to insert a mapping whose key or value have the wrong
+     * type will result in an immediate {@link ClassCastException}.
+     * Similarly, any attempt to modify the value currently associated with
+     * a key will result in an immediate {@link ClassCastException},
+     * whether the modification is attempted directly through the map
+     * itself, or through a {@link Map.Entry} instance obtained from the
+     * map's {@link Map#entrySet() entry set} view.
+     *
+     * <p>Assuming a map contains no incorrectly typed keys or values
+     * prior to the time a dynamically typesafe view is generated, and
+     * that all subsequent access to the map takes place through the view
+     * (or one of its collection views), it is <em>guaranteed</em> that the
+     * map cannot contain an incorrectly typed key or value.
+     *
+     * <p>A discussion of the use of dynamically typesafe views may be
+     * found in the documentation for the {@link #checkedCollection
+     * checkedCollection} method.
+     *
+     * <p>The returned map will be serializable if the specified map is
+     * serializable.
+     *
+     * <p>Since {@code null} is considered to be a value of any reference
+     * type, the returned map permits insertion of null keys or values
+     * whenever the backing map does.
+     *
+     * @param <K> type of map keys
+     * @param <V> type of map values
+     * @param m the map for which a dynamically typesafe view is to be
+     *          returned
+     * @param keyType the type of key that {@code m} is permitted to hold
+     * @param valueType the type of value that {@code m} is permitted to hold
+     * @return a dynamically typesafe view of the specified map
+     * @since 1.8
+     * @hide
+     */
+    public static <K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m,
+                                                        Class<K> keyType,
+                                                        Class<V> valueType) {
+        return new CheckedNavigableMap<>(m, keyType, valueType);
+    }
+
+    /**
+     * @serial include
+     */
+    static class CheckedNavigableMap<K,V> extends CheckedSortedMap<K,V>
+        implements NavigableMap<K,V>, Serializable
+    {
+        private static final long serialVersionUID = -4852462692372534096L;
+
+        private final NavigableMap<K, V> nm;
+
+        CheckedNavigableMap(NavigableMap<K, V> m,
+                         Class<K> keyType, Class<V> valueType) {
+            super(m, keyType, valueType);
+            nm = m;
+        }
+
+        public Comparator<? super K> comparator()   { return nm.comparator(); }
+        public K firstKey()                           { return nm.firstKey(); }
+        public K lastKey()                             { return nm.lastKey(); }
+
+        public Entry<K, V> lowerEntry(K key) {
+            Entry<K,V> lower = nm.lowerEntry(key);
+            return (null != lower)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(lower, valueType)
+                : null;
+        }
+
+        public K lowerKey(K key)                   { return nm.lowerKey(key); }
+
+        public Entry<K, V> floorEntry(K key) {
+            Entry<K,V> floor = nm.floorEntry(key);
+            return (null != floor)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(floor, valueType)
+                : null;
+        }
+
+        public K floorKey(K key)                   { return nm.floorKey(key); }
+
+        public Entry<K, V> ceilingEntry(K key) {
+            Entry<K,V> ceiling = nm.ceilingEntry(key);
+            return (null != ceiling)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(ceiling, valueType)
+                : null;
+        }
+
+        public K ceilingKey(K key)               { return nm.ceilingKey(key); }
+
+        public Entry<K, V> higherEntry(K key) {
+            Entry<K,V> higher = nm.higherEntry(key);
+            return (null != higher)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(higher, valueType)
+                : null;
+        }
+
+        public K higherKey(K key)                 { return nm.higherKey(key); }
+
+        public Entry<K, V> firstEntry() {
+            Entry<K,V> first = nm.firstEntry();
+            return (null != first)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(first, valueType)
+                : null;
+        }
+
+        public Entry<K, V> lastEntry() {
+            Entry<K,V> last = nm.lastEntry();
+            return (null != last)
+                ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(last, valueType)
+                : null;
+        }
+
+        public Entry<K, V> pollFirstEntry() {
+            Entry<K,V> entry = nm.pollFirstEntry();
+            return (null == entry)
+                ? null
+                : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+        }
+
+        public Entry<K, V> pollLastEntry() {
+            Entry<K,V> entry = nm.pollLastEntry();
+            return (null == entry)
+                ? null
+                : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+        }
+
+        public NavigableMap<K, V> descendingMap() {
+            return checkedNavigableMap(nm.descendingMap(), keyType, valueType);
+        }
+
+        public NavigableSet<K> keySet() {
+            return navigableKeySet();
+        }
+
+        public NavigableSet<K> navigableKeySet() {
+            return checkedNavigableSet(nm.navigableKeySet(), keyType);
+        }
+
+        public NavigableSet<K> descendingKeySet() {
+            return checkedNavigableSet(nm.descendingKeySet(), keyType);
+        }
+
+        @Override
+        public NavigableMap<K,V> subMap(K fromKey, K toKey) {
+            return checkedNavigableMap(nm.subMap(fromKey, true, toKey, false),
+                                    keyType, valueType);
+        }
+
+        @Override
+        public NavigableMap<K,V> headMap(K toKey) {
+            return checkedNavigableMap(nm.headMap(toKey, false), keyType, valueType);
+        }
+
+        @Override
+        public NavigableMap<K,V> tailMap(K fromKey) {
+            return checkedNavigableMap(nm.tailMap(fromKey, true), keyType, valueType);
+        }
+
+        public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+            return checkedNavigableMap(nm.subMap(fromKey, fromInclusive, toKey, toInclusive), keyType, valueType);
+        }
+
+        public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+            return checkedNavigableMap(nm.headMap(toKey, inclusive), keyType, valueType);
+        }
+
+        public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+            return checkedNavigableMap(nm.tailMap(fromKey, inclusive), keyType, valueType);
+        }
+    }
+
     // Empty collections
 
     /**
@@ -3623,7 +4444,50 @@
         private Object readResolve() {
             return EMPTY_SET;
         }
+    }
 
+    /**
+     * Returns an empty sorted set (immutable).  This set is serializable.
+     *
+     * <p>This example illustrates the type-safe way to obtain an empty
+     * sorted set:
+     * <pre> {@code
+     *     SortedSet<String> s = Collections.emptySortedSet();
+     * }</pre>
+     *
+     * @implNote Implementations of this method need not create a separate
+     * {@code SortedSet} object for each call.
+     *
+     * @param <E> type of elements, if there were any, in the set
+     * @return the empty sorted set
+     * @since 1.8
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> SortedSet<E> emptySortedSet() {
+        return (SortedSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
+    }
+
+    /**
+     * Returns an empty navigable set (immutable).  This set is serializable.
+     *
+     * <p>This example illustrates the type-safe way to obtain an empty
+     * navigable set:
+     * <pre> {@code
+     *     NavigableSet<String> s = Collections.emptyNavigableSet();
+     * }</pre>
+     *
+     * @implNote Implementations of this method need not
+     * create a separate {@code NavigableSet} object for each call.
+     *
+     * @param <E> type of elements, if there were any, in the set
+     * @return the empty navigable set
+     * @since 1.8
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> NavigableSet<E> emptyNavigableSet() {
+        return (NavigableSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
     }
 
     /**
@@ -3641,10 +4505,12 @@
      * <pre>
      *     List&lt;String&gt; s = Collections.emptyList();
      * </pre>
-     * Implementation note:  Implementations of this method need not
-     * create a separate <tt>List</tt> object for each call.   Using this
-     * method is likely to have comparable cost to using the like-named
-     * field.  (Unlike this method, the field does not provide type safety.)
+     *
+     * @implNote
+     * Implementations of this method need not create a separate <tt>List</tt>
+     * object for each call.   Using this method is likely to have comparable
+     * cost to using the like-named field.  (Unlike this method, the field does
+     * not provide type safety.)
      *
      * @param <T> type of elements, if there were any, in the list
      * @return an empty immutable list
@@ -3701,6 +4567,13 @@
             Objects.requireNonNull(filter);
             return false;
         }
+        @Override
+        public void replaceAll(UnaryOperator<E> operator) {
+            Objects.requireNonNull(operator);
+        }
+        @Override
+        public void sort(Comparator<? super E> c) {
+        }
 
         // Override default methods in Collection
         @Override
@@ -3711,15 +4584,6 @@
         @Override
         public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
 
-        @Override
-        public void replaceAll(UnaryOperator<E> operator) {
-            Objects.requireNonNull(operator);
-        }
-        @Override
-        public void sort(Comparator<? super E> c) {
-        }
-
-
         // Preserves singleton property
         private Object readResolve() {
             return EMPTY_LIST;
@@ -3759,6 +4623,50 @@
     }
 
     /**
+     * Returns an empty sorted map (immutable).  This map is serializable.
+     *
+     * <p>This example illustrates the type-safe way to obtain an empty map:
+     * <pre> {@code
+     *     SortedMap<String, Date> s = Collections.emptySortedMap();
+     * }</pre>
+     *
+     * @implNote Implementations of this method need not create a separate
+     * {@code SortedMap} object for each call.
+     *
+     * @param <K> the class of the map keys
+     * @param <V> the class of the map values
+     * @return an empty sorted map
+     * @since 1.8
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    public static final <K,V> SortedMap<K,V> emptySortedMap() {
+        return (SortedMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+    }
+
+    /**
+     * Returns an empty navigable map (immutable).  This map is serializable.
+     *
+     * <p>This example illustrates the type-safe way to obtain an empty map:
+     * <pre> {@code
+     *     NavigableMap<String, Date> s = Collections.emptyNavigableMap();
+     * }</pre>
+     *
+     * @implNote Implementations of this method need not create a separate
+     * {@code NavigableMap} object for each call.
+     *
+     * @param <K> the class of the map keys
+     * @param <V> the class of the map values
+     * @return an empty navigable map
+     * @since 1.8
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    public static final <K,V> NavigableMap<K,V> emptyNavigableMap() {
+        return (NavigableMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+    }
+
+    /**
      * @serial include
      */
     private static class EmptyMap<K,V>
@@ -3821,25 +4729,25 @@
 
         @Override
         public V computeIfAbsent(K key,
-                                 Function<? super K, ? extends V> mappingFunction) {
+                Function<? super K, ? extends V> mappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V computeIfPresent(K key,
-                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V compute(K key,
-                         BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V merge(K key, V value,
-                       BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
@@ -4022,15 +4930,16 @@
             throw new UnsupportedOperationException();
         }
         @Override
-        public Spliterator<E> spliterator() {
-            return singletonSpliterator(element);
-        }
         public void replaceAll(UnaryOperator<E> operator) {
             throw new UnsupportedOperationException();
         }
         @Override
         public void sort(Comparator<? super E> c) {
         }
+        @Override
+        public Spliterator<E> spliterator() {
+            return singletonSpliterator(element);
+        }
     }
 
     /**
@@ -4065,19 +4974,15 @@
             v = value;
         }
 
-        public int size()                          {return 1;}
+        public int size()                                           {return 1;}
+        public boolean isEmpty()                                {return false;}
+        public boolean containsKey(Object key)             {return eq(key, k);}
+        public boolean containsValue(Object value)       {return eq(value, v);}
+        public V get(Object key)              {return (eq(key, k) ? v : null);}
 
-        public boolean isEmpty()                   {return false;}
-
-        public boolean containsKey(Object key)     {return eq(key, k);}
-
-        public boolean containsValue(Object value) {return eq(value, v);}
-
-        public V get(Object key)                   {return (eq(key, k) ? v : null);}
-
-        private transient Set<K> keySet = null;
-        private transient Set<Map.Entry<K,V>> entrySet = null;
-        private transient Collection<V> values = null;
+        private transient Set<K> keySet;
+        private transient Set<Map.Entry<K,V>> entrySet;
+        private transient Collection<V> values;
 
         public Set<K> keySet() {
             if (keySet==null)
@@ -4136,25 +5041,25 @@
 
         @Override
         public V computeIfAbsent(K key,
-                                 Function<? super K, ? extends V> mappingFunction) {
+                Function<? super K, ? extends V> mappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V computeIfPresent(K key,
-                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V compute(K key,
-                         BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
 
         @Override
         public V merge(K key, V value,
-                       BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
     }
@@ -4753,7 +5658,6 @@
         public boolean removeIf(Predicate<? super E> filter) {
             return q.removeIf(filter);
         }
-
         @Override
         public Spliterator<E> spliterator() {return q.spliterator();}
         @Override
diff --git a/ojluni/src/main/java/sun/security/action/PutAllAction.java b/ojluni/src/main/java/sun/security/action/PutAllAction.java
deleted file mode 100644
index b58da23..0000000
--- a/ojluni/src/main/java/sun/security/action/PutAllAction.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-import java.util.Map;
-
-import java.security.Provider;
-import java.security.PrivilegedAction;
-
-/**
- * A convenience PrivilegedAction class for setting the properties of
- * a provider. See the SunRsaSign provider for a usage example.
- *
- * @see sun.security.rsa.SunRsaSign
- * @author  Andreas Sterbenz
- * @since   1.5
- */
-public class PutAllAction implements PrivilegedAction<Void> {
-
-    private final Provider provider;
-    private final Map map;
-
-    public PutAllAction(Provider provider, Map map) {
-        this.provider = provider;
-        this.map = map;
-    }
-
-    public Void run() {
-        provider.putAll(map);
-        return null;
-    }
-
-}
diff --git a/ojluni/src/main/native/Inet4AddressImpl.c b/ojluni/src/main/native/Inet4AddressImpl.c
deleted file mode 100644
index fce6d95..0000000
--- a/ojluni/src/main/native/Inet4AddressImpl.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2000, 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.
- */
-
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-
-#include "JNIHelp.h"
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-//#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
-#define HAS_GLIBC_GETHOSTBY_R   1
-//#endif
-
-#define SET_NONBLOCKING(fd) {           \
-        int flags = fcntl(fd, F_GETFL); \
-        flags |= O_NONBLOCK;            \
-        fcntl(fd, F_SETFL, flags);      \
-}
-
-/**
- * ping implementation.
- * Send a ICMP_ECHO_REQUEST packet every second until either the timeout
- * expires or a answer is received.
- * Returns true is an ECHO_REPLY is received, otherwise, false.
- */
-static jboolean
-ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,
-      struct sockaddr_in* netif, jint ttl) {
-    jint size;
-    jint n, hlen1, icmplen;
-    socklen_t len;
-    char sendbuf[1500];
-    char recvbuf[1500];
-    struct icmp *icmp;
-    struct ip *ip;
-    struct sockaddr_in sa_recv;
-    jchar pid;
-    jint tmout2, seq = 1;
-    struct timeval tv;
-    size_t plen;
-
-    /* icmp_id is a 16 bit data type, therefore down cast the pid */
-    pid = (jchar)getpid();
-    size = 60*1024;
-    setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
-    /*
-     * sets the ttl (max number of hops)
-     */
-    if (ttl > 0) {
-      setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
-    }
-    /*
-     * a specific interface was specified, so let's bind the socket
-     * to that interface to ensure the requests are sent only through it.
-     */
-    if (netif != NULL) {
-      if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
-        NET_ThrowNew(env, errno, "Can't bind socket");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-    }
-    /*
-     * Make the socket non blocking so we can use select
-     */
-    SET_NONBLOCKING(fd);
-    do {
-      /*
-       * create the ICMP request
-       */
-      icmp = (struct icmp *) sendbuf;
-      icmp->icmp_type = ICMP_ECHO;
-      icmp->icmp_code = 0;
-      icmp->icmp_id = htons(pid);
-      icmp->icmp_seq = htons(seq);
-      seq++;
-      gettimeofday(&tv, NULL);
-      memcpy(icmp->icmp_data, &tv, sizeof(tv));
-      plen = ICMP_ADVLENMIN + sizeof(tv);
-      icmp->icmp_cksum = 0;
-      icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);
-      /*
-       * send it
-       */
-      n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
-                 sizeof(struct sockaddr));
-      if (n < 0 && errno != EINPROGRESS ) {
-#ifdef __linux__
-        if (errno != EINVAL && errno != EHOSTUNREACH)
-          /*
-           * On some Linux versions, when a socket is bound to the loopback
-           * interface, sendto will fail and errno will be set to
-           * EINVAL or EHOSTUNREACH. When that happens, don't throw an
-           * exception, just return false.
-           */
-#endif /*__linux__ */
-          NET_ThrowNew(env, errno, "Can't send ICMP packet");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-
-      tmout2 = timeout > 1000 ? 1000 : timeout;
-      do {
-        tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
-        if (tmout2 >= 0) {
-          len = sizeof(sa_recv);
-          n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);
-          ip = (struct ip*) recvbuf;
-          hlen1 = (ip->ip_hl) << 2;
-          icmp = (struct icmp *) (recvbuf + hlen1);
-          icmplen = n - hlen1;
-          /*
-           * We did receive something, but is it what we were expecting?
-           * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
-           */
-          if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
-               && (ntohs(icmp->icmp_id) == pid)) {
-            if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
-              untagSocket(env, fd);
-              close(fd);
-              return JNI_TRUE;
-            }
-
-            if (him->sin_addr.s_addr == 0) {
-              untagSocket(env, fd);
-              close(fd);
-              return JNI_TRUE;
-            }
-         }
-
-        }
-      } while (tmout2 > 0);
-      timeout -= 1000;
-    } while (timeout >0);
-    untagSocket(env, fd);
-    close(fd);
-    return JNI_FALSE;
-}
-
-/*
- * Class:     java_net_Inet4AddressImpl
- * Method:    isReachable0
- * Signature: ([bI[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
-                                           jbyteArray addrArray,
-                                           jint timeout,
-                                           jbyteArray ifArray,
-                                           jint ttl) {
-    jint addr;
-    jbyte caddr[4];
-    jint fd;
-    struct sockaddr_in him;
-    struct sockaddr_in* netif = NULL;
-    struct sockaddr_in inf;
-    int len = 0;
-    int connect_rv = -1;
-    int sz;
-
-    memset((char *) caddr, 0, sizeof(caddr));
-    memset((char *) &him, 0, sizeof(him));
-    memset((char *) &inf, 0, sizeof(inf));
-    sz = (*env)->GetArrayLength(env, addrArray);
-    if (sz != 4) {
-      return JNI_FALSE;
-    }
-    (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-    addr = ((caddr[0]<<24) & 0xff000000);
-    addr |= ((caddr[1] <<16) & 0xff0000);
-    addr |= ((caddr[2] <<8) & 0xff00);
-    addr |= (caddr[3] & 0xff);
-    addr = htonl(addr);
-    him.sin_addr.s_addr = addr;
-    him.sin_family = AF_INET;
-    len = sizeof(him);
-    /*
-     * If a network interface was specified, let's create the address
-     * for it.
-     */
-    if (!(IS_NULL(ifArray))) {
-      memset((char *) caddr, 0, sizeof(caddr));
-      (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
-      addr = ((caddr[0]<<24) & 0xff000000);
-      addr |= ((caddr[1] <<16) & 0xff0000);
-      addr |= ((caddr[2] <<8) & 0xff00);
-      addr |= (caddr[3] & 0xff);
-      addr = htonl(addr);
-      inf.sin_addr.s_addr = addr;
-      inf.sin_family = AF_INET;
-      inf.sin_port = 0;
-      netif = &inf;
-    }
-
-    /*
-     * Let's try to create a RAW socket to send ICMP packets
-     * This usually requires "root" privileges, so it's likely to fail.
-     */
-    fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
-    if (fd != -1) {
-      /*
-       * It didn't fail, so we can use ICMP_ECHO requests.
-       */
-      tagSocket(env, fd);
-      return ping4(env, fd, &him, timeout, netif, ttl);
-    }
-
-    /*
-     * Can't create a raw socket, so let's try a TCP socket
-     */
-    fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);
-    if (fd == JVM_IO_ERR) {
-        /* note: if you run out of fds, you may not be able to load
-         * the exception class, and get a NoClassDefFoundError
-         * instead.
-         */
-        NET_ThrowNew(env, errno, "Can't create socket");
-        return JNI_FALSE;
-    }
-    tagSocket(env, fd);
-
-    if (ttl > 0) {
-      setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
-    }
-
-    /*
-     * A network interface was specified, so let's bind to it.
-     */
-    if (netif != NULL) {
-      if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
-        NET_ThrowNew(env, errno, "Can't bind socket");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-    }
-
-    /*
-     * Make the socket non blocking so we can use select/poll.
-     */
-    SET_NONBLOCKING(fd);
-
-    /* no need to use NET_Connect as non-blocking */
-    him.sin_port = htons(7);    /* Echo */
-    connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);
-
-    /**
-     * connection established or refused immediately, either way it means
-     * we were able to reach the host!
-     */
-    if (connect_rv == 0 || errno == ECONNREFUSED) {
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_TRUE;
-    } else {
-        int optlen;
-
-        switch (errno) {
-        case ENETUNREACH: /* Network Unreachable */
-        case EAFNOSUPPORT: /* Address Family not supported */
-        case EADDRNOTAVAIL: /* address is not available on  the  remote machine */
-#ifdef __linux__
-        case EINVAL:
-        case EHOSTUNREACH:
-          /*
-           * On some Linux versions, when a socket is bound to the loopback
-           * interface, connect will fail and errno will be set to EINVAL
-           * or EHOSTUNREACH.  When that happens, don't throw an exception,
-           * just return false.
-           */
-#endif /* __linux__ */
-          untagSocket(env, fd);
-          close(fd);
-          return JNI_FALSE;
-        }
-
-        if (errno != EINPROGRESS) {
-          NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
-                                       "connect failed");
-          untagSocket(env, fd);
-          close(fd);
-          return JNI_FALSE;
-        }
-
-        timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
-        if (timeout >= 0) {
-          /* has connection been established? */
-          optlen = sizeof(connect_rv);
-          if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
-                             &optlen) <0) {
-            connect_rv = errno;
-          }
-          if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
-            untagSocket(env, fd);
-            close(fd);
-            return JNI_TRUE;
-          }
-        }
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-    }
-}
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
index 85f2314..8129d4a 100644
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -44,7 +44,6 @@
 #include <netinet/icmp6.h>
 #endif
 
-#include "java_net_Inet4AddressImpl.h"
 #include "JNIHelp.h"
 
 #define NATIVE_METHOD(className, functionName, signature) \
@@ -137,296 +136,7 @@
         fcntl(fd, F_SETFL, flags);      \
 }
 
-#ifdef AF_INET6
-static jboolean
-ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
-      struct sockaddr_in6* netif, jint ttl) {
-    jint size;
-    jint n;
-    socklen_t len;
-    char sendbuf[1500];
-    unsigned char recvbuf[1500];
-    struct icmp6_hdr *icmp6;
-    struct sockaddr_in6 sa_recv;
-    jbyte *caddr, *recv_caddr;
-    jchar pid;
-    jint tmout2, seq = 1;
-    struct timeval tv;
-    size_t plen;
-
-#ifdef __linux__
-    {
-    int csum_offset;
-    /**
-     * For some strange reason, the linux kernel won't calculate the
-     * checksum of ICMPv6 packets unless you set this socket option
-     */
-    csum_offset = 2;
-    setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
-    }
-#endif
-
-    caddr = (jbyte *)&(him->sin6_addr);
-
-    /* icmp_id is a 16 bit data type, therefore down cast the pid */
-    pid = (jchar)getpid();
-    size = 60*1024;
-    setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
-    if (ttl > 0) {
-      setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
-    }
-    if (netif != NULL) {
-      if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
-        NET_ThrowNew(env, errno, "Can't bind socket");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-    }
-    SET_NONBLOCKING(fd);
-
-    do {
-      icmp6 = (struct icmp6_hdr *) sendbuf;
-      icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
-      icmp6->icmp6_code = 0;
-      /* let's tag the ECHO packet with our pid so we can identify it */
-      icmp6->icmp6_id = htons(pid);
-      icmp6->icmp6_seq = htons(seq);
-      seq++;
-      icmp6->icmp6_cksum = 0;
-      gettimeofday(&tv, NULL);
-      memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
-      plen = sizeof(struct icmp6_hdr) + sizeof(tv);
-      n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
-      if (n < 0 && errno != EINPROGRESS) {
-#ifdef __linux__
-        if (errno != EINVAL && errno != EHOSTUNREACH)
-          /*
-           * On some Linux versions, when a socket is  bound to the
-           * loopback interface, sendto will fail and errno will be
-           * set to EINVAL or EHOSTUNREACH.
-           * When that happens, don't throw an exception, just return false.
-           */
-#endif /*__linux__ */
-        NET_ThrowNew(env, errno, "Can't send ICMP packet");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-
-      tmout2 = timeout > 1000 ? 1000 : timeout;
-      do {
-        tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
-
-        if (tmout2 >= 0) {
-          len = sizeof(sa_recv);
-          n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);
-          icmp6 = (struct icmp6_hdr *) (recvbuf);
-          recv_caddr = (jbyte *)&(sa_recv.sin6_addr);
-          /*
-           * We did receive something, but is it what we were expecting?
-           * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
-           *       from the host that we are trying to determine is reachable.
-           */
-          if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
-              (ntohs(icmp6->icmp6_id) == pid)) {
-            if (NET_IsEqual(caddr, recv_caddr)) {
-              untagSocket(env, fd);
-              close(fd);
-              return JNI_TRUE;
-            }
-            if (NET_IsZeroAddr(caddr)) {
-              untagSocket(env, fd);
-              close(fd);
-              return JNI_TRUE;
-            }
-          }
-        }
-      } while (tmout2 > 0);
-      timeout -= 1000;
-    } while (timeout > 0);
-    untagSocket(env, fd);
-    close(fd);
-    return JNI_FALSE;
-}
-#endif /* AF_INET6 */
-
-/*
- * Class:     java_net_Inet6AddressImpl
- * Method:    isReachable0
- * Signature: ([bII[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
-                                           jbyteArray addrArray,
-                                           jint scope,
-                                           jint timeout,
-                                           jbyteArray ifArray,
-                                           jint ttl, jint if_scope) {
-#ifdef AF_INET6
-    jbyte caddr[16];
-    jint fd, sz;
-    struct sockaddr_in6 him6;
-    struct sockaddr_in6 inf6;
-    struct sockaddr_in6* netif = NULL;
-    int len = 0;
-    int connect_rv = -1;
-
-    /*
-     * If IPv6 is not enable, then we can't reach an IPv6 address, can we?
-     */
-    if (!ipv6_available()) {
-      return JNI_FALSE;
-    }
-    /*
-     * If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
-     * therefore, let's delegate to the Inet4Address method.
-     */
-    sz = (*env)->GetArrayLength(env, addrArray);
-    if (sz == 4) {
-      return Inet4AddressImpl_isReachable0(env, this,
-                                                         addrArray,
-                                                         timeout,
-                                                         ifArray, ttl);
-    }
-
-    memset((void *) caddr, 0, 16);
-    memset((void *) &him6, 0, sizeof(him6));
-    (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
-    memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
-    him6.sin6_family = AF_INET6;
-
-    // Android-change: Don't try and figure out a default scope ID if one isn't
-    // set. It's only useful for link local addresses anyway, and callers are
-    // expected to call isReachable with a specific NetworkInterface if they
-    // want to query the reachability of an address that's local to that IF.
-    if (scope > 0)
-      him6.sin6_scope_id = scope;
-    len = sizeof(struct sockaddr_in6);
-    /*
-     * If a network interface was specified, let's create the address
-     * for it.
-     */
-    if (!(IS_NULL(ifArray))) {
-      memset((void *) caddr, 0, 16);
-      memset((void *) &inf6, 0, sizeof(inf6));
-      (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
-      memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
-      inf6.sin6_family = AF_INET6;
-      inf6.sin6_scope_id = if_scope;
-      netif = &inf6;
-    }
-    /*
-     * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
-     * otherwise we'll try a tcp socket to the Echo port (7).
-     * Note that this is empiric, and not connecting could mean it's blocked
-     * or the echo service has been disabled.
-     */
-
-    fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-
-    if (fd != -1) { /* Good to go, let's do a ping */
-        tagSocket(env, fd);
-        return ping6(env, fd, &him6, timeout, netif, ttl);
-    }
-
-    /* No good, let's fall back on TCP */
-    fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
-    if (fd == JVM_IO_ERR) {
-        /* note: if you run out of fds, you may not be able to load
-         * the exception class, and get a NoClassDefFoundError
-         * instead.
-         */
-        NET_ThrowNew(env, errno, "Can't create socket");
-        return JNI_FALSE;
-    }
-    tagSocket(env, fd);
-
-    if (ttl > 0) {
-      setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
-    }
-
-    /*
-     * A network interface was specified, so let's bind to it.
-     */
-    if (netif != NULL) {
-      if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
-        NET_ThrowNew(env, errno, "Can't bind socket");
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-      }
-    }
-    SET_NONBLOCKING(fd);
-
-    /* no need to use NET_Connect as non-blocking */
-    him6.sin6_port = htons((short) 7); /* Echo port */
-    connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
-
-    /**
-     * connection established or refused immediately, either way it means
-     * we were able to reach the host!
-     */
-    if (connect_rv == 0 || errno == ECONNREFUSED) {
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_TRUE;
-    } else {
-        int optlen;
-
-        switch (errno) {
-        case ENETUNREACH: /* Network Unreachable */
-        case EAFNOSUPPORT: /* Address Family not supported */
-        case EADDRNOTAVAIL: /* address is not available on  the  remote machine */
-#ifdef __linux__
-        case EINVAL:
-        case EHOSTUNREACH:
-          /*
-           * On some Linuxes, when bound to the loopback interface, connect
-           * loopback interface, connect will fail and errno will
-           * be set to EINVAL or EHOSTUNREACH.  When that happens,
-           * don't throw an exception, just return false.
-           */
-#endif /* __linux__ */
-          untagSocket(env, fd);
-          close(fd);
-          return JNI_FALSE;
-        }
-
-        if (errno != EINPROGRESS) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
-                                         "connect failed");
-            untagSocket(env, fd);
-            close(fd);
-            return JNI_FALSE;
-        }
-
-        timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
-
-        if (timeout >= 0) {
-          /* has connection been established */
-          optlen = sizeof(connect_rv);
-          if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
-                             &optlen) <0) {
-            connect_rv = errno;
-          }
-          if (connect_rv == 0 || ECONNREFUSED) {
-            untagSocket(env, fd);
-            close(fd);
-            return JNI_TRUE;
-          }
-        }
-        untagSocket(env, fd);
-        close(fd);
-        return JNI_FALSE;
-    }
-#else /* AF_INET6 */
-    return JNI_FALSE;
-#endif /* AF_INET6 */
-}
-
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Inet6AddressImpl, isReachable0, "([BII[BII)Z"),
   NATIVE_METHOD(Inet6AddressImpl, getHostByAddr0, "([B)Ljava/lang/String;"),
 };
 
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index 0d31d02..9d40c16 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -25,12 +25,13 @@
 
 #define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
 
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include <android/log.h>
+
 #include "JniConstants.h"
 #include "ScopedLocalFrame.h"
 
-#include <stdlib.h>
-
 extern "C" {
 
 extern void register_java_io_Console(JNIEnv* env);
diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c
index 4c547c0..3386e47 100644
--- a/ojluni/src/main/native/System.c
+++ b/ojluni/src/main/native/System.c
@@ -22,19 +22,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include <string.h>
-#include <stdlib.h>
 
+#include <stdlib.h>
+#include <string.h>
+
+#include <android/log.h>
+
+#include "io_util.h"
 #include "jni.h"
 #include "jni_util.h"
 #include "jvm.h"
-#include "io_util.h"
-
 
 #include "openssl/opensslv.h"
 #include "zlib.h"
 #include "JNIHelp.h"
-#include "cutils/log.h"
 #if defined(__ANDROID__)
 void android_get_LD_LIBRARY_PATH(char*, size_t);
 #endif
diff --git a/ojluni/src/main/native/java_net_Inet4AddressImpl.h b/ojluni/src/main/native/java_net_Inet4AddressImpl.h
deleted file mode 100644
index 8ee8820..0000000
--- a/ojluni/src/main/native/java_net_Inet4AddressImpl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This file was generated from java/net/Inet4AddressImpl.java and
- * is licensed under the same terms.  The copyright and license information
- * for java/net/Inet4AddressImpl.java follows.
- *
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
- * 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.
- */
-
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class java_net_Inet4AddressImpl */
-
-#ifndef _Included_java_net_Inet4AddressImpl
-#define _Included_java_net_Inet4AddressImpl
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     java_net_Inet4AddressImpl
- * Method:    getLocalHostName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getLocalHostName
-  (JNIEnv *, jobject);
-
-/*
- * Class:     java_net_Inet4AddressImpl
- * Method:    lookupAllHostAddr
- * Signature: (Ljava/lang/String;)[Ljava/net/InetAddress;
- */
-JNIEXPORT jobjectArray JNICALL Inet4AddressImpl_lookupAllHostAddr
-  (JNIEnv *, jobject, jstring);
-
-/*
- * Class:     java_net_Inet4AddressImpl
- * Method:    getHostByAddr
- * Signature: ([B)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getHostByAddr
-  (JNIEnv *, jobject, jbyteArray);
-
-/*
- * Class:     java_net_Inet4AddressImpl
- * Method:    isReachable0
- * Signature: ([BI[BI)Z
- */
-JNIEXPORT jboolean JNICALL Inet4AddressImpl_isReachable0
-  (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 3a3fcb0..ff82754 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -54,7 +54,6 @@
     PlainSocketImpl.c \
     PlainDatagramSocketImpl.c \
     DatagramPacket.c \
-    Inet4AddressImpl.c \
     Inet6AddressImpl.c \
     ServerSocketChannelImpl.c \
     SocketInputStream.c \
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 6a1c3e6..8bf5681 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1421,7 +1421,6 @@
     ojluni/src/main/java/sun/security/action/GetIntegerAction.java \
     ojluni/src/main/java/sun/security/action/GetPropertyAction.java \
     ojluni/src/main/java/sun/security/action/LoadLibraryAction.java \
-    ojluni/src/main/java/sun/security/action/PutAllAction.java \
     ojluni/src/main/java/sun/security/jca/GetInstance.java \
     ojluni/src/main/java/sun/security/jca/JCAUtil.java \
     ojluni/src/main/java/sun/security/jca/ProviderConfig.java \
diff --git a/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
new file mode 100644
index 0000000..b5acc82
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
@@ -0,0 +1,112 @@
+/*
+ * 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.junit.junit3;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.MultipleFailureException;
+import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+
+import static org.junit.internal.runners.rules.RuleFieldValidator.RULE_VALIDATOR;
+
+/**
+ * A {@link TestCase} that supports the @Rule annotation from JUnit 4.
+ *
+ * <p>It supports both {@link TestRule} and {@link MethodRule} based rules when used with the
+ * {@code @Rule} annotation on public fields. The rules encapsulate the {@link TestCase#runBare()}
+ * method and so are run before the {@link TestCase#setUp()} and after the
+ * {@link TestCase#tearDown()} methods.
+ *
+ * <p>Classes that extend this must have a single no argument constructor.
+ */
+public abstract class TestCaseWithRules extends TestCase {
+
+    private final TestClass testClass;
+
+    private final List<Throwable> validationErrors;
+
+    public TestCaseWithRules() {
+        testClass = new TestClass(getClass());
+
+        validationErrors = new ArrayList<>();
+        RULE_VALIDATOR.validate(testClass, validationErrors);
+    }
+
+    @Override
+    public void runBare() throws Throwable {
+        if (!validationErrors.isEmpty()) {
+            throw new MultipleFailureException(validationErrors);
+        }
+
+        Statement statement = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                superRunBare();
+            }
+        };
+
+        final String name = getName();
+        FrameworkMethod frameworkMethod;
+        try {
+            Method method = getClass().getMethod(name, (Class[]) null);
+            frameworkMethod = new FrameworkMethod(method);
+        } catch (NoSuchMethodException e) {
+            frameworkMethod = new FrameworkMethod(null) {
+                @Override
+                public String getName() {
+                    return name;
+                }
+
+                @Override
+                public Annotation[] getAnnotations() {
+                    return new Annotation[0];
+                }
+
+                @Override
+                public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+                    return null;
+                }
+            };
+        }
+        Description description =
+                Description.createTestDescription(getClass(), frameworkMethod.getName(),
+                        frameworkMethod.getAnnotations());
+
+        List<Object> rules = testClass.getAnnotatedFieldValues(this, Rule.class, Object.class);
+        for (Object rule : rules) {
+            if (rule instanceof TestRule) {
+                statement = ((TestRule) rule).apply(statement, description);
+            } else {
+                statement = ((MethodRule) rule).apply(statement, frameworkMethod, this);
+            }
+        }
+
+        statement.evaluate();
+    }
+
+    private void superRunBare() throws Throwable {
+        super.runBare();
+    }
+}
diff --git a/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
new file mode 100644
index 0000000..dae7978
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
@@ -0,0 +1,150 @@
+/*
+ * 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.junit.util;
+
+import java.lang.reflect.Method;
+import java.util.function.BiConsumer;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that own resources which must not leak.
+ *
+ * <p><strong>This will not detect any resource leakages in OpenJDK</strong></p>
+ */
+public class ResourceLeakageDetector {
+    private static final LeakageDetectorRule LEAKAGE_DETECTOR_RULE;
+    private static final BiConsumer<Object, Integer> FINALIZER_CHECKER;
+
+    static {
+        LeakageDetectorRule leakageDetectorRule;
+        BiConsumer<Object, Integer> finalizerChecker;
+        try {
+            // Make sure that the CloseGuard class exists; this ensures that this is not
+            // running on a RI JVM.
+            Class.forName("dalvik.system.CloseGuard");
+
+            // Access the underlying support class using reflection in order to prevent any compile
+            // time dependencies on it so as to allow this to compile on OpenJDK.
+            Class<?> closeGuardSupportClass = Class.forName("dalvik.system.CloseGuardSupport");
+            Method method = closeGuardSupportClass.getMethod("getRule");
+            leakageDetectorRule = new LeakageDetectorRule((TestRule) method.invoke(null));
+
+            finalizerChecker = getFinalizerChecker(closeGuardSupportClass);
+
+        } catch (ReflectiveOperationException e) {
+            System.err.println("Resource leakage will not be detected; "
+                    + "this is expected in the reference implementation");
+            e.printStackTrace(System.err);
+
+            // Could not access the class for some reason so have a rule that does nothing and a
+            // finalizer checker that checks nothing. This should ensure that tests work properly
+            // on OpenJDK even though it does not support CloseGuard.
+            leakageDetectorRule = new LeakageDetectorRule(RuleChain.emptyRuleChain());
+            finalizerChecker = new BiConsumer<Object, Integer>() {
+                @Override
+                public void accept(Object o, Integer integer) {
+                    // Do nothing.
+                }
+            };
+        }
+
+        LEAKAGE_DETECTOR_RULE = leakageDetectorRule;
+        FINALIZER_CHECKER = finalizerChecker;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static BiConsumer<Object, Integer> getFinalizerChecker(Class<?> closeGuardSupportClass)
+            throws ReflectiveOperationException {
+        Method method = closeGuardSupportClass.getMethod("getFinalizerChecker");
+        return (BiConsumer<Object, Integer>) method.invoke(null);
+    }
+
+    /**
+     * @return the {@link LeakageDetectorRule}
+     */
+    public static LeakageDetectorRule getRule() {
+       return LEAKAGE_DETECTOR_RULE;
+    }
+
+    /**
+     * A {@link TestRule} that will fail a test if it detects any resources that were allocated
+     * during the test but were not released.
+     *
+     * <p>This only tracks resources that were allocated on the test thread, although it does not
+     * care what thread they were released on. This avoids flaky false positives where a background
+     * thread allocates a resource during a test but releases it after the test.
+     *
+     * <p>It is still possible to have a false positive in the case where the test causes a caching
+     * mechanism to open a resource and hold it open past the end of the test. In that case if there
+     * is no way to clear the cached data then it should be relatively simple to move the code that
+     * invokes the caching mechanism to outside the scope of this rule. i.e.
+     *
+     * <pre>{@code
+     *     @Rule
+     *     public final TestRule ruleChain = org.junit.rules.RuleChain
+     *         .outerRule(new ...invoke caching mechanism...)
+     *         .around(CloseGuardSupport.getRule());
+     * }</pre>
+     *
+     * @return a {@link TestRule} that detects resource leakages, or one that does nothing if
+     * resource leakage detection is not supported.
+     */
+    public static class LeakageDetectorRule implements TestRule {
+
+        private final TestRule leakageDetectorRule;
+
+        private LeakageDetectorRule(TestRule leakageDetectorRule) {
+            this.leakageDetectorRule = leakageDetectorRule;
+        }
+
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return leakageDetectorRule.apply(base, description);
+        }
+
+        /**
+         * Ensure that when the supplied object is finalized that it detects the expected number of
+         * unreleased resources.
+         *
+         * <p>This helps ensure that classes which own resources protected using {@code CloseGuard}
+         * support leakage detection.
+         *
+         * <p>This must only be called from within the test currently being run otherwise it will
+         * fail if the resource leakage detected mechanism is disabled, e.g. in CTS.
+         *
+         * <p>Use as follows:
+         * <pre>
+         *     Object object = ...create and 'open' an object encapsulating a protected resource...;
+         *     // Check to make sure that the object reports a resource leak when it is finalized.
+         *     assertUnreleasedResourceCount(object, 1);
+         *
+         *     object = ... create, 'open' and then 'close' another object ...;
+         *     // Check to make sure that the object does not have any unreleased resources.
+         *     assertUnreleasedResourceCount(object, 0);
+         * </pre>
+         *
+         * @param owner the object that owns the resource and uses {@code CloseGuard} object to detect
+         * when the resource is not released.
+         * @param expectedCount the expected number of unreleased resources.
+         */
+        public void assertUnreleasedResourceCount(Object owner, int expectedCount) {
+            FINALIZER_CHECKER.accept(owner, expectedCount);
+        }
+    }
+}