Merge "sun.security.action.PutAllAction: remove unused class"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 470484e..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)
@@ -188,9 +206,15 @@
 LOCAL_SRC_FILES := $(test_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs okhttp core-junit junit4-target bouncycastle mockito-target
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp core-junit junit4-target bouncycastle mockito-target
+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
@@ -217,7 +241,7 @@
 LOCAL_SRC_FILES :=  $(call all-test-java-files-under, jsr166-tests)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs core-junit junit4-target
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit junit4-target
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := jsr166-tests
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -229,7 +253,7 @@
 ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs okhttp bouncycastle
+    LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp bouncycastle
     LOCAL_STATIC_JAVA_LIBRARIES := testng
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
@@ -249,7 +273,7 @@
     # Include source code as part of JAR
     LOCAL_JAVA_RESOURCE_DIRS := ojluni/src/test/dist
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs okhttp bouncycastle testng
+    LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp bouncycastle testng
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -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 core-lambda-stubs-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex junit4-target-hostdex core-tests-support-hostdex mockito-api-hostdex
-    LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
+    LOCAL_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 core-test-rules-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -365,7 +389,7 @@
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES := $(ojtest_src_files)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-lambda-stubs-hostdex okhttp-hostdex bouncycastle-hostdex
+    LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex okhttp-hostdex bouncycastle-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := testng-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
diff --git a/NativeCode.mk b/NativeCode.mk
index cc31819..7c3efbc 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -229,7 +229,7 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libjavacore
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat libicuuc-host libicui18n-host libcrypto libz-host libziparchive
+LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat libicuuc libicui18n libcrypto libz-host libziparchive
 LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
 LOCAL_MULTILIB := both
 LOCAL_CXX_STL := libc++
@@ -241,7 +241,7 @@
 LOCAL_C_INCLUDES := $(core_c_includes)
 LOCAL_CFLAGS := -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -DLINUX -D__GLIBC__ # Sigh.
 LOCAL_CFLAGS += $(openjdk_cflags)
-LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libicuuc-host libcrypto libz-host
+LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libicuuc libcrypto libz-host
 LOCAL_SHARED_LIBRARIES += libopenjdkjvmd libnativehelper
 LOCAL_STATIC_LIBRARIES := $(core_static_libraries) libfdlibm
 LOCAL_MODULE_TAGS := optional
@@ -256,7 +256,7 @@
 LOCAL_C_INCLUDES := $(core_c_includes)
 LOCAL_CFLAGS := -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -DLINUX -D__GLIBC__ # Sigh.
 LOCAL_CFLAGS += $(openjdk_cflags)
-LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libicuuc-host libcrypto libz-host
+LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libicuuc libcrypto libz-host
 LOCAL_SHARED_LIBRARIES += libopenjdkjvm libnativehelper
 LOCAL_STATIC_LIBRARIES := $(core_static_libraries) libfdlibm
 LOCAL_MODULE_TAGS := optional
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/benchmarks/src/benchmarks/regression/NativeMethodBenchmark.java b/benchmarks/src/benchmarks/regression/NativeMethodBenchmark.java
index c30ea08..dbb6308 100644
--- a/benchmarks/src/benchmarks/regression/NativeMethodBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/NativeMethodBenchmark.java
@@ -32,11 +32,6 @@
         }
     }
 
-    public void time_emptyJniStaticMethod0(int reps) throws Exception {
-        for (int i = 0; i < reps; ++i) {
-            NativeTestTarget.emptyJniStaticMethod0();
-        }
-    }
 
     public void time_emptyJniMethod0(int reps) throws Exception {
         NativeTestTarget n = new NativeTestTarget();
@@ -45,14 +40,6 @@
         }
     }
 
-    public void time_emptyJniStaticMethod6(int reps) throws Exception {
-        int a = -1;
-        int b = 0;
-        for (int i = 0; i < reps; ++i) {
-            NativeTestTarget.emptyJniStaticMethod6(a, b, 1, 2, 3, i);
-        }
-    }
-
     public void time_emptyJniMethod6(int reps) throws Exception {
         int a = -1;
         int b = 0;
@@ -62,12 +49,6 @@
         }
     }
 
-    public void time_emptyJniStaticMethod6L(int reps) throws Exception {
-        for (int i = 0; i < reps; ++i) {
-            NativeTestTarget.emptyJniStaticMethod6L(null, null, null, null, null, null);
-        }
-    }
-
     public void time_emptyJniMethod6L(int reps) throws Exception {
         NativeTestTarget n = new NativeTestTarget();
         for (int i = 0; i < reps; ++i) {
@@ -75,4 +56,78 @@
         }
     }
 
+    public void time_emptyJniStaticMethod6L(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod6L(null, null, null, null, null, null);
+        }
+    }
+    public void time_emptyJniStaticMethod0(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod0();
+        }
+    }
+
+    public void time_emptyJniStaticMethod6(int reps) throws Exception {
+        int a = -1;
+        int b = 0;
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod6(a, b, 1, 2, 3, i);
+        }
+    }
+
+    public void time_emptyJniMethod0_Fast(int reps) throws Exception {
+        NativeTestTarget n = new NativeTestTarget();
+        for (int i = 0; i < reps; ++i) {
+            n.emptyJniMethod0_Fast();
+        }
+    }
+
+    public void time_emptyJniMethod6_Fast(int reps) throws Exception {
+        int a = -1;
+        int b = 0;
+        NativeTestTarget n = new NativeTestTarget();
+        for (int i = 0; i < reps; ++i) {
+            n.emptyJniMethod6_Fast(a, b, 1, 2, 3, i);
+        }
+    }
+
+    public void time_emptyJniMethod6L_Fast(int reps) throws Exception {
+        NativeTestTarget n = new NativeTestTarget();
+        for (int i = 0; i < reps; ++i) {
+            n.emptyJniMethod6L_Fast(null, null, null, null, null, null);
+        }
+    }
+
+    public void time_emptyJniStaticMethod6L_Fast(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod6L_Fast(null, null, null, null, null, null);
+        }
+    }
+    public void time_emptyJniStaticMethod0_Fast(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod0_Fast();
+        }
+    }
+
+    public void time_emptyJniStaticMethod6_Fast(int reps) throws Exception {
+        int a = -1;
+        int b = 0;
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod6_Fast(a, b, 1, 2, 3, i);
+        }
+    }
+
+    public void time_emptyJniStaticMethod0_Critical(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod0_Critical();
+        }
+    }
+
+    public void time_emptyJniStaticMethod6_Critical(int reps) throws Exception {
+        int a = -1;
+        int b = 0;
+        for (int i = 0; i < reps; ++i) {
+            NativeTestTarget.emptyJniStaticMethod6_Critical(a, b, 1, 2, 3, i);
+        }
+    }
 }
diff --git a/dalvik/src/main/java/dalvik/annotation/MethodParameters.java b/dalvik/src/main/java/dalvik/annotation/MethodParameters.java
new file mode 100644
index 0000000..ef30197
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/annotation/MethodParameters.java
@@ -0,0 +1,93 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Parameter;
+
+/**
+ * A "system annotation" that can optionally be used to provide parameter metadata such as
+ * parameter names and modifiers.
+ *
+ * <p>The annotation can be omitted from a method / constructor safely when the parameter metadata
+ * is not needed / desired at runtime. {@link Parameter#isNamePresent()} can be used to check
+ * whether metadata is present for a parameter, and the associated reflection methods like
+ * {@link java.lang.reflect.Parameter#getName()} will fall back to default behavior at runtime if
+ * the information is not present.
+ *
+ * <p>When including parameter metadata, compilers should include parameter metadata for generated
+ * classes like enums, since the parameter metadata includes whether or not a parameter is
+ * synthetic or mandated.
+ *
+ * <p>MethodParameters currently only describes individual method parameters and there is no
+ * mechanism to detect whether parameter method data is <em>generally</em> present for an
+ * {@link java.lang.reflect.Executable}. Therefore, it is code-size and runtime efficient to omit
+ * the annotation entirely for constructors and methods that have no parameters.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
+@interface MethodParameters {
+
+    /*
+     * This annotation is never used in source code; it is expected to be generated in .dex
+     * files by tools like compilers. Commented definitions for the annotation members expected
+     * by the runtime / reflection code can be found below for reference.
+     *
+     * The arrays documented below must be the same size as for the method_id_item dex structure
+     * associated with the method otherwise a java.lang.reflect.MalformedParametersException will
+     * be thrown at runtime.
+     *
+     * That is: method_id_item.proto_idx -> proto_id_item.parameters_off -> type_list.size must
+     * be the same as names().length and accessFlags().length.
+     *
+     * Because MethodParameters describes all formal method parameters, even those not explicitly
+     * or implicitly declared in source code, the size of the arrays may differ from the Signature
+     * or other metadata information that can be based only on explicit parameters declared in
+     * source code. MethodParameters will also not include any information about type annotation
+     * receiver parameters that do not exist in the actual method signature.
+     */
+
+
+    /*
+     * The names of formal parameters for the associated method. The array cannot be null, but can
+     * be empty if there are no formal parameters. A value in the array can be null if the formal
+     * parameter with that index has no name.
+     *
+     * If parameter name Strings are empty or contain '.', ';', '[' or '/' then a
+     * java.lang.reflect.MalformedParametersException will be thrown at runtime.
+     */
+    // String[] names();
+
+    /*
+     * The access flags of the formal parameters for the associated method. The array cannot be
+     * null, but can be empty if there are no formal parameters.
+     *
+     * The value is a bit mask with the follow values:
+     * 0x0010 : final, the parameter was declared final
+     * 0x1000 : synthetic, the parameter was introduced by the compiler.
+     * 0x8000 : mandated, the parameter is synthetic but also implied by the language
+     *          specification.
+     *
+     * If any bits are set outside of this set then a java.lang.reflect.MalformedParametersException
+     * will be thrown at runtime.
+     */
+    // int[] accessFlags();
+}
+
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index b9de236..6426bd8 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -66,6 +66,11 @@
         void onNetwork();
 
         /**
+         * Called on unbuffered input/ouput operations.
+         */
+        void onUnbufferedIO();
+
+        /**
          * Returns the policy bitmask, for shipping over Binder calls
          * to remote threads/processes and reinstantiating the policy
          * there.  The bits in the mask are from the DISALLOW_* and
@@ -118,6 +123,7 @@
             public void onWriteToDisk() {}
             public void onReadFromDisk() {}
             public void onNetwork() {}
+            public void onUnbufferedIO() {}
             public int getPolicyMask() {
                 return 0;
             }
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/main/java/org/apache/harmony/dalvik/NativeTestTarget.java b/dalvik/src/main/java/org/apache/harmony/dalvik/NativeTestTarget.java
index 5daf6a0..a9efabe 100644
--- a/dalvik/src/main/java/org/apache/harmony/dalvik/NativeTestTarget.java
+++ b/dalvik/src/main/java/org/apache/harmony/dalvik/NativeTestTarget.java
@@ -16,6 +16,9 @@
 
 package org.apache.harmony.dalvik;
 
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
 /**
  * Methods used to test calling into native code. The methods in this
  * class are all effectively no-ops and may be used to test the mechanisms
@@ -25,30 +28,6 @@
     public NativeTestTarget() {
     }
 
-    public static native synchronized void emptyJniStaticSynchronizedMethod0();
-
-    public native synchronized void emptyJniSynchronizedMethod0();
-
-    public static native void emptyJniStaticMethod0();
-
-    public native void emptyJniMethod0();
-
-    public static native void emptyJniStaticMethod6(int a, int b, int c, int d, int e, int f);
-
-    public native void emptyJniMethod6(int a, int b, int c, int d, int e, int f);
-
-    /**
-     * This is an empty native static method with six args, hooked up
-     * using JNI. These have more complex args to show the cost of
-     * parsing the signature. All six values should be null
-     * references.
-     */
-    public static native void emptyJniStaticMethod6L(String a, String[] b,
-        int[][] c, Object d, Object[] e, Object[][][][] f);
-
-    public native void emptyJniMethod6L(String a, String[] b,
-        int[][] c, Object d, Object[] e, Object[][][][] f);
-
     /**
      * This is used to benchmark dalvik's inline natives.
      */
@@ -59,4 +38,64 @@
      * This is used to benchmark dalvik's inline natives.
      */
     public static native void emptyInternalStaticMethod();
+
+    // Synchronized methods. Test normal JNI only.
+    public static native synchronized void emptyJniStaticSynchronizedMethod0();
+    public native synchronized void emptyJniSynchronizedMethod0();
+
+    // Static methods without object parameters. Test all optimization combinations.
+
+    // Normal native.
+    public static native void emptyJniStaticMethod0();
+    // Normal native.
+    public static native void emptyJniStaticMethod6(int a, int b, int c, int d, int e, int f);
+
+    @FastNative
+    public static native void emptyJniStaticMethod0_Fast();
+    @FastNative
+    public static native void emptyJniStaticMethod6_Fast(int a, int b, int c, int d, int e, int f);
+
+    @CriticalNative
+    public static native void emptyJniStaticMethod0_Critical();
+    @CriticalNative
+    public static native void emptyJniStaticMethod6_Critical(int a, int b, int c, int d, int e, int f);
+    // Instance methods or methods with object parameters. Test {Normal, @FastNative} combinations.
+
+    // Normal native.
+    public native void emptyJniMethod0();
+    // Normal native.
+    public native void emptyJniMethod6(int a, int b, int c, int d, int e, int f);
+
+    /**
+     * This is an empty native static method with six args, hooked up
+     * using JNI. These have more complex args to show the cost of
+     * parsing the signature. All six values should be null
+     * references.
+     */
+    // Normal native.
+    public static native void emptyJniStaticMethod6L(String a, String[] b,
+        int[][] c, Object d, Object[] e, Object[][][][] f);
+
+    // Normal native.
+    public native void emptyJniMethod6L(String a, String[] b,
+        int[][] c, Object d, Object[] e, Object[][][][] f);
+
+    @FastNative
+    public native void emptyJniMethod0_Fast();
+    @FastNative
+    public native void emptyJniMethod6_Fast(int a, int b, int c, int d, int e, int f);
+
+    /**
+     * This is an empty native static method with six args, hooked up
+     * using JNI. These have more complex args to show the cost of
+     * parsing the signature. All six values should be null
+     * references.
+     */
+    @FastNative
+    public static native void emptyJniStaticMethod6L_Fast(String a, String[] b,
+        int[][] c, Object d, Object[] e, Object[][][][] f);
+
+    @FastNative
+    public native void emptyJniMethod6L_Fast(String a, String[] b,
+        int[][] c, Object d, Object[] e, Object[][][][] f);
 }
diff --git a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
index 52f22a8..9a934f6 100644
--- a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
+++ b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
@@ -19,25 +19,62 @@
 #include "JNIHelp.h"
 #include "JniConstants.h"
 
-static void NativeTestTarget_emptyJniMethod0(JNIEnv*, jobject) { }
-static void NativeTestTarget_emptyJniMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
-static void NativeTestTarget_emptyJniMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject, jarray, jarray) { }
-static void NativeTestTarget_emptyJniStaticMethod0(JNIEnv*, jclass) { }
-static void NativeTestTarget_emptyJniStaticMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
-static void NativeTestTarget_emptyJniStaticMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject, jarray, jarray) { }
 static void NativeTestTarget_emptyJniStaticSynchronizedMethod0(JNIEnv*, jclass) { }
 static void NativeTestTarget_emptyJniSynchronizedMethod0(JNIEnv*, jclass) { }
 
+static JNINativeMethod gMethods_NormalOnly[] = {
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticSynchronizedMethod0, "()V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniSynchronizedMethod0, "()V"),
+};
+
+
+static void NativeTestTarget_emptyJniMethod0(JNIEnv*, jobject) { }
+static void NativeTestTarget_emptyJniMethod6(JNIEnv*, jobject, int, int, int, int, int, int) { }
+static void NativeTestTarget_emptyJniMethod6L(JNIEnv*, jobject, jobject, jarray, jarray, jobject, jarray, jarray) { }
+static void NativeTestTarget_emptyJniStaticMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject, jarray, jarray) { }
+
+static void NativeTestTarget_emptyJniStaticMethod0(JNIEnv*, jclass) { }
+static void NativeTestTarget_emptyJniStaticMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
+
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(NativeTestTarget, emptyJniMethod0, "()V"),
     NATIVE_METHOD(NativeTestTarget, emptyJniMethod6, "(IIIIII)V"),
     NATIVE_METHOD(NativeTestTarget, emptyJniMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
     NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod0, "()V"),
     NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6, "(IIIIII)V"),
-    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
-    NATIVE_METHOD(NativeTestTarget, emptyJniStaticSynchronizedMethod0, "()V"),
-    NATIVE_METHOD(NativeTestTarget, emptyJniSynchronizedMethod0, "()V"),
+};
+
+static void NativeTestTarget_emptyJniMethod0_Fast(JNIEnv*, jobject) { }
+static void NativeTestTarget_emptyJniMethod6_Fast(JNIEnv*, jobject, int, int, int, int, int, int) { }
+static void NativeTestTarget_emptyJniMethod6L_Fast(JNIEnv*, jobject, jobject, jarray, jarray, jobject, jarray, jarray) { }
+static void NativeTestTarget_emptyJniStaticMethod6L_Fast(JNIEnv*, jclass, jobject, jarray, jarray, jobject, jarray, jarray) { }
+
+static void NativeTestTarget_emptyJniStaticMethod0_Fast(JNIEnv*, jclass) { }
+static void NativeTestTarget_emptyJniStaticMethod6_Fast(JNIEnv*, jclass, int, int, int, int, int, int) { }
+
+static JNINativeMethod gMethods_Fast[] = {
+    NATIVE_METHOD(NativeTestTarget, emptyJniMethod0_Fast, "()V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniMethod6_Fast, "(IIIIII)V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod0_Fast, "()V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6_Fast, "(IIIIII)V"),
+};
+
+
+static void NativeTestTarget_emptyJniStaticMethod0_Critical() { }
+static void NativeTestTarget_emptyJniStaticMethod6_Critical( int, int, int, int, int, int) { }
+
+static JNINativeMethod gMethods_Critical[] = {
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod0_Critical, "()V"),
+    NATIVE_METHOD(NativeTestTarget, emptyJniStaticMethod6_Critical, "(IIIIII)V"),
 };
 int register_org_apache_harmony_dalvik_NativeTestTarget(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/NativeTestTarget", gMethods, NELEM(gMethods));
+    jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/NativeTestTarget", gMethods_NormalOnly, NELEM(gMethods_NormalOnly));
+    jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/NativeTestTarget", gMethods, NELEM(gMethods));
+    jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/NativeTestTarget", gMethods_Fast, NELEM(gMethods_Fast));
+    jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/NativeTestTarget", gMethods_Critical, NELEM(gMethods_Critical));
+
+    return 0;
 }
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/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 1cf37c9..a2ff4ee 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1548,5 +1548,13 @@
   names: [
     "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderImplTest#test_Constructor$Ljava_net_URLLjava_lang_ClassLoaderLjava_net_URLStreamHandlerFactory"
   ]
+},
+{
+  description: "Waiting for ICU 58 to be merged",
+  bug: 31516121,
+  result: EXEC_FAILED,
+  names: [
+    "libcore.java.text.OldBidiTest#testUnicode9EmojisAreLtrNeutral"
+  ]
 }
 ]
diff --git a/expectations/virtualdeviceknownfailures.txt b/expectations/virtualdeviceknownfailures.txt
new file mode 100644
index 0000000..f427a71
--- /dev/null
+++ b/expectations/virtualdeviceknownfailures.txt
@@ -0,0 +1,11 @@
+/*
+ * This file contains expectations for tests known to fail on virtual device
+ */
+[
+{
+  description: "IPv6 connectivity not yet supported in virtual device testing infra",
+  result: EXEC_FAILED,
+  name: "libcore.java.net.SocketTest#testSocketTestAllAddresses",
+  bug: 30965313
+}
+]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
index 948059b..6253b6b 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
@@ -18,6 +18,7 @@
 package org.apache.harmony.tests.java.io;
 
 import dalvik.system.DexFile;
+import dalvik.system.VMRuntime;
 import java.io.Externalizable;
 import java.io.File;
 import java.io.IOException;
@@ -28,6 +29,7 @@
 import java.io.ObjectStreamField;
 import java.io.Serializable;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.nio.file.Files;
@@ -227,20 +229,43 @@
 
     // http://b/28106822
     public void testBug28106822() throws Exception {
-        Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
-                "getConstructorId", Class.class);
-        getConstructorId.setAccessible(true);
+        int savedTargetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+        try {
+            // Assert behavior up to 24
+            VMRuntime.getRuntime().setTargetSdkVersion(24);
+            Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
+                    "getConstructorId", Class.class);
+            getConstructorId.setAccessible(true);
 
-        assertEquals(1189998819991197253L, getConstructorId.invoke(null, Object.class));
-        assertEquals(1189998819991197253L, getConstructorId.invoke(null, String.class));
+            assertEquals(1189998819991197253L, getConstructorId.invoke(null, Object.class));
+            assertEquals(1189998819991197253L, getConstructorId.invoke(null, String.class));
 
-        Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance",
-                Class.class, Long.TYPE);
-        newInstance.setAccessible(true);
+            Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance",
+                    Class.class, Long.TYPE);
+            newInstance.setAccessible(true);
 
-        Object obj = newInstance.invoke(null, String.class, 0 /* ignored */);
-        assertNotNull(obj);
-        assertTrue(obj instanceof String);
+            Object obj = newInstance.invoke(null, String.class, 0 /* ignored */);
+            assertNotNull(obj);
+            assertTrue(obj instanceof String);
+
+            // Assert behavior from API 25
+            VMRuntime.getRuntime().setTargetSdkVersion(25);
+            try {
+                getConstructorId.invoke(null, Object.class);
+                fail();
+            } catch (InvocationTargetException expected) {
+                assertTrue(expected.getCause() instanceof UnsupportedOperationException);
+            }
+            try {
+                newInstance.invoke(null, String.class, 0 /* ignored */);
+                fail();
+            } catch (InvocationTargetException expected) {
+                assertTrue(expected.getCause() instanceof UnsupportedOperationException);
+            }
+
+        } finally {
+            VMRuntime.getRuntime().setTargetSdkVersion(savedTargetSdkVersion);
+        }
     }
 
     // Class without <clinit> method
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
index a32845c..6d62cbb 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
@@ -131,6 +131,18 @@
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException e) {
         }
+
+        try {
+            Currency.getInstance((Locale) null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            Currency.getInstance((String) null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
     }
 
     /**
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/InvalidPropertiesFormatExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/InvalidPropertiesFormatExceptionTest.java
deleted file mode 100644
index 10bb50e..0000000
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/InvalidPropertiesFormatExceptionTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.harmony.tests.java.util;
-
-import java.io.NotSerializableException;
-import java.util.InvalidPropertiesFormatException;
-
-import org.apache.harmony.testframework.serialization.SerializationTest;
-
-public class InvalidPropertiesFormatExceptionTest extends
-        junit.framework.TestCase {
-
-    /**
-     * java.util.InvalidPropertiesFormatException#SerializationTest()
-     */
-    public void test_Serialization() throws Exception {
-        InvalidPropertiesFormatException ipfe = new InvalidPropertiesFormatException(
-                "Hey, this is InvalidPropertiesFormatException");
-        try {
-            SerializationTest.verifySelf(ipfe);
-        } catch (NotSerializableException e) {
-            // expected
-        }
-    }
-
-    /**
-     * {@link java.util.InvalidPropertiesFormatException#InvalidPropertiesFormatException(Throwable)}
-     */
-    public void test_Constructor_Ljava_lang_Throwable() {
-        Throwable throwable = new Throwable();
-        InvalidPropertiesFormatException exception = new InvalidPropertiesFormatException(
-                throwable);
-        assertEquals("the casue did not equals argument passed in constructor",
-                throwable, exception.getCause());
-    }
-
-}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PropertiesTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PropertiesTest.java
index 27cae4e..038cc7b 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PropertiesTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PropertiesTest.java
@@ -20,15 +20,18 @@
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.PrintWriter;
+import java.io.Reader;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.InvalidPropertiesFormatException;
@@ -389,21 +392,21 @@
 
         prop = new Properties();
         Properties expected = new Properties();
-        expected.put("a", "\u0000");
+        expected.put("a", "");
         prop.load(new ByteArrayInputStream("a=\\".getBytes()));
-        assertEquals("Failed to read trailing slash value", expected, prop);
+        assertEquals("Failed to trim trailing slash value", expected, prop);
 
         prop = new Properties();
         expected = new Properties();
-        expected.put("a", "\u1234\u0000");
+        expected.put("a", "\u1234");
         prop.load(new ByteArrayInputStream("a=\\u1234\\".getBytes()));
-        assertEquals("Failed to read trailing slash value #2", expected, prop);
+        assertEquals("Failed to trim trailing slash value #2", expected, prop);
 
         prop = new Properties();
         expected = new Properties();
         expected.put("a", "q");
         prop.load(new ByteArrayInputStream("a=\\q".getBytes()));
-        assertEquals("Failed to read slash value #3", expected, prop);
+        assertEquals("Failed to skip slash value #3", expected, prop);
     }
 
     /**
@@ -1087,6 +1090,47 @@
     }
 
     /**
+     * Checks the example given in the documentation of a single property split over
+     * multiple lines separated by a backslash and newline character.
+     */
+    public void testSingleProperty_multipleLinesJoinedByBackslash() throws Exception {
+        String propertyString = "fruits                           apple, banana, pear, \\\n"
+                + "                                  cantaloupe, watermelon, \\\n"
+                + "                                  kiwi, mango";
+        checkSingleProperty("fruits", "apple, banana, pear, cantaloupe, watermelon, kiwi, mango",
+                propertyString);
+    }
+
+    /**
+     * Checks that a trailing backslash at the end of the single line of input is ignored.
+     * This is similar to a check in {@link #test_loadLjava_io_Reader()} that uses an
+     * InputStream and {@link Properties#equals(Object)} .
+     */
+    public void testSingleProperty_oneLineWithTrailingBackslash() throws Exception {
+        checkSingleProperty("key", "value", "key=value\\");
+    }
+
+    /**
+     * Checks that a trailing backslash at the end of the single line of input is ignored,
+     * even when that line has a newline.
+     */
+    public void testSingleProperty_oneLineWithTrailingBackslash_newline() throws Exception {
+        checkSingleProperty("key", "value", "key=value\\\r");
+        checkSingleProperty("key", "value", "key=value\\\n");
+        checkSingleProperty("key", "value", "key=value\\\r\n");
+    }
+
+    private static void checkSingleProperty(String key, String value, String serialized)
+            throws IOException {
+        Properties properties = new Properties();
+        try (Reader reader = new CharArrayReader(serialized.toCharArray())) {
+            properties.load(reader);
+            assertEquals(Collections.singleton(key), properties.keySet());
+            assertEquals(value, properties.getProperty(key));
+        }
+    }
+
+    /**
      * Sets up the fixture, for example, open a network connection. This method
      * is called before a test is executed.
      */
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
index db2ee7a..5d35e4c 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ResourceBundleTest.java
@@ -39,6 +39,17 @@
         assertEquals("[de_CH, de, ]", c.getCandidateLocales("base", new Locale("de", "CH")).toString());
     }
 
+    public void test_getBaseName() {
+        String name = "tests.support.Support_TestResource";
+        ResourceBundle bundle = ResourceBundle.getBundle(name);
+        assertEquals(name, bundle.getBaseBundleName());
+
+        bundle = ResourceBundle.getBundle(name, Locale.getDefault());
+        assertEquals(name, bundle.getBaseBundleName());
+
+        assertNull(new Mock_ResourceBundle().getBaseBundleName());
+    }
+
     /**
      * java.util.ResourceBundle#getBundle(java.lang.String,
      *        java.util.Locale)
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLEngineTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLEngineTest.java
index 8fae7b8..aa50676 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLEngineTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLEngineTest.java
@@ -894,8 +894,8 @@
         SSLEngine sse = getEngine(host, port);
 
         try {
-            // TODO: decide whether OpenSSLEngineImpl should throw ISE (it doesn't) b/31301555
             SSLEngineResult result = sse.wrap(bbs, bbd);
+            fail();
         } catch (IllegalStateException expected) {
         }
     }
@@ -993,8 +993,11 @@
         ByteBuffer[] bbA = { ByteBuffer.allocate(5), ByteBuffer.allocate(10), ByteBuffer.allocate(5) };
         SSLEngine sse = getEngine(host, port);
 
-        SSLEngineResult result = sse.wrap(bbA, bb);
-        assertEquals(Status.BUFFER_OVERFLOW, result.getStatus());
+        try {
+            SSLEngineResult result = sse.wrap(bbA, bb);
+            fail();
+        } catch (IllegalStateException expected) {
+        }
     }
 
     /**
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/SubjectTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/SubjectTest.java
index f2ef564..6d775ec 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/SubjectTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/SubjectTest.java
@@ -19,12 +19,18 @@
 
 import junit.framework.TestCase;
 import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.apache.harmony.testframework.serialization.SerializationTest;
 
 /**
@@ -48,6 +54,29 @@
         }
     }
 
+    public void test_Constructor_failsWithNullArguments() {
+        try {
+            new Subject(false /* readOnly */,
+                    null /* principals */,
+                    new HashSet<Object>() /* pubCredentials */,
+                    new HashSet<Object>() /* privCredentials */);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            new Subject(false , new HashSet<Principal>(), null, new HashSet<Object>());
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            new Subject(false , new HashSet<Principal>(), new HashSet<Object>(), null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
     /**
      * javax.security.auth.Subject#doAs(Subject subject, PrivilegedAction action)
      */
@@ -234,6 +263,36 @@
         SerializationTest.verifyGolden(this, getSerializationData());
     }
 
+    public void testSerialization_nullPrincipalsAllowed() throws Exception {
+        Set<Principal> principalsSet = new HashSet<>();
+        principalsSet.add(new X500Principal("CN=SomePrincipal"));
+        principalsSet.add(null);
+        principalsSet.add(new X500Principal("CN=SomeOtherPrincipal"));
+        Subject subject = new Subject(
+                false /* readOnly */, principalsSet, new HashSet<Object>(), new HashSet<Object>());
+        SerializationTest.verifySelf(subject);
+    }
+
+    public void testSecureTest_removeAllNull_throwsException() throws Exception {
+        Subject subject = new Subject(
+                false, new HashSet<Principal>(), new HashSet<Object>(), new HashSet<Object>());
+        try {
+            subject.getPrincipals().removeAll(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testSecureTest_retainAllNull_throwsException() throws Exception {
+        Subject subject = new Subject(
+                false, new HashSet<Principal>(), new HashSet<Object>(), new HashSet<Object>());
+        try {
+            subject.getPrincipals().retainAll(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
     private Object[] getSerializationData() {
         Subject subject = new Subject();
         return new Object[] { subject, subject.getPrincipals(),
diff --git a/include/LocalArray.h b/include/LocalArray.h
deleted file mode 100644
index 2ab708a..0000000
--- a/include/LocalArray.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef LOCAL_ARRAY_H_included
-#define LOCAL_ARRAY_H_included
-
-#include <cstddef>
-#include <new>
-
-/**
- * A fixed-size array with a size hint. That number of bytes will be allocated
- * on the stack, and used if possible, but if more bytes are requested at
- * construction time, a buffer will be allocated on the heap (and deallocated
- * by the destructor).
- *
- * The API is intended to be a compatible subset of C++0x's std::array.
- */
-template <size_t STACK_BYTE_COUNT>
-class LocalArray {
-public:
-    /**
-     * Allocates a new fixed-size array of the given size. If this size is
-     * less than or equal to the template parameter STACK_BYTE_COUNT, an
-     * internal on-stack buffer will be used. Otherwise a heap buffer will
-     * be allocated.
-     */
-    LocalArray(size_t desiredByteCount) : mSize(desiredByteCount) {
-        if (desiredByteCount > STACK_BYTE_COUNT) {
-            mPtr = new char[mSize];
-        } else {
-            mPtr = &mOnStackBuffer[0];
-        }
-    }
-
-    /**
-     * Frees the heap-allocated buffer, if there was one.
-     */
-    ~LocalArray() {
-        if (mPtr != &mOnStackBuffer[0]) {
-            delete[] mPtr;
-        }
-    }
-
-    // Capacity.
-    size_t size() { return mSize; }
-    bool empty() { return mSize == 0; }
-
-    // Element access.
-    char& operator[](size_t n) { return mPtr[n]; }
-    const char& operator[](size_t n) const { return mPtr[n]; }
-
-private:
-    char mOnStackBuffer[STACK_BYTE_COUNT];
-    char* mPtr;
-    size_t mSize;
-
-    // Disallow copy and assignment.
-    LocalArray(const LocalArray&);
-    void operator=(const LocalArray&);
-};
-
-#endif // LOCAL_ARRAY_H_included
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
index 37c1a1d..8465a24 100644
--- a/libart/src/main/java/java/lang/DexCache.java
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -72,6 +72,12 @@
     private long strings;
 
     /**
+     * References to MethodType (C array pointer) as they become resolved following
+     * interpreter semantics.
+     */
+    private long resolvedMethodTypes;
+
+    /**
      * The number of elements in the native resolvedFields array.
      */
     private int numResolvedFields;
@@ -91,6 +97,11 @@
      */
     private int numStrings;
 
+    /**
+     * The number of elements in the native method types array.
+     */
+    private int numResolvedMethodTypes;
+
     // Only created by the VM.
     private DexCache() {}
 
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
deleted file mode 100644
index 6e3e181..0000000
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import com.android.dex.Dex;
-
-import java.lang.annotation.Annotation;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.ListOfTypes;
-import libcore.reflect.Types;
-import libcore.util.EmptyArray;
-
-/**
- * This class represents an abstract method. Abstract methods are either methods or constructors.
- * @hide
- */
-public abstract class AbstractMethod extends Executable {
-    /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
-    @SuppressWarnings("unused") // set by runtime
-    private int accessFlags;
-
-    /**
-     * The ArtMethod associated with this Method, required for dispatching due to entrypoints
-     * Classloader is held live by the declaring class.
-     * Hidden to workaround b/16828157.
-     * @hide
-     */
-    @SuppressWarnings("unused") // set by runtime
-    private long artMethod;
-
-    /** Method's declaring class */
-    @SuppressWarnings("unused") // set by runtime
-    private Class<?> declaringClass;
-
-    /** Overriden method's declaring class (same as declaringClass unless declaringClass
-     * is a proxy class)
-     */
-    @SuppressWarnings("unused") // set by runtime
-    private Class<?> declaringClassOfOverriddenMethod;
-
-    /** The method index of this method within its defining dex file */
-    @SuppressWarnings("unused") // set by runtime
-    private int dexMethodIndex;
-
-    /**
-     * Hidden to workaround b/16828157.
-     * @hide
-     */
-    protected AbstractMethod() {
-    }
-
-    /**
-     * We insert native method stubs for abstract methods so we don't have to
-     * check the access flags at the time of the method call.  This results in
-     * "native abstract" methods, which can't exist.  If we see the "abstract"
-     * flag set, clear the "native" flag.
-     *
-     * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
-     * position, because the callers of this function are trying to convey
-     * the "traditional" meaning of the flags to their callers.
-     */
-    private static int fixMethodFlags(int flags) {
-        if ((flags & Modifier.ABSTRACT) != 0) {
-            flags &= ~Modifier.NATIVE;
-        }
-        flags &= ~Modifier.SYNCHRONIZED;
-        int ACC_DECLARED_SYNCHRONIZED = 0x00020000;
-        if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
-            flags |= Modifier.SYNCHRONIZED;
-        }
-        return flags & 0xffff;  // mask out bits not used by Java
-    }
-
-    // Overrides {@link Executable#getModifiers()} - for ART behavior see fixMethodFlags().
-    @Override
-    public int getModifiers() {
-        return fixMethodFlags(accessFlags);
-    }
-
-    // Overrides {@link Executable#isSynthetic()} - we can do it cheaply here.
-    @Override
-    public boolean isSynthetic() {
-        return (accessFlags & Modifier.SYNTHETIC) != 0;
-    }
-
-    // Overrides {@link Executable#isVarArgs()} - we can do it cheaply here.
-    @Override
-    public boolean isVarArgs() {
-        return (accessFlags & Modifier.VARARGS) != 0;
-    }
-
-    @Override
-    public Class<?> getDeclaringClass() {
-        return declaringClass;
-    }
-
-    /**
-     * Returns an array of {@code Class} objects associated with the parameter types of this
-     * abstract method. If the method was declared with no parameters, an
-     * empty array will be returned.
-     *
-     * @return the parameter types
-     */
-    @Override
-    public Class<?>[] getParameterTypes() {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
-        if (types.length == 0) {
-            return EmptyArray.CLASS;
-        }
-        Class<?>[] parametersArray = new Class[types.length];
-        for (int i = 0; i < types.length; i++) {
-            // Note, in the case of a Proxy the dex cache types are equal.
-            parametersArray[i] = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
-        }
-        return parametersArray;
-    }
-
-    @Override
-    public int getParameterCount() {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
-        return types.length;
-    }
-
-    @Override
-    public Type[] getGenericParameterTypes() {
-        return Types.getTypeArray(
-                getMethodOrConstructorGenericInfoInternal().genericParameterTypes, false);
-    }
-
-    @Override
-    public Type[] getGenericExceptionTypes() {
-        return Types.getTypeArray(
-                getMethodOrConstructorGenericInfoInternal().genericExceptionTypes, false);
-    }
-
-    @Override public native Annotation[] getDeclaredAnnotations();
-
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return isAnnotationPresentNative(annotationType);
-    }
-    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
-
-    @Override
-    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        if (annotationClass == null) {
-            throw new NullPointerException("annotationClass == null");
-        }
-        return getAnnotationNative(annotationClass);
-    }
-    private native <T extends Annotation> T getAnnotationNative(Class<T> annotationClass);
-
-    @Override
-    public Annotation[][] getParameterAnnotations() {
-        Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
-        if (parameterAnnotations == null) {
-            parameterAnnotations = new Annotation[getParameterTypes().length][0];
-        }
-        return parameterAnnotations;
-    }
-    private native Annotation[][] getParameterAnnotationsNative();
-
-    /**
-     * @hide
-     */
-    public final int getAccessFlags() {
-        return accessFlags;
-    }
-
-    static final class GenericInfo {
-        final ListOfTypes genericExceptionTypes;
-        final ListOfTypes genericParameterTypes;
-        final Type genericReturnType;
-        final TypeVariable<?>[] formalTypeParameters;
-
-        GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret,
-                    TypeVariable<?>[] formal) {
-            genericExceptionTypes = exceptions;
-            genericParameterTypes = parameters;
-            genericReturnType = ret;
-            formalTypeParameters = formal;
-        }
-    }
-
-    /**
-     * Returns generic information associated with this method/constructor member.
-     */
-    final GenericInfo getMethodOrConstructorGenericInfoInternal() {
-        String signatureAttribute = getSignatureAttribute();
-        Class<?>[] exceptionTypes = this.getExceptionTypes();
-        GenericSignatureParser parser =
-            new GenericSignatureParser(this.getDeclaringClass().getClassLoader());
-        if (this instanceof Method) {
-            parser.parseForMethod(this, signatureAttribute, exceptionTypes);
-        } else {
-            parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
-        }
-        return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
-                               parser.returnType, parser.formalTypeParameters);
-    }
-
-    private String getSignatureAttribute() {
-        String[] annotation = getSignatureAnnotation();
-        if (annotation == null) {
-            return null;
-        }
-        StringBuilder result = new StringBuilder();
-        for (String s : annotation) {
-            result.append(s);
-        }
-        return result.toString();
-    }
-    private native String[] getSignatureAnnotation();
-
-    final boolean equalNameAndParametersInternal(Method m) {
-        return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes());
-    }
-
-    private boolean equalMethodParameters(Class<?>[] params) {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
-        if (types.length != params.length) {
-            return false;
-        }
-        for (int i = 0; i < types.length; i++) {
-            if (declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]) != params[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    final int compareMethodParametersInternal(Class<?>[] params) {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
-        int length = Math.min(types.length, params.length);
-        for (int i = 0; i < length; i++) {
-            Class<?> aType = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
-            Class<?> bType = params[i];
-            if (aType != bType) {
-                int comparison = aType.getName().compareTo(bType.getName());
-                if (comparison != 0) {
-                    return comparison;
-                }
-            }
-        }
-        return types.length - params.length;
-    }
-
-    final String getMethodNameInternal() {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex);
-        return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex);
-    }
-
-    final Class<?> getMethodReturnTypeInternal() {
-        Dex dex = declaringClassOfOverriddenMethod.getDex();
-        int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex);
-        // Note, in the case of a Proxy the dex cache types are equal.
-        return declaringClassOfOverriddenMethod.getDexCacheType(dex, returnTypeIndex);
-    }
-
-    /** A cheap implementation for {@link Method#isDefault()}. */
-    final boolean isDefaultMethodInternal() {
-        return (accessFlags & Modifier.DEFAULT) != 0;
-    }
-
-    /** A cheap implementation for {@link Method#isBridge()}. */
-    final boolean isBridgeMethodInternal() {
-        return (accessFlags & Modifier.BRIDGE) != 0;
-    }
-}
diff --git a/luni/src/main/java/libcore/io/IoTracker.java b/luni/src/main/java/libcore/io/IoTracker.java
new file mode 100644
index 0000000..4623b6a
--- /dev/null
+++ b/luni/src/main/java/libcore/io/IoTracker.java
@@ -0,0 +1,63 @@
+/*
+ * 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.io;
+
+import dalvik.system.BlockGuard;
+
+/**
+ * Used to detect unbuffered I/O.
+ * @hide
+ */
+public final class IoTracker {
+    private int opCount;
+    private int totalByteCount;
+    private boolean isOpen = true;
+    private Mode mode = Mode.READ;
+
+    public void trackIo(int byteCount) {
+        ++opCount;
+        totalByteCount += byteCount;
+        if (isOpen && opCount > 10 && totalByteCount < 10*512) {
+            BlockGuard.getThreadPolicy().onUnbufferedIO();
+            isOpen = false;
+        }
+    }
+
+    public void trackIo(int byteCount, Mode mode) {
+        if (this.mode != mode) {
+            reset();
+            this.mode = mode;
+        }
+        trackIo(byteCount);
+    }
+
+    /**
+     * Resets the state of the IoTracker, except {@link #isOpen} as it is not required to notify
+     * again and again about the same stream.
+     * This is primarily used by RandomAccessFile to consider a case when {@link
+     * java.io.RandomAccessFile#seek seek} is called.
+     */
+    public void reset() {
+        opCount = 0;
+        totalByteCount = 0;
+    }
+
+    public enum Mode {
+        READ,
+        WRITE
+    }
+}
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 5fd4a7d..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;
@@ -53,3 +54,20 @@
 
     return JNI_VERSION_1_6;
 }
+
+// DalvikVM calls this on shutdown, do any global cleanup here.
+// -- Very important if we restart multiple DalvikVMs in the same process to reset the state.
+void JNI_OnUnload(JavaVM* vm, void*) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("JavaVM::GetEnv() failed");
+        abort();
+    }
+    ALOGV("libjavacore JNI_OnUnload");
+
+    ScopedLocalFrame localFrame(env);
+
+#define UNREGISTER(FN) extern void FN(JNIEnv*); FN(env)
+    UNREGISTER(unregister_libcore_icu_ICU);
+#undef UNREGISTER
+}
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 3eda923..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) {
@@ -838,56 +839,110 @@
     NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
 };
 
+//
+// Global initialization & Teardown for ICU Setup
+//   - Contains handlers for JNI_OnLoad and JNI_OnUnload
+//
+
 #define FAIL_WITH_STRERROR(s) \
-    ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \
+    ALOGE("Couldn't " s " '%s': %s", path_.c_str(), strerror(errno)); \
     return FALSE;
 
 #define MAYBE_FAIL_WITH_ICU_ERROR(s) \
     if (status != U_ZERO_ERROR) {\
-        ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \
+        ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path_.c_str()); \
         return FALSE; \
     }
 
-static bool mapIcuData(const std::string& path) {
+// Contain the memory map for ICU data files.
+// Automatically adds the data file to ICU's list of data files upon constructing.
+//
+// - Automatically unmaps in the destructor.
+struct IcuDataMap {
+  // Map in ICU data at the path, returning null if it failed (prints error to ALOGE).
+  static std::unique_ptr<IcuDataMap> Create(const std::string& path) {
+    std::unique_ptr<IcuDataMap> map(new IcuDataMap(path));
+
+    if (!map->TryMap()) {
+      // madvise or ICU could fail but mmap still succeeds.
+      // Destructor will take care of cleaning up a partial init.
+      return nullptr;
+    }
+
+    return map;
+  }
+
+  // Unmap the ICU data.
+  ~IcuDataMap() {
+    TryUnmap();
+  }
+
+ private:
+  IcuDataMap(const std::string& path)
+    : path_(path),
+      data_(MAP_FAILED),
+      data_length_(0)
+  {}
+
+  bool TryMap() {
     // Open the file and get its length.
-    android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path_.c_str(), O_RDONLY)));
+
     if (fd.get() == -1) {
         FAIL_WITH_STRERROR("open");
     }
+
     struct stat sb;
     if (fstat(fd.get(), &sb) == -1) {
         FAIL_WITH_STRERROR("stat");
     }
 
+    data_length_ = sb.st_size;
+
     // Map it.
-    void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd.get(), 0);
-    if (data == MAP_FAILED) {
+    data_ = mmap(NULL, data_length_, PROT_READ, MAP_SHARED, fd.get(), 0  /* offset */);
+    if (data_ == MAP_FAILED) {
         FAIL_WITH_STRERROR("mmap");
     }
 
     // Tell the kernel that accesses are likely to be random rather than sequential.
-    if (madvise(data, sb.st_size, MADV_RANDOM) == -1) {
+    if (madvise(data_, data_length_, MADV_RANDOM) == -1) {
         FAIL_WITH_STRERROR("madvise(MADV_RANDOM)");
     }
 
     UErrorCode status = U_ZERO_ERROR;
 
     // Tell ICU to use our memory-mapped data.
-    udata_setCommonData(data, &status);
+    udata_setCommonData(data_, &status);
     MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData");
 
-    return TRUE;
-}
+    return true;
+  }
 
-void register_libcore_icu_ICU(JNIEnv* env) {
-    // Check the timezone override file exists. If it does, map it first so we use it in preference
-    // to the one that shipped with the device.
-    const char* dataPathPrefix = getenv("ANDROID_DATA");
-    if (dataPathPrefix == NULL) {
-        ALOGE("ANDROID_DATA environment variable not set"); \
-        abort();
+  bool TryUnmap() {
+    // Don't need to do opposite of udata_setCommonData,
+    // u_cleanup (performed in unregister_libcore_icu_ICU) takes care of it.
+
+    // Don't need to opposite of madvise, munmap will take care of it.
+
+    if (data_ != MAP_FAILED) {
+      if (munmap(data_, data_length_) == -1) {
+        FAIL_WITH_STRERROR("munmap");
+      }
     }
 
+    // Don't need to close the file, it was closed automatically during TryMap.
+    return true;
+  }
+
+  std::string path_;    // Save for error messages.
+  void* data_;          // Save for munmap.
+  size_t data_length_;  // Save for munmap.
+};
+
+struct ICURegistration {
+  // Init ICU, configuring it and loading the data files.
+  ICURegistration(JNIEnv* env) {
     UErrorCode status = U_ZERO_ERROR;
     // Tell ICU it can *only* use our memory-mapped data.
     udata_setFileAccess(UDATA_NO_FILES, &status);
@@ -896,15 +951,13 @@
         abort();
     }
 
-    // Map in optional TZ data files.
-    std::string dataPath;
-    dataPath = dataPathPrefix;
-    dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat";
+    std::string dataPath = getTzDataOverridePath();
 
+    // Map in optional TZ data files.
     struct stat sb;
     if (stat(dataPath.c_str(), &sb) == 0) {
         ALOGD("Timezone override file found: %s", dataPath.c_str());
-        if (!mapIcuData(dataPath)) {
+        if ((icu_datamap_from_data_ = IcuDataMap::Create(dataPath)) == nullptr) {
             ALOGW("TZ override file %s exists but could not be loaded. Skipping.", dataPath.c_str());
         }
     } else {
@@ -912,18 +965,7 @@
     }
 
     // Use the ICU data files that shipped with the device for everything else.
-    const char* systemPathPrefix = getenv("ANDROID_ROOT");
-    if (systemPathPrefix == NULL) {
-        ALOGE("ANDROID_ROOT environment variable not set"); \
-        abort();
-    }
-    std::string systemPath;
-    systemPath = systemPathPrefix;
-    systemPath += "/usr/icu/";
-    systemPath += U_ICUDATA_NAME;
-    systemPath += ".dat";
-
-    if (!mapIcuData(systemPath)) {
+    if ((icu_datamap_from_system_ = IcuDataMap::Create(getSystemPath())) == nullptr) {
         abort();
     }
 
@@ -937,4 +979,69 @@
     }
 
     jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods));
+  }
+
+  // De-init ICU, unloading the data files. Do the opposite of the above function.
+  ~ICURegistration() {
+    // Skip unregistering JNI methods explicitly, class unloading takes care of it.
+
+    // Reset libicu state to before it was loaded.
+    u_cleanup();
+
+    // Unmap ICU data files that shipped with the device for everything else.
+    icu_datamap_from_system_.reset();
+
+    // Unmap optional TZ data files.
+    icu_datamap_from_data_.reset();
+
+    // We don't need to call udata_setFileAccess because u_cleanup takes care of it.
+  }
+
+  // Check the timezone override file exists. If it does, map it first so we use it in preference
+  // to the one that shipped with the device.
+  static std::string getTzDataOverridePath() {
+    const char* dataPathPrefix = getenv("ANDROID_DATA");
+    if (dataPathPrefix == NULL) {
+      ALOGE("ANDROID_DATA environment variable not set"); \
+      abort();
+    }
+    std::string dataPath;
+    dataPath = dataPathPrefix;
+    dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat";
+
+    return dataPath;
+  }
+
+  static std::string getSystemPath() {
+    const char* systemPathPrefix = getenv("ANDROID_ROOT");
+    if (systemPathPrefix == NULL) {
+      ALOGE("ANDROID_ROOT environment variable not set"); \
+      abort();
+    }
+
+    std::string systemPath;
+    systemPath = systemPathPrefix;
+    systemPath += "/usr/icu/";
+    systemPath += U_ICUDATA_NAME;
+    systemPath += ".dat";
+    return systemPath;
+  }
+
+  std::unique_ptr<IcuDataMap> icu_datamap_from_data_;
+  std::unique_ptr<IcuDataMap> icu_datamap_from_system_;
+};
+
+// Use RAII-style initialization/teardown so that we can get unregistered
+// when dlclose is called (even if JNI_OnUnload is not).
+static std::unique_ptr<ICURegistration> sIcuRegistration;
+
+// Init ICU, configuring it and loading the data files.
+void register_libcore_icu_ICU(JNIEnv* env) {
+  sIcuRegistration.reset(new ICURegistration(env));
+}
+
+// De-init ICU, unloading the data files. Do the opposite of the above function.
+void unregister_libcore_icu_ICU(JNIEnv*) {
+  // Explicitly calling this is optional. Dlclose will take care of it as well.
+  sIcuRegistration.reset();
 }
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 820bda62..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,22 +16,24 @@
 
 #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"
-#include "LocalArray.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #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>
 
 #define BUCKET_COUNT 128
 
@@ -519,9 +521,8 @@
         }
 
         // return prefix + ":" + localName
-        ::LocalArray<1024> qName(strlen(mPrefix) + 1 + strlen(mLocalName) + 1);
-        snprintf(&qName[0], qName.size(), "%s:%s", mPrefix, mLocalName);
-        return internString(mEnv, mParsingContext, &qName[0]);
+        auto qName = android::base::StringPrintf("%s:%s", mPrefix, mLocalName);
+        return internString(mEnv, mParsingContext, qName.c_str());
     }
 
     /**
diff --git a/luni/src/test/java/dalvik/system/BlockGuardTest.java b/luni/src/test/java/dalvik/system/BlockGuardTest.java
index 24313cd..ca29e77 100644
--- a/luni/src/test/java/dalvik/system/BlockGuardTest.java
+++ b/luni/src/test/java/dalvik/system/BlockGuardTest.java
@@ -21,8 +21,11 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.RandomAccessFile;
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Created by narayan on 1/7/16.
@@ -34,6 +37,7 @@
 
     @Override
     public void setUp() {
+        recorder.setChecks(EnumSet.allOf(RecordingPolicy.Check.class));
         oldPolicy = BlockGuard.getThreadPolicy();
         BlockGuard.setThreadPolicy(recorder);
     }
@@ -138,23 +142,142 @@
         recorder.expectNoViolations();
     }
 
+    public void testUnbufferedIO() throws Exception {
+        File f = File.createTempFile("foo", "bar");
+        recorder.setChecks(EnumSet.of(RecordingPolicy.Check.UNBUFFERED_IO));
+        recorder.clear();
+
+        try (FileOutputStream fos = new FileOutputStream(f)) {
+            recorder.expectNoViolations();
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                fos.write("a".getBytes());
+            }
+            recorder.expectAndClear("onUnbufferedIO");
+        }
+
+        try (FileInputStream fis = new FileInputStream(new File("/dev/null"))) {
+            recorder.expectNoViolations();
+            byte[] b = new byte[1];
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                fis.read(b);
+            }
+            recorder.expectAndClear("onUnbufferedIO");
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            // seek should reset the IoTracker.
+            ras.seek(0);
+            recorder.expectNoViolations();
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                ras.read("a".getBytes());
+            }
+            recorder.expectAndClear("onUnbufferedIO");
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            // No violation is expected as a write is called while reading which should reset the
+            // IoTracker counter.
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                if (i == 5) {
+                    ras.write("a".getBytes());
+                }
+                ras.read("a".getBytes());
+            }
+            recorder.expectNoViolations();
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            // No violation is expected as a seek is called while reading which should reset the
+            // IoTracker counter.
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                if (i == 5) {
+                    ras.seek(0);
+                }
+                ras.read("a".getBytes());
+            }
+            recorder.expectNoViolations();
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            // seek should reset the IoTracker.
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                ras.write("a".getBytes());
+            }
+            recorder.expectAndClear("onUnbufferedIO");
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            // No violation is expected as a read is called while writing which should reset the
+            // IoTracker counter.
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                if (i == 5) {
+                    ras.read("a".getBytes());
+                }
+                ras.write("a".getBytes());
+            }
+            recorder.expectNoViolations();
+        }
+
+        try (RandomAccessFile ras = new RandomAccessFile(f, "rw")) {
+            for (int i = 0; i < 11; i++) {
+                recorder.expectNoViolations();
+                if (i == 5) {
+                    ras.seek(0);
+                }
+                ras.write("a".getBytes());
+            }
+            recorder.expectNoViolations();
+        }
+    }
 
     public static class RecordingPolicy implements BlockGuard.Policy {
         private final List<String> violations = new ArrayList<>();
+        private Set<Check> checksList;
+
+        public enum Check {
+            WRITE_TO_DISK,
+            READ_FROM_DISK,
+            NETWORK,
+            UNBUFFERED_IO,
+        }
+
+        public void setChecks(EnumSet<Check> checksList) {
+            this.checksList = checksList;
+        }
 
         @Override
         public void onWriteToDisk() {
-            addViolation("onWriteToDisk");
+            if (checksList != null && checksList.contains(Check.WRITE_TO_DISK)) {
+                addViolation("onWriteToDisk");
+            }
         }
 
         @Override
         public void onReadFromDisk() {
-            addViolation("onReadFromDisk");
+            if (checksList != null && checksList.contains(Check.READ_FROM_DISK)) {
+                addViolation("onReadFromDisk");
+            }
         }
 
         @Override
         public void onNetwork() {
-            addViolation("onNetwork");
+            if (checksList != null && checksList.contains(Check.NETWORK)) {
+                addViolation("onNetwork");
+            }
+        }
+
+        @Override
+        public void onUnbufferedIO() {
+            if (checksList != null && checksList.contains(Check.UNBUFFERED_IO)) {
+                addViolation("onUnbufferedIO");
+            }
         }
 
         private void addViolation(String type) {
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 648ac2a..687d903 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -596,8 +596,6 @@
   }
 
   public void test_xattr_Errno() throws Exception {
-    File file = File.createTempFile("xattr", "test");
-    final String path = file.getAbsolutePath();
     final String NAME_TEST = "user.meow";
     final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8);
 
@@ -606,53 +604,54 @@
       Libcore.os.getxattr("", NAME_TEST);
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOENT, e.errno);
+      assertEquals(ENOENT, e.errno);
     }
     try {
       Libcore.os.listxattr("");
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOENT, e.errno);
+      assertEquals(ENOENT, e.errno);
     }
     try {
       Libcore.os.removexattr("", NAME_TEST);
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOENT, e.errno);
+      assertEquals(ENOENT, e.errno);
     }
     try {
       Libcore.os.setxattr("", NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE);
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOENT, e.errno);
+      assertEquals(ENOENT, e.errno);
     }
 
     // ENOTSUP, Extended attributes are not supported by the filesystem, or are disabled.
+    final boolean root = (Libcore.os.getuid() == 0);
+    final String path = "/proc/self/stat";
     try {
-      Libcore.os.getxattr("/proc/version", NAME_TEST);
+      Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE);
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOTSUP, e.errno);
+      // setxattr(2) requires root permission for writing to this file, will get EACCES otherwise.
+      assertEquals(root ? ENOTSUP : EACCES, e.errno);
+    }
+    try {
+      Libcore.os.getxattr(path, NAME_TEST);
+      fail();
+    } catch (ErrnoException e) {
+      assertEquals(ENOTSUP, e.errno);
     }
     try {
       // Linux listxattr does not set errno.
-      Libcore.os.listxattr("/proc/version");
+      Libcore.os.listxattr(path);
     } catch (ErrnoException e) {
       fail();
     }
     try {
-      Libcore.os.removexattr("/proc/version", "security.selinux");
+      Libcore.os.removexattr(path, NAME_TEST);
       fail();
     } catch (ErrnoException e) {
-      assertEquals(OsConstants.ENOTSUP, e.errno);
-    }
-    try {
-      Libcore.os.setxattr("/proc/version", NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE);
-      fail();
-    } catch (ErrnoException e) {
-      // For setxattr, EACCES or ENOTSUP is set depending on whether running with root permission.
-      assertTrue(e.errno == OsConstants.EACCES ||
-                 e.errno == OsConstants.ENOTSUP);
+      assertEquals(ENOTSUP, e.errno);
     }
   }
 
diff --git a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
index 00c5389..71b9517 100644
--- a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
+++ b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
@@ -393,4 +393,37 @@
         BufferedReader br = new BufferedReader(new InputStreamReader(pis));
         assertEquals("hello, world", br.readLine());
     }
+
+    public void test_closeException() throws Exception {
+        final IOException testException = new IOException("kaboom!");
+        Reader thrower = new Reader() {
+            @Override
+            public int read(char cbuf[], int off, int len) throws IOException {
+                // Not used
+                return 0;
+            }
+
+            @Override
+            public void close() throws IOException {
+                throw testException;
+            }
+        };
+        BufferedReader br = new BufferedReader(thrower);
+
+        try {
+            br.close();
+            fail();
+        } catch(IOException expected) {
+            assertSame(testException, expected);
+        }
+
+        try {
+            // Pre-openJdk8 BufferedReader#close() with exception wouldn't
+            // reset the input reader to null. This would still allow ready()
+            // to succeed.
+            br.ready();
+            fail();
+        } catch(IOException expected) {
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/io/OldBufferedWriterTest.java b/luni/src/test/java/libcore/java/io/OldBufferedWriterTest.java
index ed5b862..5e157d2 100644
--- a/luni/src/test/java/libcore/java/io/OldBufferedWriterTest.java
+++ b/luni/src/test/java/libcore/java/io/OldBufferedWriterTest.java
@@ -17,6 +17,7 @@
 
 package libcore.java.io;
 
+import java.io.Writer;
 import java.io.BufferedWriter;
 import java.io.IOException;
 import tests.support.Support_ASimpleWriter;
@@ -300,6 +301,43 @@
         }
     }
 
+    public void test_closeException() throws Exception {
+        final IOException testException = new IOException("kaboom!");
+        Writer thrower = new Writer() {
+            @Override
+            public void write(char cbuf[], int off, int len) throws IOException {
+                // Not used
+            }
+
+            @Override
+            public void flush() throws IOException {
+                // Not used
+            }
+
+            @Override
+            public void close() throws IOException {
+                throw testException;
+            }
+        };
+        BufferedWriter bw = new BufferedWriter(thrower);
+
+        try {
+            bw.close();
+            fail();
+        } catch(IOException expected) {
+            assertSame(testException, expected);
+        }
+
+        try {
+            // Pre-openJdk8 BufferedWriter#close() with exception wouldn't
+            // reset the output writer to null. This would still allow write()
+            // to succeed.
+            bw.write(1);
+            fail();
+        } catch(IOException expected) {
+        }
+    }
+
     protected void setUp() {
         sw = new Support_StringWriter();
         ssw = new Support_ASimpleWriter(true);
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/lang/invoke/MethodHandlesTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
new file mode 100644
index 0000000..e7799e9
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.lang.invoke;
+
+import junit.framework.TestCase;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Vector;
+
+import static java.lang.invoke.MethodHandles.Lookup.*;
+
+public class MethodHandlesTest extends TestCase {
+    private static final int ALL_LOOKUP_MODES = (PUBLIC | PRIVATE | PACKAGE | PROTECTED);
+
+    public void test_publicLookupClassAndModes() {
+        MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
+        assertSame(Object.class, publicLookup.lookupClass());
+        assertEquals(PUBLIC, publicLookup.lookupModes());
+    }
+
+    public void test_defaultLookupClassAndModes() {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+        assertSame(MethodHandlesTest.class, defaultLookup.lookupClass());
+        assertEquals(ALL_LOOKUP_MODES, defaultLookup.lookupModes());
+    }
+
+    public void test_LookupIn() {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+
+        // A class in the same package loses the privilege to lookup protected and private
+        // members.
+        MethodHandles.Lookup siblingLookup = defaultLookup.in(PackageSibling.class);
+        assertEquals(ALL_LOOKUP_MODES & ~(PROTECTED | PRIVATE),  siblingLookup.lookupModes());
+
+        // The new lookup isn't in the same package, so it loses all its privileges except
+        // for public.
+        MethodHandles.Lookup nonSibling = defaultLookup.in(Vector.class);
+        assertEquals(PUBLIC, nonSibling.lookupModes());
+
+        // Special case, sibling inner classes in the same parent class
+        MethodHandles.Lookup inner2 = Inner1.lookup.in(Inner2.class);
+        assertEquals(PUBLIC | PRIVATE | PACKAGE, inner2.lookupModes());
+
+        try {
+            MethodHandles.lookup().in(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        // Callers cannot change the lookup context to anything within the java.lang.invoke package.
+        try {
+            MethodHandles.lookup().in(MethodHandle.class);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void test_findStatic() throws Exception {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+
+        // Handle for String String#valueOf(char[]).
+        MethodHandle handle = defaultLookup.findStatic(String.class, "valueOf",
+                MethodType.methodType(String.class, char[].class));
+        assertNotNull(handle);
+
+        assertEquals(String.class, handle.type().returnType());
+        assertEquals(1, handle.type().parameterCount());
+        assertEquals(char[].class, handle.type().parameterArray()[0]);
+        assertEquals(MethodHandle.INVOKE_STATIC, handle.getHandleKind());
+
+        MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class);
+
+        // Package private in a public class in a different package from the lookup.
+        try {
+            inUtil.findStatic(MethodHandlesTest.class, "packagePrivateStaticMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Protected in a public class in a different package from the lookup.
+        try {
+            inUtil.findStatic(MethodHandlesTest.class, "protectedStaticMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Private in a public class in a different package from the lookup.
+        try {
+            inUtil.findStatic(MethodHandlesTest.class, "privateStaticMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Public method in a package private class in a different package from the lookup.
+        try {
+            inUtil.findStatic(PackageSibling.class, "publicStaticMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Public virtual method should not discoverable via findStatic.
+        try {
+            inUtil.findStatic(MethodHandlesTest.class, "publicMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+    }
+
+    public void test_findConstructor() throws Exception {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+
+        // Handle for String.<init>(String). The requested type of the constructor declares
+        // a void return type (to match the bytecode) but the handle that's created will declare
+        // a return type that's equal to the type being constructed.
+        MethodHandle handle = defaultLookup.findConstructor(String.class,
+                MethodType.methodType(void.class, String.class));
+        assertNotNull(handle);
+
+        assertEquals(String.class, handle.type().returnType());
+        assertEquals(1, handle.type().parameterCount());
+
+        assertEquals(String.class, handle.type().parameterArray()[0]);
+        assertEquals(MethodHandle.INVOKE_DIRECT, handle.getHandleKind());
+
+        MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class);
+
+        // Package private in a public class in a different package from the lookup.
+        try {
+            inUtil.findConstructor(ConstructorTest.class,
+                    MethodType.methodType(void.class, String.class, int.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Protected in a public class in a different package from the lookup.
+        try {
+            inUtil.findConstructor(ConstructorTest.class,
+                    MethodType.methodType(void.class, String.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Private in a public class in a different package from the lookup.
+        try {
+            inUtil.findConstructor(ConstructorTest.class,
+                    MethodType.methodType(void.class, String.class, char.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Protected constructor in a package private class in a different package from the lookup.
+        try {
+            inUtil.findConstructor(PackageSibling.class,
+                    MethodType.methodType(void.class, String.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Public constructor in a package private class in a different package from the lookup.
+        try {
+            inUtil.findConstructor(PackageSibling.class,
+                    MethodType.methodType(void.class, String.class, char.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+    }
+
+    public void test_findVirtual() throws Exception {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+
+        // String.replaceAll(String, String);
+        MethodHandle handle = defaultLookup.findVirtual(String.class, "replaceAll",
+                MethodType.methodType(String.class, String.class, String.class));
+        assertNotNull(handle);
+
+        assertEquals(String.class, handle.type().returnType());
+        // Note that the input type was (String,String)String but the handle's type is
+        // (String, String, String)String - since it's a non static call, we prepend the
+        // receiver to the type.
+        assertEquals(3, handle.type().parameterCount());
+        MethodType expectedType = MethodType.methodType(String.class,
+                new Class<?>[] { String.class, String.class, String.class});
+
+        assertEquals(expectedType, handle.type());
+        assertEquals(MethodHandle.INVOKE_VIRTUAL, handle.getHandleKind());
+
+        MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class);
+
+        // Package private in a public class in a different package from the lookup.
+        try {
+            inUtil.findVirtual(MethodHandlesTest.class, "packagePrivateMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Protected in a public class in a different package from the lookup.
+        try {
+            inUtil.findVirtual(MethodHandlesTest.class, "protectedMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Protected in a public class in a different package from the lookup.
+        try {
+            inUtil.findVirtual(MethodHandlesTest.class, "privateMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Public method in a package private class in a different package from the lookup.
+        try {
+            inUtil.findVirtual(PackageSibling.class, "publicMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+
+        // Public static method should not discoverable via findVirtual.
+        try {
+            inUtil.findVirtual(MethodHandlesTest.class, "publicStaticMethod",
+                    MethodType.methodType(void.class));
+            fail();
+        } catch (IllegalAccessException expected) {
+        }
+    }
+
+    public static class Inner1 {
+        public static MethodHandles.Lookup lookup = MethodHandles.lookup();
+    }
+
+    public static class Inner2 {
+    }
+
+    private static void privateStaticMethod() {}
+    public static void publicStaticMethod() {}
+    static void packagePrivateStaticMethod() {}
+    protected static void protectedStaticMethod() {}
+
+    public void publicMethod() {}
+    private void privateMethod() {}
+    void packagePrivateMethod() {}
+    protected void protectedMethod() {}
+
+    public static class ConstructorTest {
+        ConstructorTest(String unused, int unused2) {}
+        protected ConstructorTest(String unused) {}
+        private ConstructorTest(String unused, char unused2) {}
+    }
+}
+
+class PackageSibling {
+    public void publicMethod() {}
+    public static void publicStaticMethod() {}
+
+    protected PackageSibling(String unused) {}
+    public PackageSibling(String unused, char unused2) {}
+}
+
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java b/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java
index 3093bbd..8d7ed71 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java
@@ -17,6 +17,8 @@
 package libcore.java.lang.reflect;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Parameter;
+
 import junit.framework.TestCase;
 
 public final class ConstructorTest extends TestCase {
@@ -33,8 +35,12 @@
     }
 
     public void test_getParameterTypes() throws Exception {
-        Class[] expectedParameters = new Class[] { Object.class };
+        Class[] expectedParameters = new Class[0];
         Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+        assertEquals(0, constructor.getParameterTypes().length);
+
+        expectedParameters = new Class[] { Object.class };
+        constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
         Class[] parameters = constructor.getParameterTypes();
         assertEquals(1, parameters.length);
         assertEquals(expectedParameters[0], parameters[0]);
@@ -46,12 +52,37 @@
     }
 
     public void test_getParameterCount() throws Exception {
-        Class[] expectedParameters = new Class[] { Object.class };
+        Class[] expectedParameters = new Class[0];
         Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+        assertEquals(0, constructor.getParameterCount());
+
+        expectedParameters = new Class[] { Object.class };
+        constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
         int count = constructor.getParameterCount();
         assertEquals(1, count);
     }
 
+    public void test_getParameters() throws Exception {
+        Class[] expectedParameters = new Class[0];
+        Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+        assertEquals(0, constructor.getParameters().length);
+
+        expectedParameters = new Class[] { Object.class };
+        constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+
+        // Test the information available via other Constructor methods. See ParameterTest and
+        // annotations.ParameterTest for more in-depth Parameter testing.
+        Parameter[] parameters = constructor.getParameters();
+        assertEquals(1, parameters.length);
+        assertEquals(Object.class, parameters[0].getType());
+
+        // Check that corrupting our array doesn't affect other callers.
+        parameters[0] = null;
+        parameters = constructor.getParameters();
+        assertEquals(1, parameters.length);
+        assertEquals(Object.class, parameters[0].getType());
+    }
+
     public void testGetConstructorWithNullArgumentsArray() throws Exception {
         Constructor<?> constructor = ConstructorTestHelper.class.getConstructor((Class[]) null);
         assertEquals(0, constructor.getParameterTypes().length);
diff --git a/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java b/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java
index 5cb88d6..315a885 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java
@@ -19,6 +19,7 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
 import java.lang.reflect.Proxy;
 import java.util.Collections;
 import java.util.Comparator;
@@ -41,8 +42,12 @@
     }
 
     public void test_getParameterTypes() throws Exception {
-        Class[] expectedParameters = new Class[] { Object.class };
-        Method method = MethodTestHelper.class.getMethod("m2", expectedParameters);
+        Class[] expectedParameters = new Class[0];
+        Method method = MethodTestHelper.class.getMethod("m1", expectedParameters);
+        assertEquals(0, method.getParameterTypes().length);
+
+        expectedParameters = new Class[] { Object.class };
+        method = MethodTestHelper.class.getMethod("m2", expectedParameters);
         Class[] parameters = method.getParameterTypes();
         assertEquals(1, parameters.length);
         assertEquals(expectedParameters[0], parameters[0]);
@@ -54,12 +59,37 @@
     }
 
     public void test_getParameterCount() throws Exception {
-        Class[] expectedParameters = new Class[] { Object.class };
-        Method method = MethodTestHelper.class.getMethod("m2", expectedParameters);
+        Class[] expectedParameters = new Class[0];
+        Method method = MethodTestHelper.class.getMethod("m1", expectedParameters);
+        assertEquals(0, method.getParameterCount());
+
+        expectedParameters = new Class[] { Object.class };
+        method = MethodTestHelper.class.getMethod("m2", expectedParameters);
         int count = method.getParameterCount();
         assertEquals(1, count);
     }
 
+    public void test_getParameters() throws Exception {
+        Class[] expectedParameters = new Class[0];
+        Method method = MethodTestHelper.class.getMethod("m1", expectedParameters);
+        assertEquals(0, method.getParameters().length);
+
+        expectedParameters = new Class[] { Object.class };
+        method = MethodTestHelper.class.getMethod("m2", expectedParameters);
+
+        // Test the information available via other Method methods. See ParameterTest and
+        // annotations.ParameterTest for more in-depth Parameter testing.
+        Parameter[] parameters = method.getParameters();
+        assertEquals(1, parameters.length);
+        assertEquals(Object.class, parameters[0].getType());
+
+        // Check that corrupting our array doesn't affect other callers.
+        parameters[0] = null;
+        parameters = method.getParameters();
+        assertEquals(1, parameters.length);
+        assertEquals(Object.class, parameters[0].getType());
+    }
+
     public void testGetMethodWithPrivateMethodAndInterfaceMethod() throws Exception {
         assertEquals(InterfaceA.class, Sub.class.getMethod("a").getDeclaringClass());
     }
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java
new file mode 100644
index 0000000..1a45497
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java
@@ -0,0 +1,1146 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang.reflect;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.MalformedParametersException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.function.Function;
+import libcore.io.Streams;
+
+import dalvik.system.PathClassLoader;
+
+/**
+ * Tests for {@link Parameter}. For annotation-related tests see
+ * {@link libcore.java.lang.reflect.annotations.AnnotatedElementParameterTest} and
+ * {@link libcore.java.lang.reflect.annotations.ExecutableParameterTest}.
+ *
+ * <p>Tests suffixed with _withMetadata() require parameter metadata compiled in to work properly.
+ * These are handled by loading pre-compiled .dex files.
+ * See also {@link DependsOnParameterMetadata}.
+ */
+public class ParameterTest extends TestCase {
+
+    /**
+     * A ClassLoader that can be used to load the
+     * libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses class and its nested
+     * classes. The loaded classes has valid metadata that could be created by a valid Android
+     * compiler.
+     */
+    private ClassLoader classesWithMetadataClassLoader;
+
+    /**
+     * A ClassLoader that can be used to load the
+     * libcore.java.lang.reflect.parameter.MetadataVariations class.
+     * The loaded class has invalid metadata that could not be created by a valid Android
+     * compiler.
+     */
+    private ClassLoader metadataVariationsClassLoader;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        File dexDir = File.createTempFile("dexDir", "");
+        assertTrue(dexDir.delete());
+        assertTrue(dexDir.mkdirs());
+
+        classesWithMetadataClassLoader =
+                createClassLoaderForDexResource(dexDir, "parameter_metadata_test_classes.dex");
+        metadataVariationsClassLoader =
+                createClassLoaderForDexResource(dexDir, "metadata_variations.dex");
+    }
+
+    /**
+     * A source annotation used to mark code below with behavior that is highly dependent on
+     * parameter metadata. It is intended to bring readers here for the following:
+     *
+     * <p>Unless the compiler supports (and is configured to enable) storage of metadata
+     * for parameters, the runtime does not have access to the parameter name from the source and
+     * some modifier information like "implicit" (AKA "mandated"), "synthetic" and "final".
+     *
+     * <p>This test class is expected to be compiled <em>without</em> requesting that the metadata
+     * be compiled in. dex files that contains classes with metadata are loaded in setUp() and
+     * used from the tests suffixed with "_withMetadata".
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target(ElementType.METHOD)
+    private @interface DependsOnParameterMetadata {}
+
+    private static class SingleParameter {
+        @SuppressWarnings("unused")
+        SingleParameter(String p0) {}
+
+        @SuppressWarnings("unused")
+        void oneParameter(String p0) {}
+    }
+
+    public void testSingleParameterConstructor() throws Exception {
+        Constructor<?> constructor = SingleParameter.class.getDeclaredConstructor(String.class);
+        checkSingleStringParameter(constructor);
+    }
+
+    public void testSingleParameterMethod() throws Exception {
+        Method method = SingleParameter.class.getDeclaredMethod("oneParameter", String.class);
+        checkSingleStringParameter(method);
+    }
+
+    private static void checkSingleStringParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    public void testSingleParameterConstructor_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("SingleParameter");
+        Constructor<?> constructor  = clazz.getDeclaredConstructor(String.class);
+        checkSingleStringParameter_withMetadata(constructor);
+    }
+
+    public void testSingleParameterMethod_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("SingleParameter");
+        Method method = clazz.getDeclaredMethod("oneParameter", String.class);
+        checkSingleStringParameter_withMetadata(method);
+    }
+
+    private static void checkSingleStringParameter_withMetadata(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String p0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkName(true /* expectedNameIsPresent */, "p0")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    private static class GenericParameter {
+        @SuppressWarnings("unused")
+        GenericParameter(Function<String, Integer> p0) {}
+
+        @SuppressWarnings("unused")
+        void genericParameter(Function<String, Integer> p0) {}
+    }
+
+    public void testGenericParameterConstructor() throws Exception {
+        Constructor<?> constructor = GenericParameter.class.getDeclaredConstructor(Function.class);
+        checkGenericParameter(constructor);
+    }
+
+    public void testGenericParameterMethod() throws Exception {
+        Method method = GenericParameter.class.getDeclaredMethod(
+                "genericParameter", Function.class);
+        checkGenericParameter(method);
+    }
+
+    private static void checkGenericParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString(
+                        "[java.util.function.Function<java.lang.String, java.lang.Integer> arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(Function.class)
+                .checkGetParameterizedType(
+                        "java.util.function.Function<java.lang.String, java.lang.Integer>");
+    }
+
+    public void testGenericParameterConstructor_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("GenericParameter");
+        Constructor<?> constructor = clazz.getDeclaredConstructor(Function.class);
+        checkGenericParameter_withMetadata(constructor);
+    }
+
+    public void testGenericParameterMethod_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("GenericParameter");
+        Method method = clazz.getDeclaredMethod("genericParameter", Function.class);
+        checkGenericParameter_withMetadata(method);
+    }
+
+    private static void checkGenericParameter_withMetadata(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString(
+                        "[java.util.function.Function<java.lang.String, java.lang.Integer> p0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(Function.class)
+                .checkName(true /* expectedNameIsPresent */, "p0")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetParameterizedType(
+                        "java.util.function.Function<java.lang.String, java.lang.Integer>");
+    }
+
+    private static class TwoParameters {
+        @SuppressWarnings("unused")
+        TwoParameters(String p0, Integer p1) {}
+        @SuppressWarnings("unused")
+        void twoParameters(String p0, Integer p1) {}
+    }
+
+    public void testTwoParameterConstructor() throws Exception {
+        Constructor<?> constructor =
+                TwoParameters.class.getDeclaredConstructor(String.class, Integer.class);
+        checkTwoParameters(constructor);
+    }
+
+    public void testTwoParameterMethod() throws Exception {
+        Method method = TwoParameters.class.getDeclaredMethod(
+                "twoParameters", String.class, Integer.class);
+        checkTwoParameters(method);
+    }
+
+    private static void checkTwoParameters(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String arg0, java.lang.Integer arg1]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(Integer.class)
+                .checkGetParameterizedType("class java.lang.Integer");
+    }
+
+    public void testTwoParameterConstructor_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("TwoParameters");
+        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
+        checkTwoParameters_withMetadata(constructor);
+    }
+
+    public void testTwoParameterMethod_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("TwoParameters");
+        Method method = clazz.getDeclaredMethod("twoParameters", String.class, Integer.class);
+        checkTwoParameters_withMetadata(method);
+    }
+
+    private static void checkTwoParameters_withMetadata(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String p0, java.lang.Integer p1]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkName(true /* expectedNameIsPresent */, "p0")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetParameterizedType("class java.lang.String");
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(Integer.class)
+                .checkName(true /* expectedNameIsPresent */, "p1")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetParameterizedType("class java.lang.Integer");
+    }
+
+    private static class FinalParameter {
+        @SuppressWarnings("unused")
+        FinalParameter(final String p0) {}
+        @SuppressWarnings("unused")
+        void finalParameter(final String p0) {}
+    }
+
+    public void testFinalParameterConstructor() throws Exception {
+        Constructor<?> constructor = FinalParameter.class.getDeclaredConstructor(String.class);
+        checkFinalParameter(constructor);
+    }
+
+    public void testFinalParameterMethod() throws Exception {
+        Method method = FinalParameter.class.getDeclaredMethod("finalParameter", String.class);
+        checkFinalParameter(method);
+    }
+
+    private static void checkFinalParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    public void testFinalParameterConstructor_withMetdata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("FinalParameter");
+        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
+        checkFinalParameter_withMetadata(constructor);
+    }
+
+    public void testFinalParameterMethod_withMetdata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("FinalParameter");
+        Method method = clazz.getDeclaredMethod("finalParameter", String.class);
+        checkFinalParameter_withMetadata(method);
+    }
+
+    private static void checkFinalParameter_withMetadata(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[final java.lang.String p0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkName(true /* expectedNameIsPresent */, "p0")
+                .checkModifiers(Modifier.FINAL)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    /**
+     * An inner class, used for checking compiler-inserted parameters: The first parameter is an
+     * instance of the surrounding class.
+     */
+    private class InnerClass {
+        @SuppressWarnings("unused")
+        public InnerClass() {}
+        @SuppressWarnings("unused")
+        public InnerClass(String p1) {}
+        @SuppressWarnings("unused")
+        public InnerClass(Function<String, Integer> p1) {}
+    }
+
+    public void testInnerClassSingleParameter() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = InnerClass.class;
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[" + outerClass.getName() + " arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    public void testInnerClassSingleParameter_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[final " + outerClass.getName() + " this$0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkName(true /* expectedNameIsPresent */, "this$0")
+                .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetParameterizedType("class " + outerClass.getName());
+    }
+
+    public void testInnerClassTwoParameters() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = InnerClass.class;
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, String.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString(
+                        "[" + outerClass.getName() + " arg0, java.lang.String arg1]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName());
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    public void testInnerClassTwoParameters_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, String.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString(
+                        "[final " + outerClass.getName() + " this$0, java.lang.String p1]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "this$0")
+                .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+
+        helper.getParameterTestHelper(1)
+                .checkName(true /* expectedNameIsPresent */, "p1")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    public void testInnerClassGenericParameter() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = InnerClass.class;
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, Function.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString(
+                        "[" + outerClass.getName() + " arg0, java.util.function.Function arg1]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(Function.class)
+                .checkGetParameterizedType("interface java.util.function.Function");
+
+        // The non-genericised string above is probably the result of a spec bug due to a mismatch
+        // between the generic signature for the constructor (which suggests a single parameter)
+        // and the actual parameters (which suggests two). In the absence of parameter metadata
+        // to identify the synthetic parameter the code reverts to using non-Signature (type erased)
+        // information.
+    }
+
+    public void testInnerClassGenericParameter_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, Function.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[final " + outerClass.getName() + " this$0, "
+                        + "java.util.function.Function<java.lang.String, java.lang.Integer> p1]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "this$0")
+                .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+
+        helper.getParameterTestHelper(1)
+                .checkName(true /* expectedNameIsPresent */, "p1")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetType(Function.class)
+                .checkGetParameterizedType(
+                        "java.util.function.Function<java.lang.String, java.lang.Integer>");
+    }
+
+    @SuppressWarnings("unused")
+    enum TestEnum { ONE, TWO }
+
+    /**
+     * Enums are a documented example of a type of class with synthetic constructor parameters and
+     * generated methods. This test may be brittle as it may rely on the compiler's implementation
+     * of enums.
+     */
+    public void testEnumConstructor() throws Exception {
+        Constructor<?> constructor = TestEnum.class.getDeclaredConstructor(String.class, int.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String arg0, int arg1]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(int.class)
+                .checkGetParameterizedType("int");
+    }
+
+    public void testEnumConstructor_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("TestEnum");
+        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                // The extra spaces below are the result of a trivial upstream bug in
+                // Parameter.toString() due to Modifier.toString(int) outputting nothing for
+                // "SYNTHETIC".
+                .checkParametersToString("[ java.lang.String $enum$name,  int $enum$ordinal]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "$enum$name")
+                .checkModifiers(4096) // 4096 == Modifier.SYNTHETIC
+                .checkImplicitAndSynthetic(false, true)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+
+        helper.getParameterTestHelper(1)
+                .checkName(true /* expectedNameIsPresent */, "$enum$ordinal")
+                .checkModifiers(4096) // 4096 == Modifier.SYNTHETIC
+                .checkImplicitAndSynthetic(false, true)
+                .checkGetType(int.class)
+                .checkGetParameterizedType("int");
+    }
+
+    public void testEnumValueOf() throws Exception {
+        Method method = TestEnum.class.getDeclaredMethod("valueOf", String.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(method);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    public void testEnumValueOf_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("TestEnum");
+        Method method = clazz.getDeclaredMethod("valueOf", String.class);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(method);
+        helper.checkStandardParametersBehavior()
+                // The extra space below are the result of a trivial upstream bug in
+                // Parameter.toString() due to Modifier.toString(int) outputting nothing for
+                // "MANDATED".
+                .checkParametersToString("[ java.lang.String name]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "name")
+                .checkModifiers(32768) // 32768 == Modifier.MANDATED
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetType(String.class)
+                .checkGetParameterizedType("class java.lang.String");
+    }
+
+    private static class SingleVarArgs {
+        @SuppressWarnings("unused")
+        SingleVarArgs(String... p0) {}
+
+        @SuppressWarnings("unused")
+        void varArgs(String... p0) {}
+    }
+
+    public void testSingleVarArgsConstructor() throws Exception {
+        Constructor<?> constructor = SingleVarArgs.class.getDeclaredConstructor(String[].class);
+        checkSingleVarArgsParameter(constructor);
+    }
+
+    public void testSingleVarArgsMethod() throws Exception {
+        Method method = SingleVarArgs.class.getDeclaredMethod("varArgs", String[].class);
+        checkSingleVarArgsParameter(method);
+    }
+
+    private static void checkSingleVarArgsParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String... arg0]")
+                .checkParametersMetadataNotAvailable();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(String[].class)
+                .checkIsVarArg(true)
+                .checkGetParameterizedType("class [Ljava.lang.String;");
+    }
+
+    public void testSingleVarArgsConstructor_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("SingleVarArgs");
+        Constructor<?> constructor = clazz.getDeclaredConstructor(String[].class);
+        checkSingleVarArgsParameter_withMetadata(constructor);
+    }
+
+    public void testSingleVarArgsMethod_withMetadata() throws Exception {
+        Class<?> clazz = loadTestInnerClassWithMetadata("SingleVarArgs");
+        Method method = clazz.getDeclaredMethod("varArgs", String[].class);
+        checkSingleVarArgsParameter_withMetadata(method);
+    }
+
+    private static void checkSingleVarArgsParameter_withMetadata(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.String... p0]");
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "p0")
+                .checkModifiers(0)
+                .checkImplicitAndSynthetic(false, false)
+                .checkGetType(String[].class)
+                .checkIsVarArg(true)
+                .checkGetParameterizedType("class [Ljava.lang.String;");
+    }
+
+    private static class MixedVarArgs {
+        @SuppressWarnings("unused")
+        MixedVarArgs(Integer[] p0, String... p1) {}
+        @SuppressWarnings("unused")
+        void both(Integer[] p0, String... p1) {}
+    }
+
+    public void testMixedVarArgsConstructor() throws Exception {
+        Constructor<?> constructor =
+                MixedVarArgs.class.getDeclaredConstructor(Integer[].class, String[].class);
+        checkMixedVarArgsParameter(constructor);
+    }
+
+    public void testMixedVarArgsMethod() throws Exception {
+        Method method = MixedVarArgs.class.getDeclaredMethod("both", Integer[].class, String[].class);
+        checkMixedVarArgsParameter(method);
+    }
+
+    private static void checkMixedVarArgsParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.Integer[] arg0, java.lang.String... arg1]")
+                .checkParametersMetadataNotAvailable();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(Integer[].class)
+                .checkIsVarArg(false)
+                .checkGetParameterizedType("class [Ljava.lang.Integer;");
+
+        helper.getParameterTestHelper(1)
+                .checkGetType(String[].class)
+                .checkIsVarArg(true)
+                .checkGetParameterizedType("class [Ljava.lang.String;");
+    }
+
+    private static class NonVarArgs {
+        @SuppressWarnings("unused")
+        NonVarArgs(Integer[] p0) {}
+        @SuppressWarnings("unused")
+        void notVarArgs(Integer[] p0) {}
+    }
+
+    public void testNonVarsArgsConstructor() throws Exception {
+        Constructor<?> constructor = NonVarArgs.class.getDeclaredConstructor(Integer[].class);
+        checkNonVarsArgsParameter(constructor);
+    }
+
+    public void testNonVarsArgsMethod() throws Exception {
+        Method method = NonVarArgs.class.getDeclaredMethod("notVarArgs", Integer[].class);
+        checkNonVarsArgsParameter(method);
+    }
+
+    private static void checkNonVarsArgsParameter(Executable executable) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(executable);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[java.lang.Integer[] arg0]")
+                .checkParametersMetadataNotAvailable();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(Integer[].class)
+                .checkIsVarArg(false)
+                .checkGetParameterizedType("class [Ljava.lang.Integer;");
+    }
+
+    public void testAnonymousClassConstructor() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = getAnonymousClassWith1ParameterConstructor();
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[" + outerClass.getName() + " arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    private Class<?> getAnonymousClassWith1ParameterConstructor() {
+        // Deliberately not implemented with a lambda. Do not refactor.
+        Callable<String> anonymousClassObject = new Callable<String>() {
+            @Override
+            public String call() throws Exception {
+                return ParameterTest.this.outerClassMethod();
+            }
+        };
+        return anonymousClassObject.getClass();
+    }
+
+    public void testAnonymousClassConstructor_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Object outer = outerClass.newInstance();
+        Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
+                "getAnonymousClassWith1ParameterConstructor").invoke(outer);
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[final " + outerClass.getName() + " this$0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "this$0")
+                .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    public void testMethodClassConstructor() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = getMethodClassWith1ImplicitParameterConstructor();
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[" + outerClass.getName() + " arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    private Class<?> getMethodClassWith1ImplicitParameterConstructor() {
+        class MethodClass {
+            MethodClass() {
+                ParameterTest.this.outerClassMethod();
+            }
+        }
+        return MethodClass.class;
+    }
+
+    public void testMethodClassConstructor_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Object outer = outerClass.newInstance();
+        Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
+                "getMethodClassWith1ImplicitParameterConstructor").invoke(outer);
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[final " + outerClass.getName() + " this$0]")
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkName(true /* expectedNameIsPresent */, "this$0")
+                .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
+                .checkImplicitAndSynthetic(true, false)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    public void testLambdaClassConstructor() throws Exception {
+        Class<?> outerClass = ParameterTest.class;
+        Class<?> innerClass = getLambdaClassWith1ParameterConstructor();
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        checkLambdaClassConstructor(outerClass, constructor);
+    }
+
+    private Class<?> getLambdaClassWith1ParameterConstructor() {
+        return ((Callable<?>) ParameterTest.this::outerClassMethod).getClass();
+    }
+
+    public void testLambdaClassConstructor_withMetadata() throws Exception {
+        Class<?> outerClass = loadTestOuterClassWithMetadata();
+        Object outer = outerClass.newInstance();
+        Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
+                "getLambdaClassWith1ParameterConstructor").invoke(outer);
+        Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
+
+        // There should be no parameter metadata for lambda classes.
+        checkLambdaClassConstructor(outerClass, constructor);
+    }
+
+    // This behavior is likely to be quite brittle and may not be specified.
+    private void checkLambdaClassConstructor(Class<?> outerClass, Constructor<?> constructor) {
+        ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
+        helper.checkStandardParametersBehavior()
+                .checkParametersToString("[" + outerClass.getName() + " arg0]")
+                .checkParametersMetadataNotAvailable()
+                .checkParametersNoVarArgs();
+
+        helper.getParameterTestHelper(0)
+                .checkGetType(outerClass)
+                .checkGetParameterizedType("class " + outerClass.getName() + "");
+    }
+
+    private static class NonIdenticalParameters {
+        @SuppressWarnings("unused")
+        void method0(String p0) {}
+        @SuppressWarnings("unused")
+        void method1(String p0) {}
+    }
+
+    public void testEquals_checksExecutable() throws Exception {
+        Method method0 = NonIdenticalParameters.class.getDeclaredMethod("method0", String.class);
+        Method method1 = NonIdenticalParameters.class.getDeclaredMethod("method1", String.class);
+        Parameter method0P0 = method0.getParameters()[0];
+        Parameter method1P0 = method1.getParameters()[0];
+        assertFalse(method0P0.equals(method1P0));
+        assertFalse(method1P0.equals(method0P0));
+        assertTrue(method0P0.equals(method0P0));
+    }
+
+    public void testManyParameters_withMetadata() throws Exception {
+        int expectedParameterCount = 300;
+        Class<?>[] parameterTypes = new Class[expectedParameterCount];
+        Arrays.fill(parameterTypes, int.class);
+        Method method = getMetadataVariationsMethod("manyParameters", parameterTypes);
+        Parameter[] parameters = method.getParameters();
+        assertEquals(expectedParameterCount, parameters.length);
+
+        NumberFormat format = NumberFormat.getIntegerInstance();
+        format.setMinimumIntegerDigits(3);
+        for (int i = 0; i < parameters.length; i++) {
+            assertEquals(true, parameters[i].isNamePresent());
+            assertEquals(Modifier.FINAL, parameters[i].getModifiers());
+            assertEquals("a" + format.format(i), parameters[i].getName());
+        }
+    }
+
+    public void testEmptyMethodParametersAnnotation_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("emptyMethodParametersAnnotation");
+        assertEquals(0, method.getParameters().length);
+    }
+
+    public void testTooManyAccessFlags_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("tooManyAccessFlags", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testTooFewAccessFlags_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod(
+                "tooFewAccessFlags", String.class, String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testTooManyNames_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("tooManyNames", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testTooFewNames_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("tooFewNames", String.class, String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testTooManyBoth_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("tooManyBoth", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testTooFewBoth_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("tooFewBoth", String.class, String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testNullName_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("nullName", String.class);
+        Parameter parameter0 = method.getParameters()[0];
+        assertEquals("arg0", parameter0.getName());
+        assertEquals(Modifier.FINAL, parameter0.getModifiers());
+    }
+
+    public void testEmptyName_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("emptyName", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testNameWithSemicolon_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("nameWithSemicolon", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testNameWithSlash_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("nameWithSlash", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testNameWithPeriod_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("nameWithPeriod", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testNameWithOpenSquareBracket_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("nameWithOpenSquareBracket", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testBadAccessModifier_withMetadata() throws Exception {
+        Method method = getMetadataVariationsMethod("badAccessModifier", String.class);
+        checkGetParametersThrowsMalformedParametersException(method);
+    }
+
+    public void testBadlyFormedAnnotation() throws Exception {
+        Method method = getMetadataVariationsMethod("badlyFormedAnnotation", String.class);
+        // Badly formed annotations are treated as if the annotation is entirely absent.
+        Parameter parameter0 = method.getParameters()[0];
+        assertFalse(parameter0.isNamePresent());
+    }
+
+    /** A non-static method that exists to be called by inner classes, lambdas, etc. */
+    private String outerClassMethod() {
+        return "Howdy";
+    }
+
+    private static class ExecutableTestHelper {
+        private final Executable executable;
+
+        ExecutableTestHelper(Executable executable) {
+            this.executable = executable;
+        }
+
+        @DependsOnParameterMetadata
+        ExecutableTestHelper checkParametersToString(String expectedString) {
+            assertEquals(expectedString, Arrays.toString(executable.getParameters()));
+            return this;
+        }
+
+        /**
+         * Combines checks that should be true of any result from
+         * {@link Executable#getParameters()}
+         */
+        ExecutableTestHelper checkStandardParametersBehavior() {
+            return checkGetParametersClonesArray()
+                    .checkParametersGetDeclaringExecutable()
+                    .checkParametersEquals()
+                    .checkParametersHashcode();
+        }
+
+        ExecutableTestHelper checkParametersGetDeclaringExecutable() {
+            for (Parameter p : executable.getParameters()) {
+                assertSame(executable, p.getDeclaringExecutable());
+            }
+            return this;
+        }
+
+        ExecutableTestHelper checkGetParametersClonesArray() {
+            Parameter[] parameters1 = executable.getParameters();
+            Parameter[] parameters2 = executable.getParameters();
+            assertNotSame(parameters1, parameters2);
+
+            assertEquals(parameters1.length, parameters2.length);
+            for (int i = 0; i < parameters1.length; i++) {
+                assertSame(parameters1[i], parameters2[i]);
+            }
+            return this;
+        }
+
+        ExecutableTestHelper checkParametersEquals() {
+            Parameter[] parameters = executable.getParameters();
+            for (int i = 0; i < parameters.length; i++) {
+                assertEquals(parameters[i], parameters[i]);
+                if (i > 0) {
+                    assertFalse(parameters[0].equals(parameters[i]));
+                    assertFalse(parameters[i].equals(parameters[0]));
+                }
+            }
+            return this;
+        }
+
+        ExecutableTestHelper checkParametersHashcode() {
+            for (Parameter parameter : executable.getParameters()) {
+                // Not much to assert. Just call the method and check it is consistent.
+                assertEquals(parameter.hashCode(), parameter.hashCode());
+            }
+            return this;
+        }
+
+        @DependsOnParameterMetadata
+        ExecutableTestHelper checkParametersMetadataNotAvailable() {
+            ParameterTestHelper[] parameterTestHelpers = getParameterTestHelpers();
+            for (int i = 0; i < parameterTestHelpers.length; i++) {
+                ParameterTestHelper parameterTestHelper = parameterTestHelpers[i];
+                parameterTestHelper.checkName(false, "arg" + i)
+                        .checkImplicitAndSynthetic(false, false)
+                        .checkModifiers(0);
+            }
+            return this;
+        }
+
+        /**
+         * Checks that non of the parameters return {@code true} for {@link Parameter#isVarArgs()}.
+         */
+        ExecutableTestHelper checkParametersNoVarArgs() {
+            for (ParameterTestHelper parameterTestHelper : getParameterTestHelpers()) {
+                parameterTestHelper.checkIsVarArg(false);
+            }
+            return this;
+        }
+
+        ParameterTestHelper getParameterTestHelper(int index) {
+            return new ParameterTestHelper(executable.getParameters()[index]);
+        }
+
+        private ParameterTestHelper[] getParameterTestHelpers() {
+            final int parameterCount = executable.getParameterCount();
+            ParameterTestHelper[] parameterTestHelpers = new ParameterTestHelper[parameterCount];
+            for (int i = 0; i < parameterCount; i++) {
+                parameterTestHelpers[i] = getParameterTestHelper(i);
+            }
+            return parameterTestHelpers;
+        }
+
+        private static class ParameterTestHelper {
+            private final Parameter parameter;
+
+            ParameterTestHelper(Parameter parameter) {
+                this.parameter = parameter;
+            }
+
+            ParameterTestHelper checkGetType(Class<?> expectedType) {
+                assertEquals(expectedType, parameter.getType());
+                return this;
+            }
+
+            @DependsOnParameterMetadata
+            ParameterTestHelper checkName(boolean expectedIsNamePresent, String expectedName) {
+                assertEquals(expectedIsNamePresent, parameter.isNamePresent());
+                assertEquals(expectedName, parameter.getName());
+                return this;
+            }
+
+            @DependsOnParameterMetadata
+            ParameterTestHelper checkModifiers(int expectedModifiers) {
+                assertEquals(expectedModifiers, parameter.getModifiers());
+                return this;
+            }
+
+            ParameterTestHelper checkGetParameterizedType(String expectedParameterizedTypeString) {
+                assertEquals(
+                        expectedParameterizedTypeString,
+                        parameter.getParameterizedType().toString());
+                return this;
+            }
+
+            @DependsOnParameterMetadata
+            ParameterTestHelper checkImplicitAndSynthetic(
+                    boolean expectedIsImplicit, boolean expectedIsSynthetic) {
+                assertEquals(expectedIsImplicit, parameter.isImplicit());
+                assertEquals(expectedIsSynthetic, parameter.isSynthetic());
+                return this;
+            }
+
+            ParameterTestHelper checkIsVarArg(boolean expectedIsVarArg) {
+                assertEquals(expectedIsVarArg, parameter.isVarArgs());
+                return this;
+            }
+        }
+    }
+
+    private static ClassLoader createClassLoaderForDexResource(File dexDir, String resourceName)
+            throws Exception {
+        File dexFile = new File(dexDir, resourceName);
+        copyResource(resourceName, dexFile);
+        return new PathClassLoader(dexFile.getAbsolutePath(), ClassLoader.getSystemClassLoader());
+    }
+
+    /**
+     * Copy a resource in the libcore/java/lang/reflect/parameter/ resource path to the indicated
+     * target file.
+     */
+    private static void copyResource(String resourceName, File destination) throws Exception {
+        assertFalse(destination.exists());
+        ClassLoader classLoader = ParameterTest.class.getClassLoader();
+        assertNotNull(classLoader);
+
+        final String RESOURCE_PATH = "libcore/java/lang/reflect/parameter/";
+        String fullResourcePath = RESOURCE_PATH + resourceName;
+        try (InputStream in = classLoader.getResourceAsStream(fullResourcePath);
+             FileOutputStream out = new FileOutputStream(destination)) {
+            if (in == null) {
+                throw new IllegalStateException("Resource not found: " + fullResourcePath);
+            }
+            Streams.copy(in, out);
+        }
+    }
+
+    /**
+     * Loads an inner class from the ParameterMetadataTestClasses class defined in a separate dex
+     * file. See src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
+     */
+    private Class<?> loadTestInnerClassWithMetadata(String name) throws Exception {
+        return classesWithMetadataClassLoader.loadClass(
+                "libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses$" + name);
+    }
+
+    /**
+     * Loads the ParameterMetadataTestClasses class defined in a separate dex file.
+     * See src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
+     */
+    private Class<?> loadTestOuterClassWithMetadata() throws Exception {
+        return classesWithMetadataClassLoader.loadClass(
+                "libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses");
+    }
+
+    /**
+     * Loads a method from the MetadataVariations class defined in a separate dex file. See
+     * src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
+     */
+    private Method getMetadataVariationsMethod(String methodName, Class<?>... parameterTypes)
+            throws Exception {
+        Class<?> metadataVariationsClass = metadataVariationsClassLoader.loadClass(
+                "libcore.java.lang.reflect.parameter.MetadataVariations");
+        return metadataVariationsClass.getDeclaredMethod(methodName, parameterTypes);
+    }
+
+    private static void checkGetParametersThrowsMalformedParametersException(Method method) {
+        try {
+            method.getParameters();
+            fail();
+        } catch (MalformedParametersException expected) {}
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java
new file mode 100644
index 0000000..aa14bd3
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
+
+/**
+ * Tests for the {@link java.lang.reflect.AnnotatedElement} methods from the {@link Parameter}
+ * objects obtained from both {@link Constructor} and {@link Method}.
+ */
+public class AnnotatedElementParameterTest extends TestCase {
+
+    private static class MethodClass {
+        public void methodWithoutAnnotatedParameters(String parameter1, String parameter2) {}
+
+        public void methodWithAnnotatedParameters(@AnnotationB @AnnotationD String parameter1,
+                @AnnotationC @AnnotationD String parameter2) {}
+    }
+
+    public void testMethodParameterAnnotations() throws Exception {
+        Class<?> c = MethodClass.class;
+        {
+            Parameter[] parameters = c.getDeclaredMethod(
+                    "methodWithoutAnnotatedParameters", String.class, String.class).getParameters();
+            Parameter parameter0 = parameters[0];
+            checkAnnotatedElementPresentMethods(parameter0);
+
+            Parameter parameter1 = parameters[1];
+            checkAnnotatedElementPresentMethods(parameter1);
+        }
+        {
+            Parameter[] parameters = c.getDeclaredMethod(
+                    "methodWithAnnotatedParameters", String.class, String.class).getParameters();
+
+            Parameter parameter0 = parameters[0];
+            checkAnnotatedElementPresentMethods(parameter0, AnnotationB.class, AnnotationD.class);
+
+            Parameter parameter1 = parameters[1];
+            checkAnnotatedElementPresentMethods(parameter1, AnnotationC.class, AnnotationD.class);
+        }
+    }
+
+    private static class ConstructorClass {
+        // No annotations.
+        public ConstructorClass(Integer parameter1, Integer parameter2) {}
+
+        // Annotations.
+        public ConstructorClass(@AnnotationB @AnnotationD String parameter1,
+                @AnnotationC @AnnotationD String parameter2) {}
+    }
+
+    public void testConstructorParameterAnnotations() throws Exception {
+        Class<?> c = ConstructorClass.class;
+        {
+            Parameter[] parameters =
+                    c.getDeclaredConstructor(Integer.class, Integer.class).getParameters();
+            Parameter parameter0 = parameters[0];
+            checkAnnotatedElementPresentMethods(parameter0);
+
+            Parameter parameter1 = parameters[1];
+            checkAnnotatedElementPresentMethods(parameter1);
+        }
+        {
+            Parameter[] parameters =
+                    c.getDeclaredConstructor(String.class, String.class).getParameters();
+
+            Parameter parameter0 = parameters[0];
+            checkAnnotatedElementPresentMethods(parameter0, AnnotationB.class, AnnotationD.class);
+
+            Parameter parameter1 = parameters[1];
+            checkAnnotatedElementPresentMethods(parameter1, AnnotationC.class, AnnotationD.class);
+        }
+    }
+
+    private static class AnnotatedMethodClass {
+        void noAnnotation(String p0) {}
+
+        void multipleAnnotationOddity(
+                @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) String p0) {}
+
+        void multipleAnnotationExplicitSingle(@Container({@Repeated(1)}) String p0) {}
+
+        void multipleAnnotation(@Repeated(1) @Repeated(2) String p0) {}
+
+        void singleAnnotation(@Repeated(1) String p0) {}
+
+        static Method getMethodWithoutAnnotations() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("noAnnotation", String.class);
+        }
+
+        static Method getMethodMultipleAnnotationOddity() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod(
+                    "multipleAnnotationOddity", String.class);
+        }
+
+        static Method getMethodMultipleAnnotationExplicitSingle() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod(
+                    "multipleAnnotationExplicitSingle", String.class);
+        }
+
+        static Method getMethodMultipleAnnotation() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("multipleAnnotation", String.class);
+        }
+
+        static Method getMethodSingleAnnotation() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("singleAnnotation", String.class);
+        }
+    }
+
+    // Tests for isAnnotationPresent and getDeclaredAnnotation.
+    public void testMethodDeclaredAnnotation() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                container, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                container, null);
+    }
+
+    private static class AnnotatedConstructorClass {
+        public AnnotatedConstructorClass(Boolean p0) {}
+
+        public AnnotatedConstructorClass(
+                @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) Long p0) {}
+
+        public AnnotatedConstructorClass(@Container({@Repeated(1)}) Double p0) {}
+
+        public AnnotatedConstructorClass(@Repeated(1) @Repeated(2) Integer p0) {}
+
+        public AnnotatedConstructorClass(@Repeated(1) String p0) {}
+
+        static Constructor<?> getConstructorWithoutAnnotations() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Boolean.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotationOddity() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Long.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotationExplicitSingle()
+                throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Double.class);
+        }
+
+        static Constructor<?> getConstructorSingleAnnotation() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(String.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotation() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Integer.class);
+        }
+    }
+
+    // Tests for isAnnotationPresent and getDeclaredAnnotation.
+    public void testConstructorDeclaredAnnotation() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                repeated, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                container, null);
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0DeclaredAnnotation(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                container, null);
+    }
+
+    private static void checkParameter0DeclaredAnnotation(
+            Executable executable, Class<? extends Annotation> annotationType,
+            String expectedAnnotationString) throws Exception {
+        Parameter parameter = executable.getParameters()[0];
+
+        // isAnnotationPresent
+        assertIsAnnotationPresent(parameter, annotationType, expectedAnnotationString != null);
+
+        // getDeclaredAnnotation
+        assertGetDeclaredAnnotation(parameter, annotationType, expectedAnnotationString);
+    }
+
+    public void testMethodGetDeclaredAnnotationsByType() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                repeated, EXPECT_EMPTY);
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                repeated, "@Repeated(1)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                repeated, "@Repeated(1)", "@Repeated(2)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                container, EXPECT_EMPTY);
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                container, EXPECT_EMPTY);
+    }
+
+    public void testConstructorGetDeclaredAnnotationsByType() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                repeated, EXPECT_EMPTY);
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                repeated, "@Repeated(1)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                repeated, "@Repeated(1)", "@Repeated(2)");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                container, EXPECT_EMPTY);
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0GetDeclaredAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                container, EXPECT_EMPTY);
+    }
+
+    private static void checkParameter0GetDeclaredAnnotationsByType(
+            Executable executable, Class<? extends Annotation> annotationType,
+            String... expectedAnnotationStrings) throws Exception {
+        Parameter parameter = executable.getParameters()[0];
+        AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+                parameter, annotationType, expectedAnnotationStrings);
+    }
+
+    public void testMethodGetAnnotationsByType() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                repeated, EXPECT_EMPTY);
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                repeated, "@Repeated(1)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                repeated, "@Repeated(1)", "@Repeated(2)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(),
+                container, EXPECT_EMPTY);
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                container, EXPECT_EMPTY);
+    }
+
+    public void testConstructorGetAnnotationsByType() throws Exception {
+        Class<? extends Annotation> repeated = Repeated.class;
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                repeated, EXPECT_EMPTY);
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                repeated, "@Repeated(1)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                repeated, "@Repeated(1)", "@Repeated(2)");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                repeated, "@Repeated(1)");
+
+        Class<? extends Annotation> container = Container.class;
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                container, EXPECT_EMPTY);
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                container, "@Container({@Repeated(2), @Repeated(3)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                container, "@Container({@Repeated(1)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                container, "@Container({@Repeated(1), @Repeated(2)})");
+        checkParameter0GetAnnotationsByType(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                container, EXPECT_EMPTY);
+    }
+
+    private static void checkParameter0GetAnnotationsByType(
+            Executable executable, Class<? extends Annotation> annotationType,
+            String... expectedAnnotationStrings) throws Exception {
+        Parameter parameter = executable.getParameters()[0];
+        AnnotatedElementTestSupport.assertGetAnnotationsByType(
+                parameter, annotationType, expectedAnnotationStrings);
+    }
+
+    /**
+     * As an inner class the constructor will actually have two parameters: the first, referencing
+     * the enclosing object, is inserted by the compiler.
+     */
+    class InnerClass {
+        InnerClass(@Repeated(1) String p1) {}
+    }
+
+    /** Special case testing for a compiler-generated constructor parameter. */
+    public void testImplicitConstructorParameters_singleAnnotation() throws Exception {
+        Constructor<InnerClass> constructor =
+                InnerClass.class.getDeclaredConstructor(
+                        AnnotatedElementParameterTest.class, String.class);
+        Parameter[] parameters = constructor.getParameters();
+
+        // The compiler-generated constructor should have no annotations.
+        Parameter parameter0 = parameters[0];
+        AnnotatedElementTestSupport.assertGetAnnotationsByType(
+                parameter0, Repeated.class, new String[0]);
+        AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+                parameter0, Repeated.class, new String[0]);
+        AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
+                parameter0, Repeated.class, null);
+        AnnotatedElementTestSupport.assertIsAnnotationPresent(parameter0, Repeated.class, false);
+
+        // The annotation should remain on the correct parameter.
+        Parameter parameter1 = parameters[1];
+        AnnotatedElementTestSupport.assertGetAnnotationsByType(
+                parameter1, Repeated.class, new String[] {"@Repeated(1)"});
+        AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+                parameter1, Repeated.class, new String[] {"@Repeated(1)"});
+        AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
+                parameter1, Repeated.class, "@Repeated(1)");
+        AnnotatedElementTestSupport.assertIsAnnotationPresent(
+                parameter1, Repeated.class, true);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java
index ec57469..b17fbff 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java
@@ -95,8 +95,8 @@
      * returns annotations of the supplied expected classes.
      *
      * <p>Where the expected classes contains some subset from
-     * {@link AnnotationA}, {@link AnnotationB} and {@link AnnotationC}, this method also asserts
-     * that {@link AnnotatedElement#isAnnotationPresent(Class)} and
+     * {@link AnnotationA}, {@link AnnotationB}, {@link AnnotationC}, {@link AnnotationD} this
+     * method also asserts that {@link AnnotatedElement#isAnnotationPresent(Class)} and
      * {@link AnnotatedElement#getAnnotation(Class)} works as expected.
      *
      * <p>This method also confirms that {@link AnnotatedElement#isAnnotationPresent(Class)} and
@@ -112,6 +112,7 @@
         assertPresent(expectedTypes.contains(AnnotationA.class), element, AnnotationA.class);
         assertPresent(expectedTypes.contains(AnnotationB.class), element, AnnotationB.class);
         assertPresent(expectedTypes.contains(AnnotationC.class), element, AnnotationC.class);
+        assertPresent(expectedTypes.contains(AnnotationD.class), element, AnnotationD.class);
 
         try {
             element.isAnnotationPresent(null);
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java
new file mode 100644
index 0000000..a07f2b3
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.annotationsToTypes;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertAnnotationsMatch;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.set;
+
+/**
+ * Tests for {@link Executable#getParameterAnnotations()} via the {@link Constructor} and
+ * {@link Method} classes. See {@link AnnotatedElementParameterTest} for testing of the
+ * {@link java.lang.reflect.AnnotatedElement} methods.
+ */
+public class ExecutableParameterTest extends TestCase {
+    private static class MethodClass {
+        public void methodWithoutAnnotatedParameters(String parameter1, String parameter2) {}
+
+        public void methodWithAnnotatedParameters(@AnnotationB @AnnotationD String parameter1,
+                @AnnotationC @AnnotationD String parameter2) {}
+    }
+
+    public void testMethodGetParameterAnnotations() throws Exception {
+        Method methodWithoutAnnotatedParameters = MethodClass.class.getMethod(
+                "methodWithoutAnnotatedParameters", String.class, String.class);
+        Annotation[][] noParameterAnnotations =
+                methodWithoutAnnotatedParameters.getParameterAnnotations();
+        assertEquals(2, noParameterAnnotations.length);
+        assertEquals(set(), annotationsToTypes(noParameterAnnotations[0]));
+        assertEquals(set(), annotationsToTypes(noParameterAnnotations[1]));
+
+        Method methodWithAnnotatedParameters = MethodClass.class.getMethod(
+                "methodWithAnnotatedParameters", String.class, String.class);
+        Annotation[][] parameterAnnotations =
+                methodWithAnnotatedParameters.getParameterAnnotations();
+        assertEquals(2, parameterAnnotations.length);
+        assertEquals(set(AnnotationB.class, AnnotationD.class),
+                annotationsToTypes(parameterAnnotations[0]));
+        assertEquals(set(AnnotationC.class, AnnotationD.class),
+                annotationsToTypes(parameterAnnotations[1]));
+    }
+
+    private static class ConstructorClass {
+        // No annotations.
+        public ConstructorClass(Integer parameter1, Integer parameter2) {}
+
+        // Annotations.
+        public ConstructorClass(@AnnotationB @AnnotationD String parameter1,
+                @AnnotationC @AnnotationD String parameter2) {}
+    }
+
+    public void testConstructorGetParameterAnnotations() throws Exception {
+        Constructor constructorWithoutAnnotatedParameters =
+                ConstructorClass.class.getDeclaredConstructor(Integer.class, Integer.class);
+        Annotation[][] noParameterAnnotations =
+                constructorWithoutAnnotatedParameters.getParameterAnnotations();
+        assertEquals(2, noParameterAnnotations.length);
+        assertEquals(set(), annotationsToTypes(noParameterAnnotations[0]));
+        assertEquals(set(), annotationsToTypes(noParameterAnnotations[1]));
+
+        Constructor constructorWithAnnotatedParameters =
+                ConstructorClass.class.getDeclaredConstructor(String.class, String.class);
+        Annotation[][] parameterAnnotations =
+                constructorWithAnnotatedParameters.getParameterAnnotations();
+        assertEquals(2, parameterAnnotations.length);
+        assertEquals(set(AnnotationB.class, AnnotationD.class),
+                annotationsToTypes(parameterAnnotations[0]));
+        assertEquals(set(AnnotationC.class, AnnotationD.class),
+                annotationsToTypes(parameterAnnotations[1]));
+    }
+
+    private static class AnnotatedMethodClass {
+        void noAnnotation(String p0) {}
+
+        void multipleAnnotationOddity(
+                @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) String p0) {}
+
+        void multipleAnnotationExplicitSingle(@Container({@Repeated(1)}) String p0) {}
+
+        void multipleAnnotation(@Repeated(1) @Repeated(2) String p0) {}
+
+        void singleAnnotation(@Repeated(1) String p0) {}
+
+        static Method getMethodWithoutAnnotations() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("noAnnotation", String.class);
+        }
+
+        static Method getMethodMultipleAnnotationOddity() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod(
+                    "multipleAnnotationOddity", String.class);
+        }
+
+        static Method getMethodMultipleAnnotationExplicitSingle() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod(
+                    "multipleAnnotationExplicitSingle", String.class);
+        }
+
+        static Method getMethodMultipleAnnotation() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("multipleAnnotation", String.class);
+        }
+
+        static Method getMethodSingleAnnotation() throws Exception {
+            return AnnotatedMethodClass.class.getDeclaredMethod("singleAnnotation", String.class);
+        }
+    }
+
+    public void testMethodGetParameterAnnotations_repeated() throws Exception {
+        assertParameter0Annotations(
+                AnnotatedMethodClass.getMethodWithoutAnnotations(), EXPECT_EMPTY);
+        assertParameter0Annotations(
+                AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
+                "@Repeated(1)", "@Container({@Repeated(2), @Repeated(3)})");
+        assertParameter0Annotations(
+                AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
+                "@Container({@Repeated(1)})");
+        assertParameter0Annotations(
+                AnnotatedMethodClass.getMethodMultipleAnnotation(),
+                "@Container({@Repeated(1), @Repeated(2)})");
+        assertParameter0Annotations(
+                AnnotatedMethodClass.getMethodSingleAnnotation(),
+                "@Repeated(1)");
+    }
+
+    private static class AnnotatedConstructorClass {
+        public AnnotatedConstructorClass(Boolean p0) {}
+
+        public AnnotatedConstructorClass(
+                @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) Long p0) {}
+
+        public AnnotatedConstructorClass(@Container({@Repeated(1)}) Double p0) {}
+
+        public AnnotatedConstructorClass(@Repeated(1) @Repeated(2) Integer p0) {}
+
+        public AnnotatedConstructorClass(@Repeated(1) String p0) {}
+
+        static Constructor<?> getConstructorWithoutAnnotations() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Boolean.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotationOddity() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Long.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotationExplicitSingle()
+                throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Double.class);
+        }
+
+        static Constructor<?> getConstructorMultipleAnnotation() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(Integer.class);
+        }
+
+        static Constructor<?> getConstructorSingleAnnotation() throws Exception {
+            return AnnotatedConstructorClass.class.getDeclaredConstructor(String.class);
+        }
+    }
+
+    public void testConstructorGetParameterAnnotations_repeated() throws Exception {
+        assertParameter0Annotations(
+                AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
+                EXPECT_EMPTY);
+        assertParameter0Annotations(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
+                "@Repeated(1)", "@Container({@Repeated(2), @Repeated(3)})");
+        assertParameter0Annotations(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
+                "@Container({@Repeated(1)})");
+        assertParameter0Annotations(
+                AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
+                "@Container({@Repeated(1), @Repeated(2)})");
+        assertParameter0Annotations(
+                AnnotatedConstructorClass.getConstructorSingleAnnotation(),
+                "@Repeated(1)");
+    }
+
+    private static void assertParameter0Annotations(
+            Executable executable, String... expectedAnnotationStrings) throws Exception {
+        Annotation[][] allAnnotations = executable.getParameterAnnotations();
+        final int expectedParameterCount = 1;
+        assertEquals(expectedParameterCount, allAnnotations.length);
+
+        Annotation[] p0Annotations = allAnnotations[0];
+        assertAnnotationsMatch(p0Annotations, expectedAnnotationStrings);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java
deleted file mode 100644
index f40ac9f..0000000
--- a/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.java.lang.reflect.annotations;
-
-import junit.framework.TestCase;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
-import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
-import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
-import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
-import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
-
-import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
-import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.annotationsToTypes;
-import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertAnnotationsMatch;
-import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.set;
-
-public class ParameterTest extends TestCase {
-    private static class Type {
-        @AnnotationB
-        @AnnotationC
-        public void method(String parameter1, String parameter2) {}
-
-        @AnnotationB
-        @AnnotationC
-        public void parameters(@AnnotationB @AnnotationD String parameter1,
-                @AnnotationC @AnnotationD String parameter2) {}
-    }
-
-    public void testParameterAnnotations() throws Exception {
-        Method method = Type.class.getMethod("method", String.class, String.class);
-        Annotation[][] noParameterAnnotations = method.getParameterAnnotations();
-        assertEquals(2, noParameterAnnotations.length);
-        assertEquals(set(), annotationsToTypes(noParameterAnnotations[0]));
-        assertEquals(set(), annotationsToTypes(noParameterAnnotations[1]));
-
-        Method parameters = Type.class.getMethod("parameters", String.class, String.class);
-        Annotation[][] parameterAnnotations = parameters.getParameterAnnotations();
-        assertEquals(2, parameterAnnotations.length);
-        assertEquals(set(AnnotationB.class, AnnotationD.class),
-                annotationsToTypes(parameterAnnotations[0]));
-        assertEquals(set(AnnotationC.class, AnnotationD.class),
-                annotationsToTypes(parameterAnnotations[1]));
-    }
-
-    private static class AnnotatedClass {
-        public void singleAnnotation(@Repeated(1) String p0) {}
-
-        public void multipleAnnotation(@Repeated(1) @Repeated(2) String p0) {}
-
-        public void multipleAnnotationExplicitSingle(@Container({@Repeated(1)}) String p0) {}
-
-        public void multipleAnnotationOddity(
-                @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) String p0) {}
-
-        public void noAnnotation(String p0) {}
-    }
-
-    public void testGetParameterAnnotations() throws Exception {
-        Class<?> c = AnnotatedClass.class;
-
-        assertParameter0Annotations(c, "noAnnotation", EXPECT_EMPTY);
-        assertParameter0Annotations(c, "multipleAnnotationOddity",
-                "@Repeated(1)", "@Container({@Repeated(2), @Repeated(3)})");
-        assertParameter0Annotations(c, "multipleAnnotationExplicitSingle",
-                "@Container({@Repeated(1)})");
-        assertParameter0Annotations(c, "multipleAnnotation",
-                "@Container({@Repeated(1), @Repeated(2)})");
-        assertParameter0Annotations(c, "singleAnnotation",
-                "@Repeated(1)");
-    }
-
-    private static void assertParameter0Annotations(
-            Class<?> c, String methodName, String... expectedAnnotationStrings) throws Exception {
-        Annotation[][] allAnnotations =
-                c.getDeclaredMethod(methodName, String.class).getParameterAnnotations();
-        final int expectedParameterCount = 1;
-        assertEquals(expectedParameterCount, allAnnotations.length);
-
-        Annotation[] p0Annotations = allAnnotations[0];
-        assertAnnotationsMatch(p0Annotations, expectedAnnotationStrings);
-    }
-}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/MetadataVariations.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/MetadataVariations.smali
new file mode 100644
index 0000000..9d76dc9
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/MetadataVariations.smali
@@ -0,0 +1,779 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class public interface abstract Llibcore/java/lang/reflect/parameter/MetadataVariations;
+.super Ljava/lang/Object;
+.source "MetadataVariations.java"
+
+
+# virtual methods
+.method public abstract badAccessModifier(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0xFF
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+.end method
+
+.method public abstract badlyFormedAnnotation(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0xFF
+        }
+    .end annotation
+.end method
+
+.method public abstract emptyMethodParametersAnnotation()V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {}
+        names = {}
+    .end annotation
+.end method
+
+.method public abstract emptyName(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            ""
+        }
+    .end annotation
+.end method
+
+.method public abstract manyParameters(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10,
+            0x10
+        }
+        names = {
+            "a000",
+            "a001",
+            "a002",
+            "a003",
+            "a004",
+            "a005",
+            "a006",
+            "a007",
+            "a008",
+            "a009",
+            "a010",
+            "a011",
+            "a012",
+            "a013",
+            "a014",
+            "a015",
+            "a016",
+            "a017",
+            "a018",
+            "a019",
+            "a020",
+            "a021",
+            "a022",
+            "a023",
+            "a024",
+            "a025",
+            "a026",
+            "a027",
+            "a028",
+            "a029",
+            "a030",
+            "a031",
+            "a032",
+            "a033",
+            "a034",
+            "a035",
+            "a036",
+            "a037",
+            "a038",
+            "a039",
+            "a040",
+            "a041",
+            "a042",
+            "a043",
+            "a044",
+            "a045",
+            "a046",
+            "a047",
+            "a048",
+            "a049",
+            "a050",
+            "a051",
+            "a052",
+            "a053",
+            "a054",
+            "a055",
+            "a056",
+            "a057",
+            "a058",
+            "a059",
+            "a060",
+            "a061",
+            "a062",
+            "a063",
+            "a064",
+            "a065",
+            "a066",
+            "a067",
+            "a068",
+            "a069",
+            "a070",
+            "a071",
+            "a072",
+            "a073",
+            "a074",
+            "a075",
+            "a076",
+            "a077",
+            "a078",
+            "a079",
+            "a080",
+            "a081",
+            "a082",
+            "a083",
+            "a084",
+            "a085",
+            "a086",
+            "a087",
+            "a088",
+            "a089",
+            "a090",
+            "a091",
+            "a092",
+            "a093",
+            "a094",
+            "a095",
+            "a096",
+            "a097",
+            "a098",
+            "a099",
+            "a100",
+            "a101",
+            "a102",
+            "a103",
+            "a104",
+            "a105",
+            "a106",
+            "a107",
+            "a108",
+            "a109",
+            "a110",
+            "a111",
+            "a112",
+            "a113",
+            "a114",
+            "a115",
+            "a116",
+            "a117",
+            "a118",
+            "a119",
+            "a120",
+            "a121",
+            "a122",
+            "a123",
+            "a124",
+            "a125",
+            "a126",
+            "a127",
+            "a128",
+            "a129",
+            "a130",
+            "a131",
+            "a132",
+            "a133",
+            "a134",
+            "a135",
+            "a136",
+            "a137",
+            "a138",
+            "a139",
+            "a140",
+            "a141",
+            "a142",
+            "a143",
+            "a144",
+            "a145",
+            "a146",
+            "a147",
+            "a148",
+            "a149",
+            "a150",
+            "a151",
+            "a152",
+            "a153",
+            "a154",
+            "a155",
+            "a156",
+            "a157",
+            "a158",
+            "a159",
+            "a160",
+            "a161",
+            "a162",
+            "a163",
+            "a164",
+            "a165",
+            "a166",
+            "a167",
+            "a168",
+            "a169",
+            "a170",
+            "a171",
+            "a172",
+            "a173",
+            "a174",
+            "a175",
+            "a176",
+            "a177",
+            "a178",
+            "a179",
+            "a180",
+            "a181",
+            "a182",
+            "a183",
+            "a184",
+            "a185",
+            "a186",
+            "a187",
+            "a188",
+            "a189",
+            "a190",
+            "a191",
+            "a192",
+            "a193",
+            "a194",
+            "a195",
+            "a196",
+            "a197",
+            "a198",
+            "a199",
+            "a200",
+            "a201",
+            "a202",
+            "a203",
+            "a204",
+            "a205",
+            "a206",
+            "a207",
+            "a208",
+            "a209",
+            "a210",
+            "a211",
+            "a212",
+            "a213",
+            "a214",
+            "a215",
+            "a216",
+            "a217",
+            "a218",
+            "a219",
+            "a220",
+            "a221",
+            "a222",
+            "a223",
+            "a224",
+            "a225",
+            "a226",
+            "a227",
+            "a228",
+            "a229",
+            "a230",
+            "a231",
+            "a232",
+            "a233",
+            "a234",
+            "a235",
+            "a236",
+            "a237",
+            "a238",
+            "a239",
+            "a240",
+            "a241",
+            "a242",
+            "a243",
+            "a244",
+            "a245",
+            "a246",
+            "a247",
+            "a248",
+            "a249",
+            "a250",
+            "a251",
+            "a252",
+            "a253",
+            "a254",
+            "a255",
+            "a256",
+            "a257",
+            "a258",
+            "a259",
+            "a260",
+            "a261",
+            "a262",
+            "a263",
+            "a264",
+            "a265",
+            "a266",
+            "a267",
+            "a268",
+            "a269",
+            "a270",
+            "a271",
+            "a272",
+            "a273",
+            "a274",
+            "a275",
+            "a276",
+            "a277",
+            "a278",
+            "a279",
+            "a280",
+            "a281",
+            "a282",
+            "a283",
+            "a284",
+            "a285",
+            "a286",
+            "a287",
+            "a288",
+            "a289",
+            "a290",
+            "a291",
+            "a292",
+            "a293",
+            "a294",
+            "a295",
+            "a296",
+            "a297",
+            "a298",
+            "a299"
+        }
+    .end annotation
+.end method
+
+.method public abstract nameWithOpenSquareBracket(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = { 0x1 }
+        names = { "a[a" }
+    .end annotation
+.end method
+
+.method public abstract nameWithPeriod(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = { 0x1 }
+        names = { "a.a" }
+    .end annotation
+.end method
+
+.method public abstract nameWithSemicolon(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = { 0x1 }
+        names = { "a;a" }
+    .end annotation
+.end method
+
+.method public abstract nameWithSlash(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = { 0x1 }
+        names = { "a/a" }
+    .end annotation
+.end method
+
+.method public abstract nullName(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            null
+        }
+    .end annotation
+.end method
+
+.method public abstract tooFewAccessFlags(Ljava/lang/String;Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+.end method
+
+.method public abstract tooFewBoth(Ljava/lang/String;Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+.end method
+
+.method public abstract tooFewNames(Ljava/lang/String;Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10,
+            0x10
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+.end method
+
+.method public abstract tooManyAccessFlags(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10,
+            0x10
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+.end method
+
+.method public abstract tooManyBoth(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10,
+            0x10
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+.end method
+
+.method public abstract tooManyNames(Ljava/lang/String;)V
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0.smali
new file mode 100644
index 0000000..f872cef
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0.smali
@@ -0,0 +1,64 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class final synthetic Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+# interfaces
+.implements Ljava/util/concurrent/Callable;
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x1010
+    name = "-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0"
+.end annotation
+
+
+# instance fields
+.field private synthetic val$this:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+
+# direct methods
+.method public synthetic constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+    .registers 2
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;->val$this:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    return-void
+.end method
+
+
+# virtual methods
+.method public call()Ljava/lang/Object;
+    .registers 2
+
+    iget-object v0, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;->val$this:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-virtual {v0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->-libcore_java_lang_reflect_parameter_ParameterMetadataTestClasses-mthref-0()Ljava/lang/String;
+
+    move-result-object v0
+
+    return-object v0
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1.smali
new file mode 100644
index 0000000..b46b487
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1.smali
@@ -0,0 +1,108 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+# interfaces
+.implements Ljava/util/concurrent/Callable;
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingMethod;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->getAnonymousClassWith1ParameterConstructor()Ljava/lang/Class;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x0
+    name = null
+.end annotation
+
+.annotation system Ldalvik/annotation/Signature;
+    value = {
+        "Ljava/lang/Object;",
+        "Ljava/util/concurrent/Callable",
+        "<",
+        "Ljava/lang/String;",
+        ">;"
+    }
+.end annotation
+
+
+# instance fields
+.field final synthetic this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+
+# direct methods
+.method constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8010
+        }
+        names = {
+            "this$0"
+        }
+    .end annotation
+
+    .prologue
+    .line 70
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method public bridge synthetic call()Ljava/lang/Object;
+    .registers 2
+    .annotation system Ldalvik/annotation/Throws;
+        value = {
+            Ljava/lang/Exception;
+        }
+    .end annotation
+
+    .prologue
+    .line 72
+    invoke-virtual {p0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;->call()Ljava/lang/String;
+
+    move-result-object v0
+
+    return-object v0
+.end method
+
+.method public call()Ljava/lang/String;
+    .registers 2
+    .annotation system Ldalvik/annotation/Throws;
+        value = {
+            Ljava/lang/Exception;
+        }
+    .end annotation
+
+    .prologue
+    .line 73
+    iget-object v0, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-static {v0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->-wrap0(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)Ljava/lang/String;
+
+    move-result-object v0
+
+    return-object v0
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass.smali
new file mode 100644
index 0000000..c026225
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass.smali
@@ -0,0 +1,61 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingMethod;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->getMethodClassWith1ImplicitParameterConstructor()Ljava/lang/Class;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x0
+    name = "MethodClass"
+.end annotation
+
+
+# instance fields
+.field final synthetic this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+
+# direct methods
+.method constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8010
+        }
+        names = {
+            "this$0"
+        }
+    .end annotation
+
+    .prologue
+    .line 81
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    .line 82
+    invoke-static {p1}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->-wrap0(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)Ljava/lang/String;
+
+    .line 81
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$FinalParameter.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$FinalParameter.smali
new file mode 100644
index 0000000..6d0ff2d
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$FinalParameter.smali
@@ -0,0 +1,69 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$FinalParameter;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "FinalParameter"
+.end annotation
+
+
+# direct methods
+.method constructor <init>(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 26
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method finalParameter(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x10
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 28
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$GenericParameter.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$GenericParameter.smali
new file mode 100644
index 0000000..2e7a6fb
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$GenericParameter.smali
@@ -0,0 +1,91 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$GenericParameter;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "GenericParameter"
+.end annotation
+
+
+# direct methods
+.method constructor <init>(Ljava/util/function/Function;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "(",
+            "Ljava/util/function/Function",
+            "<",
+            "Ljava/lang/String;",
+            "Ljava/lang/Integer;",
+            ">;)V"
+        }
+    .end annotation
+
+    .prologue
+    .line 14
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method genericParameter(Ljava/util/function/Function;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "(",
+            "Ljava/util/function/Function",
+            "<",
+            "Ljava/lang/String;",
+            "Ljava/lang/Integer;",
+            ">;)V"
+        }
+    .end annotation
+
+    .prologue
+    .line 16
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass.smali
new file mode 100644
index 0000000..6ed4514
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass.smali
@@ -0,0 +1,109 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x0
+    name = "InnerClass"
+.end annotation
+
+
+# instance fields
+.field final synthetic this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+
+# direct methods
+.method public constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8010
+        }
+        names = {
+            "this$0"
+        }
+    .end annotation
+
+
+    .prologue
+    .line 32
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+.method public constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;Ljava/lang/String;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8010, 0x0
+        }
+        names = {
+            "this$0", "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 34
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+.method public constructor <init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;Ljava/util/function/Function;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8010, 0x0
+        }
+        names = {
+            "this$0", "p1"
+        }
+    .end annotation
+
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "(",
+            "Ljava/util/function/Function",
+            "<",
+            "Ljava/lang/String;",
+            "Ljava/lang/Integer;",
+            ">;)V"
+        }
+    .end annotation
+
+    .prologue
+    .line 36
+    iput-object p1, p0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass;->this$0:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$MixedVarArgs.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$MixedVarArgs.smali
new file mode 100644
index 0000000..ad404b0
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$MixedVarArgs.smali
@@ -0,0 +1,73 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$MixedVarArgs;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "MixedVarArgs"
+.end annotation
+
+
+# direct methods
+.method varargs constructor <init>([Ljava/lang/Integer;[Ljava/lang/String;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 48
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method varargs both([Ljava/lang/Integer;[Ljava/lang/String;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 50
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonIdenticalParameters.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonIdenticalParameters.smali
new file mode 100644
index 0000000..91be02a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonIdenticalParameters.smali
@@ -0,0 +1,77 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonIdenticalParameters;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "NonIdenticalParameters"
+.end annotation
+
+
+# direct methods
+.method constructor <init>()V
+    .registers 1
+
+    .prologue
+    .line 59
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method method0(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 60
+    return-void
+.end method
+
+.method method1(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 61
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonVarArgs.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonVarArgs.smali
new file mode 100644
index 0000000..37e4aca
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonVarArgs.smali
@@ -0,0 +1,71 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonVarArgs;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "NonVarArgs"
+.end annotation
+
+
+# direct methods
+.method constructor <init>([Ljava/lang/Integer;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 54
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method notVarArgs([Ljava/lang/Integer;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 56
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleParameter.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleParameter.smali
new file mode 100644
index 0000000..cfaff4a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleParameter.smali
@@ -0,0 +1,69 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleParameter;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "SingleParameter"
+.end annotation
+
+
+# direct methods
+.method constructor <init>(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 8
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method oneParameter(Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 10
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleVarArgs.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleVarArgs.smali
new file mode 100644
index 0000000..7f020e7
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleVarArgs.smali
@@ -0,0 +1,69 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleVarArgs;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "SingleVarArgs"
+.end annotation
+
+
+# direct methods
+.method varargs constructor <init>([Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 42
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method varargs varArgs([Ljava/lang/String;)V
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0
+        }
+        names = {
+            "p0"
+        }
+    .end annotation
+
+    .prologue
+    .line 44
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum.smali
new file mode 100644
index 0000000..c564635
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum.smali
@@ -0,0 +1,144 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class final enum Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+.super Ljava/lang/Enum;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x4018
+    name = "TestEnum"
+.end annotation
+
+.annotation system Ldalvik/annotation/Signature;
+    value = {
+        "Ljava/lang/Enum",
+        "<",
+        "Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;",
+        ">;"
+    }
+.end annotation
+
+
+# static fields
+.field private static final synthetic $VALUES:[Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+.field public static final enum ONE:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+.field public static final enum TWO:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+
+# direct methods
+.method static constructor <clinit>()V
+    .registers 4
+
+    .prologue
+    const/4 v3, 0x1
+
+    const/4 v2, 0x0
+
+    .line 39
+    new-instance v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    const-string/jumbo v1, "ONE"
+
+    invoke-direct {v0, v1, v2}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;-><init>(Ljava/lang/String;I)V
+
+    sput-object v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->ONE:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    new-instance v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    const-string/jumbo v1, "TWO"
+
+    invoke-direct {v0, v1, v3}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;-><init>(Ljava/lang/String;I)V
+
+    sput-object v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->TWO:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    const/4 v0, 0x2
+
+    new-array v0, v0, [Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    sget-object v1, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->ONE:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    aput-object v1, v0, v2
+
+    sget-object v1, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->TWO:Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    aput-object v1, v0, v3
+
+    sput-object v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->$VALUES:[Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    return-void
+.end method
+
+.method private constructor <init>(Ljava/lang/String;I)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x1000, 0x1000
+        }
+        names = {
+            "$enum$name", "$enum$ordinal"
+        }
+    .end annotation
+
+    .prologue
+    .line 39
+    invoke-direct {p0, p1, p2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V
+
+    return-void
+.end method
+
+.method public static valueOf(Ljava/lang/String;)Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+    .registers 2
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x8000
+        }
+        names = {
+            "name"
+        }
+    .end annotation
+
+    .prologue
+    .line 39
+    const-class v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    invoke-static {v0, p0}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
+
+    move-result-object v0
+
+    check-cast v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    return-object v0
+.end method
+
+.method public static values()[Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+    .registers 1
+
+    .prologue
+    .line 39
+    sget-object v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;->$VALUES:[Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;
+
+    return-object v0
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TwoParameters.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TwoParameters.smali
new file mode 100644
index 0000000..ce4f299
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TwoParameters.smali
@@ -0,0 +1,73 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TwoParameters;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x8
+    name = "TwoParameters"
+.end annotation
+
+
+# direct methods
+.method constructor <init>(Ljava/lang/String;Ljava/lang/Integer;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 20
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+
+# virtual methods
+.method twoParameters(Ljava/lang/String;Ljava/lang/Integer;)V
+    .registers 3
+    .annotation system Ldalvik/annotation/MethodParameters;
+        accessFlags = {
+            0x0,
+            0x0
+        }
+        names = {
+            "p0",
+            "p1"
+        }
+    .end annotation
+
+    .prologue
+    .line 22
+    return-void
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses.smali b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses.smali
new file mode 100644
index 0000000..f7de5b8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses.smali
@@ -0,0 +1,148 @@
+#
+# 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.
+
+# Originally generated using baksmali and edited. See README.txt in this directory.
+
+.class public Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;
+.super Ljava/lang/Object;
+.source "ParameterMetadataTestClasses.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/MemberClasses;
+    value = {
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$FinalParameter;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$GenericParameter;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$InnerClass;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$MixedVarArgs;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonIdenticalParameters;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$NonVarArgs;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleParameter;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$SingleVarArgs;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TestEnum;,
+        Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$TwoParameters;
+    }
+.end annotation
+
+
+# direct methods
+.method static synthetic -wrap0(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)Ljava/lang/String;
+    .registers 2
+
+    invoke-direct {p0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->outerClassMethod()Ljava/lang/String;
+
+    move-result-object v0
+
+    return-object v0
+.end method
+
+.method public constructor <init>()V
+    .registers 1
+
+    .prologue
+    .line 6
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+.method private outerClassMethod()Ljava/lang/String;
+    .registers 2
+
+    .prologue
+    .line 191
+    const-string/jumbo v0, "Howdy"
+
+    return-object v0
+.end method
+
+
+# virtual methods
+.method synthetic -libcore_java_lang_reflect_parameter_ParameterMetadataTestClasses-mthref-0()Ljava/lang/String;
+    .registers 2
+
+    .prologue
+    .line 89
+    invoke-direct {p0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;->outerClassMethod()Ljava/lang/String;
+
+    move-result-object v0
+
+    return-object v0
+.end method
+
+.method public getAnonymousClassWith1ParameterConstructor()Ljava/lang/Class;
+    .registers 2
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "()",
+            "Ljava/lang/Class",
+            "<*>;"
+        }
+    .end annotation
+
+    .prologue
+    .line 70
+    new-instance v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;
+
+    invoke-direct {v0, p0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1;-><init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+
+    .line 76
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v0
+
+    return-object v0
+.end method
+
+.method public getLambdaClassWith1ParameterConstructor()Ljava/lang/Class;
+    .registers 2
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "()",
+            "Ljava/lang/Class",
+            "<*>;"
+        }
+    .end annotation
+
+    .prologue
+    .line 89
+    new-instance v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;
+
+    invoke-direct {v0, p0}, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$-java_lang_Class_getLambdaClassWith1ParameterConstructor__LambdaImpl0;-><init>(Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses;)V
+
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v0
+
+    return-object v0
+.end method
+
+.method public getMethodClassWith1ImplicitParameterConstructor()Ljava/lang/Class;
+    .registers 2
+    .annotation system Ldalvik/annotation/Signature;
+        value = {
+            "()",
+            "Ljava/lang/Class",
+            "<*>;"
+        }
+    .end annotation
+
+    .prologue
+    .line 85
+    const-class v0, Llibcore/java/lang/reflect/parameter/ParameterMetadataTestClasses$1MethodClass;
+
+    return-object v0
+.end method
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
new file mode 100644
index 0000000..6d5a6c2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
@@ -0,0 +1,212 @@
+This directory contains the .smali files used to generate .dex files used
+by libcore.java.lang.reflect.ParameterTest.
+
+The use of .smali files allows construction of valid and invalid
+system annotations for parameter metadata that are then tested in
+ParameterTest.
+
+Regenerate the .dex files with:
+
+make smali
+smali libcore/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetdataTestClasses*.smali \
+    -o libcore/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex
+
+For reference, the valid smali code should be (roughly) the equivalent of the
+following Java code when compiled using a compiler with .dex parameter metadata support
+enabled.
+
+The smali was generated using Jack to create a .dex file.
+
+For example:
+
+jack -D jack.java.source.version=1.8 \
+  --output-dex . \
+  -cp ${ANDROID_BUILD_TOP}/out/target/common/obj/JAVA_LIBRARIES/core-all_intermediates/classes.jack \
+  src/test/java/libcore/java/lang/reflect/parameter/ParameterMetadataTestClasses.java
+
+It was then decompiled using baksmali, hand modified, and a .dex generated from it using smali.
+
+ParameterMetadataTestClasses* contain valid metadata.
+MetadataVariations* contain variations on valid and invalid metdata that would be difficult to
+generate from a .java file (i.e. invalid cases, null/empty parameter names).
+
+---------------------
+
+package libcore.java.lang.reflect.parameter;
+
+import java.util.concurrent.Callable;
+import java.util.function.Function;
+
+public class ParameterMetadataTestClasses {
+    static class SingleParameter {
+        SingleParameter(String p0) {}
+
+        void oneParameter(String p0) {}
+    }
+
+    static class GenericParameter {
+        GenericParameter(Function<String, Integer> p0) {}
+
+        void genericParameter(Function<String, Integer> p0) {}
+    }
+
+    static class TwoParameters {
+        TwoParameters(String p0, Integer p1) {}
+
+        void twoParameters(String p0, Integer p1) {}
+    }
+
+    static class FinalParameter {
+        FinalParameter(final String p0) {}
+
+        void finalParameter(final String p0) {}
+    }
+
+    class InnerClass {
+        public InnerClass() {}
+
+        public InnerClass(String p1) {}
+
+        public InnerClass(Function<String, Integer> p1) {}
+    }
+
+    enum TestEnum { ONE, TWO }
+
+    static class SingleVarArgs {
+        SingleVarArgs(String... p0) {}
+
+        void varArgs(String... p0) {}
+    }
+
+    static class MixedVarArgs {
+        MixedVarArgs(Integer[] p0, String... p1) {}
+
+        void both(Integer[] p0, String... p1) {}
+    }
+
+    static class NonVarArgs {
+        NonVarArgs(Integer[] p0) {}
+
+        void notVarArgs(Integer[] p0) {}
+    }
+
+    static class NonIdenticalParameters {
+        void method0(String p1) {}
+
+        void method1(String p1) {}
+    }
+
+    private String outerClassMethod() {
+        return "Howdy";
+    }
+
+    public Class<?> getAnonymousClassWith1ParameterConstructor() {
+        // Deliberately not implemented with a lambda. Do not refactor.
+        Callable<String> anonymousClassObject = new Callable<String>() {
+            @Override
+            public String call() throws Exception {
+                return ParameterMetadataTestClasses.this.outerClassMethod();
+            }
+        };
+        return anonymousClassObject.getClass();
+    }
+
+    public Class<?> getMethodClassWith1ImplicitParameterConstructor() {
+        class MethodClass {
+            MethodClass() {
+                ParameterMetadataTestClasses.this.outerClassMethod();
+            }
+        }
+        return MethodClass.class;
+    }
+
+    public Class<?> getLambdaClassWith1ParameterConstructor() {
+        return ((Callable<String>) ParameterMetadataTestClasses.this::outerClassMethod).getClass();
+    }
+}
+
+----------------
+
+package libcore.java.lang.reflect.parameter;
+
+public interface MetadataVariations {
+
+    void emptyMethodParametersAnnotation();
+    void tooManyAccessFlags(final String p0);
+    void tooFewAccessFlags(final String p0, final String p1);
+    void tooManyNames(final String p0);
+    void tooFewNames(final String p0, final String p1);
+    void tooManyBoth(final String p0);
+    void tooFewBoth(final String p0, final String p1);
+    void nullName(final String p0);
+    void emptyName(final String p0);
+    void nameWithSemicolon(final String p0);
+    void nameWithSlash(final String p0);
+    void nameWithPeriod(final String p0);
+    void nameWithOpenSquareBracket(final String p0);
+    void badAccessModifier(final String p0);
+    void badlyFormedAnnotation(final String p0);
+
+    void manyParameters(
+            final int a000, final int a001, final int a002, final int a003, final int a004,
+            final int a005, final int a006, final int a007, final int a008, final int a009,
+            final int a010, final int a011, final int a012, final int a013, final int a014,
+            final int a015, final int a016, final int a017, final int a018, final int a019,
+            final int a020, final int a021, final int a022, final int a023, final int a024,
+            final int a025, final int a026, final int a027, final int a028, final int a029,
+            final int a030, final int a031, final int a032, final int a033, final int a034,
+            final int a035, final int a036, final int a037, final int a038, final int a039,
+            final int a040, final int a041, final int a042, final int a043, final int a044,
+            final int a045, final int a046, final int a047, final int a048, final int a049,
+            final int a050, final int a051, final int a052, final int a053, final int a054,
+            final int a055, final int a056, final int a057, final int a058, final int a059,
+            final int a060, final int a061, final int a062, final int a063, final int a064,
+            final int a065, final int a066, final int a067, final int a068, final int a069,
+            final int a070, final int a071, final int a072, final int a073, final int a074,
+            final int a075, final int a076, final int a077, final int a078, final int a079,
+            final int a080, final int a081, final int a082, final int a083, final int a084,
+            final int a085, final int a086, final int a087, final int a088, final int a089,
+            final int a090, final int a091, final int a092, final int a093, final int a094,
+            final int a095, final int a096, final int a097, final int a098, final int a099,
+            final int a100, final int a101, final int a102, final int a103, final int a104,
+            final int a105, final int a106, final int a107, final int a108, final int a109,
+            final int a110, final int a111, final int a112, final int a113, final int a114,
+            final int a115, final int a116, final int a117, final int a118, final int a119,
+            final int a120, final int a121, final int a122, final int a123, final int a124,
+            final int a125, final int a126, final int a127, final int a128, final int a129,
+            final int a130, final int a131, final int a132, final int a133, final int a134,
+            final int a135, final int a136, final int a137, final int a138, final int a139,
+            final int a140, final int a141, final int a142, final int a143, final int a144,
+            final int a145, final int a146, final int a147, final int a148, final int a149,
+            final int a150, final int a151, final int a152, final int a153, final int a154,
+            final int a155, final int a156, final int a157, final int a158, final int a159,
+            final int a160, final int a161, final int a162, final int a163, final int a164,
+            final int a165, final int a166, final int a167, final int a168, final int a169,
+            final int a170, final int a171, final int a172, final int a173, final int a174,
+            final int a175, final int a176, final int a177, final int a178, final int a179,
+            final int a180, final int a181, final int a182, final int a183, final int a184,
+            final int a185, final int a186, final int a187, final int a188, final int a189,
+            final int a190, final int a191, final int a192, final int a193, final int a194,
+            final int a195, final int a196, final int a197, final int a198, final int a199,
+            final int a200, final int a201, final int a202, final int a203, final int a204,
+            final int a205, final int a206, final int a207, final int a208, final int a209,
+            final int a210, final int a211, final int a212, final int a213, final int a214,
+            final int a215, final int a216, final int a217, final int a218, final int a219,
+            final int a220, final int a221, final int a222, final int a223, final int a224,
+            final int a225, final int a226, final int a227, final int a228, final int a229,
+            final int a230, final int a231, final int a232, final int a233, final int a234,
+            final int a235, final int a236, final int a237, final int a238, final int a239,
+            final int a240, final int a241, final int a242, final int a243, final int a244,
+            final int a245, final int a246, final int a247, final int a248, final int a249,
+            final int a250, final int a251, final int a252, final int a253, final int a254,
+            final int a255, final int a256, final int a257, final int a258, final int a259,
+            final int a260, final int a261, final int a262, final int a263, final int a264,
+            final int a265, final int a266, final int a267, final int a268, final int a269,
+            final int a270, final int a271, final int a272, final int a273, final int a274,
+            final int a275, final int a276, final int a277, final int a278, final int a279,
+            final int a280, final int a281, final int a282, final int a283, final int a284,
+            final int a285, final int a286, final int a287, final int a288, final int a289,
+            final int a290, final int a291, final int a292, final int a293, final int a294,
+            final int a295, final int a296, final int a297, final int a298, final int a299
+    );
+}
diff --git a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
index 85526cc..3277385 100644
--- a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
@@ -21,8 +21,10 @@
 import java.lang.reflect.Field;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.SocketAddress;
 import java.net.SocketException;
 
 public class DatagramSocketTest extends TestCase {
@@ -64,37 +66,90 @@
     final int port = 9999;
 
     try (DatagramSocket s = new DatagramSocket()) {
-      s.connect(InetAddress.getLocalHost(), port);
+      forceConnectToThrowSocketException(s);
 
-      // connect may set pendingConnectException on internal failure; since we have no reliable way
-      // to make connect fail, set pendingConnectException through reflection.
-      Field pendingConnectException = s.getClass().getDeclaredField("pendingConnectException");
-      pendingConnectException.setAccessible(true);
-      pendingConnectException.set(s, new SocketException());
+      s.connect(InetAddress.getLocalHost(), port);
 
       byte[] data = new byte[100];
       DatagramPacket p = new DatagramPacket(data, data.length);
 
+      // Confirm send() throws the pendingConnectException.
       try {
         s.send(p);
         fail();
       } catch (SocketException expected) {
+        assertTrue(expected.getMessage().contains("Pending connect failure"));
       }
 
+      // Confirm receive() throws the pendingConnectException.
       try {
         s.receive(p);
         fail();
       } catch (SocketException expected) {
+        assertTrue(expected.getMessage().contains("Pending connect failure"));
       }
+
+      // Confirm that disconnect() doesn't throw a runtime exception.
+      s.disconnect();
     }
   }
 
   public void test_setTrafficClass() throws Exception {
-    DatagramSocket s = new DatagramSocket();
-
-    for (int i = 0; i <= 255; ++i) {
-      s.setTrafficClass(i);
-      assertEquals(i, s.getTrafficClass());
+    try (DatagramSocket s = new DatagramSocket()) {
+      for (int i = 0; i <= 255; ++i) {
+        s.setTrafficClass(i);
+        assertEquals(i, s.getTrafficClass());
+      }
     }
   }
+
+  // DatagramSocket should "become connected" even when impl.connect() fails and throws an
+  // exception.
+  public void test_b31218085() throws Exception {
+    final int port = 9999;
+
+    try (DatagramSocket s = new DatagramSocket()) {
+      forceConnectToThrowSocketException(s);
+
+      s.connect(InetAddress.getLocalHost(), port);
+      assertTrue(s.isConnected());
+
+      // Confirm that disconnect() doesn't throw a runtime exception.
+      s.disconnect();
+    }
+  }
+
+  public void testForceConnectToThrowSocketException() throws Exception {
+    // Unlike connect(InetAddress, int), connect(SocketAddress) can (and should) throw an
+    // exception after a call to forceConnectToThrowSocketException(). The
+    // forceConnectToThrowSocketException() method is used in various tests for
+    // connect(InetAddress, int) and this test exists to confirm it stays working.
+
+    SocketAddress validAddress = new InetSocketAddress(InetAddress.getLocalHost(), 9999);
+
+    try (DatagramSocket s1 = new DatagramSocket()) {
+      s1.connect(validAddress);
+      s1.disconnect();
+    }
+
+    try (DatagramSocket s2 = new DatagramSocket()) {
+      forceConnectToThrowSocketException(s2);
+      try {
+        s2.connect(validAddress);
+      } catch (SocketException expected) {
+      }
+      s2.disconnect();
+    }
+  }
+
+  private static void forceConnectToThrowSocketException(DatagramSocket s) throws Exception {
+    // Set fd of DatagramSocketImpl to null, forcing impl.connect() to throw a SocketException
+    // (Socket closed).
+    Field f = DatagramSocket.class.getDeclaredField("impl");
+    f.setAccessible(true);
+    DatagramSocketImpl impl = (DatagramSocketImpl) f.get(s);
+    f = DatagramSocketImpl.class.getDeclaredField("fd");
+    f.setAccessible(true);
+    f.set(impl, null);
+  }
 }
diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java
index f273f8e..1952286 100644
--- a/luni/src/test/java/libcore/java/net/SocketTest.java
+++ b/luni/src/test/java/libcore/java/net/SocketTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.net;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -43,7 +44,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
-import java.io.FileDescriptor;
 
 
 public class SocketTest extends junit.framework.TestCase {
@@ -379,33 +379,43 @@
 
     public void testCloseDuringConnect() throws Exception {
         final CountDownLatch signal = new CountDownLatch(1);
-
         final Socket s = new Socket();
-        new Thread() {
-            @Override
-            public void run() {
-                try {
-                    // This address is reserved for documentation: should never be reachable.
-                    InetSocketAddress unreachableIp = new InetSocketAddress("192.0.2.0", 80);
-                    // This should never return.
-                    s.connect(unreachableIp, 0 /* infinite */);
-                    fail("Connect returned unexpectedly for: " + unreachableIp);
-                } catch (SocketException expected) {
-                    assertTrue(expected.getMessage().contains("Socket closed"));
-                    signal.countDown();
-                } catch (IOException e) {
-                    fail("Unexpected exception: " + e);
-                }
-            }
-        }.start();
 
-        // Wait for the connect() thread to run and start connect()
+        // Executes a connect() that should block.
+        Callable<String> connectWorker = () -> {
+            try {
+                // This address is reserved for documentation: should never be reachable.
+                InetSocketAddress unreachableIp = new InetSocketAddress("192.0.2.0", 80);
+                // This should never return.
+                s.connect(unreachableIp, 0 /* infinite */);
+                return "Connect returned unexpectedly for: " + unreachableIp;
+            } catch (SocketException expected) {
+                signal.countDown();
+                return expected.getMessage().contains("Socket closed")
+                        ? null
+                        : "Unexpected SocketException message: " + expected.getMessage();
+            } catch (IOException e) {
+                return "Unexpected exception: " + e;
+            }
+        };
+        Future<String> connectResult =
+                Executors.newSingleThreadScheduledExecutor().submit(connectWorker);
+
+        // Wait sufficient time for the connectWorker thread to run and start connect().
         Thread.sleep(2000);
 
+        // Close the socket that connectWorker should currently be blocked in connect().
         s.close();
 
+        // connectWorker should have been unblocked so await() should return true.
         boolean connectUnblocked = signal.await(2000, TimeUnit.MILLISECONDS);
-        assertTrue(connectUnblocked);
+
+        // connectWorker should have returned null if everything went as expected.
+        String workerFailure = connectResult.get(2000, TimeUnit.MILLISECONDS);
+
+        assertTrue("connectUnblocked=[" + connectUnblocked
+                + "], workerFailure=[" + workerFailure + "]",
+                connectUnblocked && workerFailure == null);
     }
 
     // http://b/29092095
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index d1d26a8..3f750e4 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -2723,7 +2723,7 @@
     public void testSslFallback_allSupportedProtocols() throws Exception {
         TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
-        String[] allSupportedProtocols = { "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3" };
+        String[] allSupportedProtocols = { "TLSv1.2", "TLSv1.1", "TLSv1" };
         SSLSocketFactory serverSocketFactory =
                 new LimitedProtocolsSocketFactory(
                         testSSLContext.serverContext.getSocketFactory(),
@@ -2731,7 +2731,6 @@
         server.useHttps(serverSocketFactory, false);
         server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
         server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
-        server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
         server.enqueue(new MockResponse().setBody("This required fallbacks"));
         server.play();
 
@@ -2749,28 +2748,24 @@
         // Confirm the server accepted a single connection.
         RecordedRequest retry = server.takeRequest();
         assertEquals(0, retry.getSequenceNumber());
-        assertEquals("SSLv3", retry.getSslProtocol());
+        assertEquals("TLSv1", retry.getSslProtocol());
 
         // Confirm the client fallback looks ok.
         List<SSLSocket> createdSockets = clientSocketFactory.getCreatedSockets();
-        assertEquals(4, createdSockets.size());
+        assertEquals(3, createdSockets.size());
         TlsFallbackDisabledScsvSSLSocket clientSocket1 =
                 (TlsFallbackDisabledScsvSSLSocket) createdSockets.get(0);
         assertSslSocket(clientSocket1,
-                false /* expectedWasFallbackScsvSet */, "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3");
+                false /* expectedWasFallbackScsvSet */, "TLSv1.2", "TLSv1.1", "TLSv1");
 
         TlsFallbackDisabledScsvSSLSocket clientSocket2 =
                 (TlsFallbackDisabledScsvSSLSocket) createdSockets.get(1);
         assertSslSocket(clientSocket2,
-                true /* expectedWasFallbackScsvSet */, "TLSv1.1", "TLSv1", "SSLv3");
+                true /* expectedWasFallbackScsvSet */, "TLSv1.1", "TLSv1");
 
         TlsFallbackDisabledScsvSSLSocket clientSocket3 =
                 (TlsFallbackDisabledScsvSSLSocket) createdSockets.get(2);
-        assertSslSocket(clientSocket3, true /* expectedWasFallbackScsvSet */, "TLSv1", "SSLv3");
-
-        TlsFallbackDisabledScsvSSLSocket clientSocket4 =
-                (TlsFallbackDisabledScsvSSLSocket) createdSockets.get(3);
-        assertSslSocket(clientSocket4, true /* expectedWasFallbackScsvSet */, "SSLv3");
+        assertSslSocket(clientSocket3, true /* expectedWasFallbackScsvSet */, "TLSv1");
     }
 
     public void testSslFallback_defaultProtocols() throws Exception {
diff --git a/luni/src/test/java/libcore/java/net/URLStreamHandlerFactoryTest.java b/luni/src/test/java/libcore/java/net/URLStreamHandlerFactoryTest.java
index de50e16..21c2971 100644
--- a/luni/src/test/java/libcore/java/net/URLStreamHandlerFactoryTest.java
+++ b/luni/src/test/java/libcore/java/net/URLStreamHandlerFactoryTest.java
@@ -21,6 +21,8 @@
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.net.URLStreamHandlerFactory;
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 import libcore.java.net.customstreamhandler.http.Handler;
 
@@ -61,13 +63,23 @@
         try {
             URL.setURLStreamHandlerFactory(shf);
             fail();
+        } catch (AssertionFailedError error) {
+            // Rethrow the error thrown by fail to avoid it being caught by the more general catch
+            // statement below.
+            throw error;
         } catch (Error expected) {
+            // The setURLStreamHandlerFactory is behaving correctly by throwing an Error.
         }
 
         try {
             URL.setURLStreamHandlerFactory(null);
             fail();
+        } catch (AssertionFailedError error) {
+            // Rethrow the error thrown by fail to avoid it being caught by the more general catch
+            // statement below.
+            throw error;
         } catch (Error expected) {
+            // The setURLStreamHandlerFactory is behaving correctly by throwing an Error.
         }
     }
 
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index 789e3e9..566c314 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -735,6 +735,11 @@
             }
 
             @Override
+            public void onUnbufferedIO() {
+                fail("Blockguard.Policy.onUnbufferedIO");
+            }
+
+            @Override
             public int getPolicyMask() {
                 return 0;
             }
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
index 0951302..52146ee 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
@@ -490,6 +490,7 @@
         assertTrue(key.isValid());
         assertSame(networkInterface, key.networkInterface());
         assertNull(key.sourceAddress());
+        dc.close();
     }
 
     public void test_dropAnySource_twice_IPv4() throws Exception {
diff --git a/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java b/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java
index 99799bf..6f74dd8 100644
--- a/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java
+++ b/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java
@@ -30,7 +30,7 @@
      * b/31360928
      */
     @Test
-    public void test() {
+    public void testGetException() {
         Exception e = new Exception();
         PrivilegedActionException pae = new PrivilegedActionException(e);
 
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 35712e0..8d1af37 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -238,32 +238,28 @@
 
         @Override
         protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
-            throw new UnsupportedOperationException();
         }
 
         @Override
         protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
-            throw new UnsupportedOperationException();
         }
 
         @Override
         protected void engineUpdate(byte b) throws SignatureException {
-            throw new UnsupportedOperationException();
         }
 
         @Override
         protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
-            throw new UnsupportedOperationException();
         }
 
         @Override
         protected byte[] engineSign() throws SignatureException {
-            throw new UnsupportedOperationException();
+            return new byte[10];
         }
 
         @Override
         protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
-            throw new UnsupportedOperationException();
+            return true;
         }
 
         @Override
@@ -277,6 +273,153 @@
         }
     }
 
+    public void testSignature_signArray_nullArray_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.sign(null /* outbuf */, 1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_signArray_negativeOffset_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.sign(new byte[4], -1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_signArray_negativeLength_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.sign(new byte[4], 1 /* offset */ , -1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_signArray_invalidLengths_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            // Start at offset 3 with length 2, thus attempting to overread from an array of size 4.
+            s.sign(new byte[4], 3 /* offset */ , 2 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    private static PublicKey createPublicKey() throws Exception {
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(PK_BYTES);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        return keyFactory.generatePublic(keySpec);
+    }
+
+    public void testSignature_verifyArray_nullArray_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.verify(null /* outbuf */, 1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_verifyArray_negativeOffset_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.verify(new byte[4], -1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_verifyArray_negativeLength_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.verify(new byte[4], 1 /* offset */ , -1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_verifyArray_invalidLengths_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            // Start at offset 3 with length 2, thus attempting to overread from an array of size 4.
+            s.verify(new byte[4], 3 /* offset */ , 2 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_verifyArray_correctParameters_ok() throws Exception {
+        Signature s = new MySignature("FOO");
+        s.initVerify(createPublicKey());
+        // Start at offset 3 with length 2, thus attempting to overread from an array of size 4.
+        s.verify(new byte[4], 1 /* offset */, 2 /* length */);
+    }
+
+    public void testSignature_updateArray_nullArray_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.update(null /* outbuf */, 1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_updateArray_negativeOffset_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.update(new byte[4], -1 /* offset */, 1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_updateArray_negativeLength_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            s.update(new byte[4], 1 /* offset */ , -1 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_updateArray_invalidLengths_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.initVerify(createPublicKey());
+            // Start at offset 3 with length 2, thus attempting to overread from an array of size 4.
+            s.update(new byte[4], 3 /* offset */ , 2 /* length */);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testSignature_updateArray_wrongState_throws() throws Exception {
+        try {
+            Signature s = new MySignature("FOO");
+            s.update(new byte[4], 0 /* offset */ , 1 /* length */);
+            fail();
+        } catch (SignatureException expected) {
+        }
+    }
+
+    public void testSignature_updateArray_correctStateAndParameters_ok() throws Exception {
+        Signature s = new MySignature("FOO");
+        s.initVerify(createPublicKey());
+        s.update(new byte[4], 0 /* offset */ , 1 /* length */);
+    }
+
     public void testSignature_getProvider_Subclass() throws Exception {
         Provider mockProviderNonSpi = new MockProvider("MockProviderNonSpi") {
             public void setup() {
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/text/OldBidiTest.java b/luni/src/test/java/libcore/java/text/OldBidiTest.java
index fbf68ea..fe8b6cb 100644
--- a/luni/src/test/java/libcore/java/text/OldBidiTest.java
+++ b/luni/src/test/java/libcore/java/text/OldBidiTest.java
@@ -17,6 +17,7 @@
 
 package libcore.java.text;
 
+import java.text.AttributedCharacterIterator;
 import java.text.Bidi;
 import junit.framework.TestCase;
 
@@ -192,4 +193,16 @@
         }
     }
 
+    // http://b/30652865
+    public void testUnicode9EmojisAreLtrNeutral() {
+        String callMeHand = "\uD83E\uDD19"; // U+1F919 in UTF-16
+        String hebrewAndEmoji = "\u05e9\u05dc" + callMeHand + "\u05d5\u05dd";
+        String latinAndEmoji = "Hel" + callMeHand + "lo";
+        Bidi hebrew = new Bidi(hebrewAndEmoji, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+        assertFalse("Hebrew bidi is mixed: " + hebrew, hebrew.isMixed());
+        assertTrue("Hebrew bidi is not right to left: " + hebrew, hebrew.isRightToLeft());
+        Bidi latin = new Bidi(latinAndEmoji, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+        assertFalse("Latin bidi is mixed: " + latin, latin.isMixed());
+        assertTrue("latin bidi is not left to right: " + latin, latin.isLeftToRight());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index d9656a0..47c2365 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -513,4 +513,23 @@
         assertEquals("torstai", formatDate(fi, "cccc"));
         assertEquals("torstaina", formatDate(fi, "EEEE"));
     }
+
+    public void testDayNumberOfWeek() throws Exception {
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+        Locale en = Locale.ENGLISH;
+        Locale pl = new Locale("pl");
+
+        assertEquals("4", formatDate(en, "u"));
+        assertEquals("04", formatDate(en, "uu"));
+        assertEquals("4", formatDate(pl, "u"));
+        assertEquals("04", formatDate(pl, "uu"));
+
+        assertEquals(Calendar.THURSDAY, parseDate(en, "u", "4").get(Calendar.DAY_OF_WEEK));
+        assertEquals(Calendar.MONDAY, parseDate(en, "uu", "1").get(Calendar.DAY_OF_WEEK));
+    }
+
+    // http://b/20879084
+    public void testFormatUtc() {
+        assertEquals("UTC", formatDate(Locale.ENGLISH, "z", TimeZone.getTimeZone("Etc/UTC")));
+    }
 }
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/CurrencyTest.java b/luni/src/test/java/libcore/java/util/CurrencyTest.java
index 58c958a..91584de 100644
--- a/luni/src/test/java/libcore/java/util/CurrencyTest.java
+++ b/luni/src/test/java/libcore/java/util/CurrencyTest.java
@@ -18,10 +18,14 @@
 
 import java.util.Currency;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.Set;
 
 import libcore.util.SerializationTester;
 
+import static java.util.Locale.Category.DISPLAY;
+import static java.util.Locale.Category.FORMAT;
+
 public class CurrencyTest extends junit.framework.TestCase {
     // Regression test to ensure that Currency.getSymbol(Locale) returns the
     // currency code if ICU doesn't have a localization of the symbol. The
@@ -35,6 +39,30 @@
         assertEquals("AED", Currency.getInstance("AED").getSymbol(Locale.CANADA));
     }
 
+    public void test_getSymbol_locale() {
+        Currency currency = Currency.getInstance("DEM");
+        assertEquals("DEM", currency.getSymbol(Locale.FRANCE));
+        assertEquals("DM", currency.getSymbol(Locale.GERMANY));
+        assertEquals("DEM", currency.getSymbol(Locale.US));
+    }
+
+    /**
+     * Checks that the no-argument version of {@link Currency#getSymbol()} uses the
+     * default DISPLAY locale as opposed to the default locale or the default FORMAT
+     * locale.
+     */
+    public void test_getSymbol_noLocaleArgument() {
+        Currency currency = Currency.getInstance("DEM");
+        Locales locales = getDefaultLocales();
+        try {
+            // Locales(locale, displayLocale, formatLocale)
+            setDefaultLocales(new Locales(Locale.US, Locale.GERMANY, Locale.FRANCE));
+            assertEquals("DM", currency.getSymbol());
+        } finally {
+            setDefaultLocales(locales);
+        }
+    }
+
     // Regression test to ensure that Currency.getInstance(String) throws if
     // given an invalid ISO currency code.
     public void test_getInstance_illegal_currency_code() throws Exception {
@@ -56,11 +84,45 @@
         assertTrue(all.toString(), all.contains(Currency.getInstance("USD")));
     }
 
-    public void test_getDisplayName() throws Exception {
-        assertEquals("Swiss Franc", Currency.getInstance("CHF").getDisplayName(Locale.US));
-        assertEquals("Schweizer Franken", Currency.getInstance("CHF").getDisplayName(new Locale("de", "CH")));
-        assertEquals("franc suisse", Currency.getInstance("CHF").getDisplayName(new Locale("fr", "CH")));
-        assertEquals("franco svizzero", Currency.getInstance("CHF").getDisplayName(new Locale("it", "CH")));
+    public void test_getDisplayName_locale_chf() throws Exception {
+        Currency currency = Currency.getInstance("CHF");
+        assertEquals("Swiss Franc", currency.getDisplayName(Locale.US));
+        assertEquals("Schweizer Franken", currency.getDisplayName(new Locale("de", "CH")));
+        assertEquals("franc suisse", currency.getDisplayName(new Locale("fr", "CH")));
+        assertEquals("franco svizzero", currency.getDisplayName(new Locale("it", "CH")));
+    }
+
+    public void test_getDisplayName_locale_dem() throws Exception {
+        Currency currency = Currency.getInstance("DEM");
+        assertEquals("Deutsche Mark", currency.getDisplayName(Locale.GERMANY));
+        assertEquals("German Mark", currency.getDisplayName(Locale.US));
+        assertEquals("mark allemand", currency.getDisplayName(Locale.FRANCE));
+    }
+
+    public void test_getDisplayName_null() {
+        Currency currency = Currency.getInstance("CHF");
+        try {
+            currency.getDisplayName(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * Checks that the no-argument version of {@link Currency#getDisplayName()} uses
+     * the default DISPLAY locale, as opposed to the default locale or the default
+     * FORMAT locale.
+     */
+    public void test_getDisplayName_noLocaleArgument() {
+        Currency currency = Currency.getInstance("DEM");
+        Locales locales = getDefaultLocales();
+        try {
+            // Locales(uncategorizedLocale, displayLocale, formatLocale)
+            setDefaultLocales(new Locales(Locale.US, Locale.GERMANY, Locale.FRANCE));
+            assertEquals("Deutsche Mark", currency.getDisplayName());
+        } finally {
+            setDefaultLocales(locales);
+        }
     }
 
     public void test_getDefaultFractionDigits() throws Exception {
@@ -108,4 +170,54 @@
         assertEquals(999, Currency.getInstance("XXX").getNumericCode());
         assertEquals(0, Currency.getInstance("XFU").getNumericCode());
     }
+
+    static Locales getDefaultLocales() {
+        return new Locales(
+                Locale.getDefault(), Locale.getDefault(DISPLAY), Locale.getDefault(FORMAT));
+    }
+
+    static void setDefaultLocales(Locales locales) {
+        // The lines below must set the Locales in this order because setDefault(Locale)
+        // overwrites the other ones.
+        Locale.setDefault(locales.uncategorizedLocale);
+        Locale.setDefault(DISPLAY, locales.displayLocale);
+        Locale.setDefault(FORMAT, locales.formatLocale);
+
+        assertEquals(locales, getDefaultLocales()); // sanity check
+    }
+
+    static class Locales {
+        final Locale uncategorizedLocale;
+        final Locale displayLocale;
+        final Locale formatLocale;
+
+        public Locales(Locale uncategorizedLocale, Locale displayLocale, Locale formatLocale) {
+            this.uncategorizedLocale = uncategorizedLocale;
+            this.displayLocale = displayLocale;
+            this.formatLocale = formatLocale;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Locales)) {
+                return false;
+            }
+            Locales that = (Locales) obj;
+            return uncategorizedLocale.equals(that.uncategorizedLocale)
+                    && displayLocale.equals(that.displayLocale)
+                    && formatLocale.equals(that.formatLocale);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(uncategorizedLocale, displayLocale, formatLocale);
+        }
+
+        @Override
+        public String toString() {
+            return "Locales[displayLocale=" + displayLocale + ", locale=" + uncategorizedLocale +
+                    ", formatLocale=" + formatLocale + ']';
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/InvalidPropertiesFormatExceptionTest.java b/luni/src/test/java/libcore/java/util/InvalidPropertiesFormatExceptionTest.java
new file mode 100644
index 0000000..694c069
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/InvalidPropertiesFormatExceptionTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package libcore.java.util;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.InvalidPropertiesFormatException;
+import libcore.util.SerializationTester;
+
+public class InvalidPropertiesFormatExceptionTest extends TestCase {
+
+    public void testConstructorArgs() {
+        InvalidPropertiesFormatException e = new InvalidPropertiesFormatException("testing");
+        assertEquals("testing", e.getMessage());
+        assertNull(e.getCause());
+
+        InvalidPropertiesFormatException e2 = new InvalidPropertiesFormatException(e);
+        assertSame(e, e2.getCause());
+        assertEquals(e.toString(), e2.getMessage());
+    }
+
+    public void testDeserialize_notSupported() throws Exception {
+        // Result of
+        // SerializationTester.serializeHex(new InvalidPropertiesFormatException("testing"))
+        // using a InvalidPropertiesFormatException class that had its
+        // writeObject() method commented out.
+        String hex = "aced00057372002a6a6176612e7574696c2e496e76616c696450726f"
+                + "70657274696573466f726d6174457863657074696f6e6bbbea5ee5f9cb5"
+                + "b020000787200136a6176612e696f2e494f457863657074696f6e6c8073"
+                + "646525f0ab020000787200136a6176612e6c616e672e457863657074696"
+                + "f6ed0fd1f3e1a3b1cc4020000787200136a6176612e6c616e672e546872"
+                + "6f7761626c65d5c635273977b8cb0300044c000563617573657400154c6"
+                + "a6176612f6c616e672f5468726f7761626c653b4c000d64657461696c4d"
+                + "6573736167657400124c6a6176612f6c616e672f537472696e673b5b000"
+                + "a737461636b547261636574001e5b4c6a6176612f6c616e672f53746163"
+                + "6b5472616365456c656d656e743b4c00147375707072657373656445786"
+                + "3657074696f6e737400104c6a6176612f7574696c2f4c6973743b787071"
+                + "007e000874000774657374696e677572001e5b4c6a6176612e6c616e672"
+                + "e537461636b5472616365456c656d656e743b02462a3c3cfd2239020000"
+                + "78700000000a7372001b6a6176612e6c616e672e537461636b547261636"
+                + "5456c656d656e746109c59a2636dd8502000449000a6c696e654e756d62"
+                + "65724c000e6465636c6172696e67436c61737371007e00054c000866696"
+                + "c654e616d6571007e00054c000a6d6574686f644e616d6571007e000578"
+                + "70000000457400366c6962636f72652e6a6176612e7574696c2e496e766"
+                + "16c696450726f70657274696573466f726d6174457863657074696f6e54"
+                + "657374740029496e76616c696450726f70657274696573466f726d61744"
+                + "57863657074696f6e546573742e6a61766174001a746573745365726961"
+                + "6c697a655f6e6f74537570706f727465647371007e000cfffffffe74001"
+                + "86a6176612e6c616e672e7265666c6563742e4d6574686f6474000b4d65"
+                + "74686f642e6a617661740006696e766f6b657371007e000c000000c2740"
+                + "028766f6761722e7461726765742e6a756e69742e4a756e69743324566f"
+                + "6761724a556e69745465737474000b4a756e6974332e6a6176617400037"
+                + "2756e7371007e000c0000003b740024766f6761722e7461726765742e6a"
+                + "756e69742e566f6761725465737452756e6e65722431740014566f67617"
+                + "25465737452756e6e65722e6a6176617400086576616c75617465737100"
+                + "7e000c0000004874002b766f6761722e7461726765742e6a756e69742e5"
+                + "4696d656f7574416e6441626f727452756e52756c65243274001b54696d"
+                + "656f7574416e6441626f727452756e52756c652e6a61766174000463616"
+                + "c6c7371007e000c0000004474002b766f6761722e7461726765742e6a75"
+                + "6e69742e54696d656f7574416e6441626f727452756e52756c652432740"
+                + "01b54696d656f7574416e6441626f727452756e52756c652e6a61766174"
+                + "000463616c6c7371007e000c000000ed74001f6a6176612e7574696c2e6"
+                + "36f6e63757272656e742e4675747572655461736b74000f467574757265"
+                + "5461736b2e6a61766174000372756e7371007e000c0000046d7400276a6"
+                + "176612e7574696c2e636f6e63757272656e742e546872656164506f6f6c"
+                + "4578656375746f72740017546872656164506f6f6c4578656375746f722"
+                + "e6a61766174000972756e576f726b65727371007e000c0000025f74002e"
+                + "6a6176612e7574696c2e636f6e63757272656e742e546872656164506f6"
+                + "f6c4578656375746f7224576f726b6572740017546872656164506f6f6c"
+                + "4578656375746f722e6a61766174000372756e7371007e000c000002f87"
+                + "400106a6176612e6c616e672e54687265616474000b5468726561642e6a"
+                + "61766174000372756e7372001f6a6176612e7574696c2e436f6c6c65637"
+                + "4696f6e7324456d7074794c6973747ab817b43ca79ede020000787078";
+        try {
+            Object obj = SerializationTester.deserializeHex(hex);
+            fail("Deserialized to " + obj);
+        } catch (NotSerializableException expected) {
+            // Sanity check that this is the right exception that we expected.
+            assertEquals("Not serializable.", expected.getMessage());
+        }
+    }
+
+    public void testSerialize_notSupported() throws Exception {
+        Serializable notActuallySerializable = new InvalidPropertiesFormatException("testing");
+        try {
+            try (ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream())) {
+                out.writeObject(notActuallySerializable);
+            }
+            fail();
+        } catch (NotSerializableException expected) {
+            // Sanity check that this is the right exception that we expected.
+            assertEquals("Not serializable.", expected.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index f9146b3..1b9e7d3 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -29,6 +29,31 @@
 import java.util.MissingResourceException;
 
 public class LocaleTest extends junit.framework.TestCase {
+
+    public void test_extension_absent() throws Exception {
+        Locale locale = Locale.forLanguageTag("en-US");
+        assertFalse(locale.hasExtensions());
+        assertEquals(locale, locale.stripExtensions());
+    }
+
+    public void test_extension_builder() throws Exception {
+        Locale.Builder b = new Locale.Builder();
+        Locale localeWithoutExtension = b.build();
+        b.setExtension('g', "FO_ba-BR_bg");
+        Locale locale = b.build();
+        assertTrue(locale.hasExtensions());
+        assertFalse(locale.stripExtensions().hasExtensions());
+        assertEquals(localeWithoutExtension, locale.stripExtensions());
+    }
+
+    public void test_extension_languageTag() throws Exception {
+        Locale lA = Locale.forLanguageTag("en-Latn-US-x-foo");
+        Locale lB = Locale.forLanguageTag("en-Latn-US");
+        assertTrue(lA.hasExtensions());
+        assertFalse(lB.hasExtensions());
+        assertEquals(lB, lA.stripExtensions());
+    }
+
     // http://b/2611311; if there's no display language/country/variant, use the raw codes.
     public void test_getDisplayName_invalid() throws Exception {
         Locale invalid = new Locale("AaBbCc", "DdEeFf", "GgHhIi");
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 d86c9f2..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
+++ /dev/null
@@ -1,73 +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.
-   */
-  public void testDetectsUnclosedCloseGuard() throws Exception {
-    ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
-    try {
-      CloseGuard closeGuard = createCloseGuard();
-      closeGuard.open("open");
-    } finally {
-      try {
-        System.logI("Checking for leaks");
-        detector.checkForLeaks();
-        fail();
-      } catch (AssertionError expected) {
-      }
-    }
-  }
-
-  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/libcore/java/util/ServiceLoaderTest.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
index b69a2dd..f17eb22 100644
--- a/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
@@ -44,7 +44,7 @@
       ServiceLoader.load(ServiceLoaderTestInterfaceMissingClass.class).iterator().next();
       fail();
     } catch (ServiceConfigurationError expected) {
-      assertTrue(expected.getCause() instanceof ClassNotFoundException);
+      assertTrue(expected.toString(), expected.getCause() instanceof ClassNotFoundException);
     }
   }
 
@@ -55,7 +55,7 @@
       ServiceLoader.load(ServiceLoaderTestInterfaceWrongType.class).iterator().next();
       fail();
     } catch (ServiceConfigurationError expected) {
-      assertTrue(expected.getCause() instanceof ClassCastException);
+      assertTrue(expected.toString(), expected.getCause() instanceof ClassCastException);
     }
   }
 
diff --git a/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java b/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java
index 785b265..ead0b2e 100644
--- a/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java
+++ b/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java
@@ -33,6 +33,7 @@
 import java.util.logging.Level;
 import java.util.logging.LogManager;
 import java.util.logging.LogRecord;
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 public class OldFileHandlerTest extends TestCase {
@@ -162,11 +163,15 @@
         FileHandler h7 = new FileHandler("%t/log/string%u.log");
         h7.publish(r);
         h7.close();
+        boolean assertionPassed = false;
         try {
-            assertFileContent(TEMPPATH + SEP + "log", "string0.log", h
-                    .getFormatter());
-            fail("should assertion failed");
-        } catch (Error e) {
+            assertFileContent(TEMPPATH + SEP + "log", "string0.log", h.getFormatter());
+            assertionPassed = true;
+        } catch (AssertionFailedError e) {
+            // Assertion failed as expected.
+        }
+        if (assertionPassed) {
+            fail("assertion should have failed");
         }
         File file = new File(TEMPPATH + SEP + "log");
         assertTrue("length list of file is incorrect", file.list().length <= 2);
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 1127559..c5260328 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -36,7 +36,8 @@
 import java.security.Security;
 import java.security.cert.Certificate;
 import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
 import java.security.spec.RSAPublicKeySpec;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -57,8 +58,10 @@
 import javax.crypto.ShortBufferException;
 import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.OAEPParameterSpec;
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.PBEParameterSpec;
+import javax.crypto.spec.PSource;
 import javax.crypto.spec.SecretKeySpec;
 import junit.framework.TestCase;
 import libcore.java.security.StandardNames;
@@ -243,42 +246,65 @@
                 || algorithm.contains("/CFB");
     }
 
+    private static boolean isRandomizedEncryption(String algorithm) {
+        return algorithm.endsWith("/PKCS1PADDING") || algorithm.endsWith("/OAEPPADDING")
+                || algorithm.contains("/OAEPWITH");
+    }
+
     private static Map<String, Key> ENCRYPT_KEYS = new HashMap<String, Key>();
-    private synchronized static Key getEncryptKey(String algorithm) throws Exception {
+
+    /**
+     * Returns the key meant for enciphering for {@code algorithm}.
+     */
+    private synchronized static Key getEncryptKey(String algorithm) {
         Key key = ENCRYPT_KEYS.get(algorithm);
         if (key != null) {
             return key;
         }
-        if (algorithm.startsWith("RSA")) {
-            KeyFactory kf = KeyFactory.getInstance("RSA");
-            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                                                              RSA_2048_privateExponent);
-            key = kf.generatePrivate(keySpec);
-        } else if (isPBE(algorithm)) {
-            SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
-            key = skf.generateSecret(new PBEKeySpec("secret".toCharArray()));
-        } else {
-            KeyGenerator kg = KeyGenerator.getInstance(getBaseAlgorithm(algorithm));
-            key = kg.generateKey();
+        try {
+            if (algorithm.startsWith("RSA")) {
+                KeyFactory kf = KeyFactory.getInstance("RSA");
+                RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                        RSA_2048_publicExponent);
+                key = kf.generatePublic(keySpec);
+            } else if (isPBE(algorithm)) {
+                SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
+                key = skf.generateSecret(new PBEKeySpec("secret".toCharArray()));
+            } else {
+                KeyGenerator kg = KeyGenerator.getInstance(getBaseAlgorithm(algorithm));
+                key = kg.generateKey();
+            }
+        } catch (Exception e) {
+            throw new AssertionError("Error generating keys for test setup", e);
         }
         ENCRYPT_KEYS.put(algorithm, key);
         return key;
     }
 
     private static Map<String, Key> DECRYPT_KEYS = new HashMap<String, Key>();
-    private synchronized static Key getDecryptKey(String algorithm) throws Exception {
+
+    /**
+     * Returns the key meant for deciphering for {@code algorithm}.
+     */
+    private synchronized static Key getDecryptKey(String algorithm) {
         Key key = DECRYPT_KEYS.get(algorithm);
         if (key != null) {
             return key;
         }
-        if (algorithm.startsWith("RSA")) {
-            KeyFactory kf = KeyFactory.getInstance("RSA");
-            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus,
-                                                            RSA_2048_publicExponent);
-            key = kf.generatePublic(keySpec);
-        } else {
-            assertFalse(algorithm, isAsymmetric(algorithm));
-            key = getEncryptKey(algorithm);
+        try {
+            if (algorithm.startsWith("RSA")) {
+                KeyFactory kf = KeyFactory.getInstance("RSA");
+                RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(RSA_2048_modulus,
+                        RSA_2048_publicExponent, RSA_2048_privateExponent, RSA_2048_primeP,
+                        RSA_2048_primeQ, RSA_2048_primeExponentP, RSA_2048_primeExponentQ,
+                        RSA_2048_crtCoefficient);
+                key = kf.generatePrivate(keySpec);
+            } else {
+                assertFalse(algorithm, isAsymmetric(algorithm));
+                key = getEncryptKey(algorithm);
+            }
+        } catch (Exception e) {
+            throw new AssertionError("Error generating keys for test setup", e);
         }
         DECRYPT_KEYS.put(algorithm, key);
         return key;
@@ -1395,7 +1421,7 @@
 
         test_Cipher_init_Decrypt_NullParameters(c, decryptMode, encryptKey, decryptSpec != null);
 
-        c.init(decryptMode, encryptKey, decryptSpec);
+        c.init(decryptMode, getDecryptKey(algorithm), decryptSpec);
         assertEquals(cipherID + " getBlockSize() decryptMode",
                      getExpectedBlockSize(algorithm, decryptMode, providerName), c.getBlockSize());
         assertEquals(cipherID + " getOutputSize(0) decryptMode",
@@ -1484,13 +1510,10 @@
                 c.updateAAD(new byte[24]);
             }
             byte[] cipherText = c.doFinal(getActualPlainText(algorithm));
-            if (isAEAD(algorithm)) {
-                c.updateAAD(new byte[24]);
+            if (!isRandomizedEncryption(algorithm) && !isAEAD(algorithm)) {
+                byte[] cipherText2 = c.doFinal(getActualPlainText(algorithm));
+                assertEquals(cipherID, Arrays.toString(cipherText), Arrays.toString(cipherText2));
             }
-            byte[] cipherText2 = c.doFinal(getActualPlainText(algorithm));
-            assertEquals(cipherID,
-                         Arrays.toString(cipherText),
-                         Arrays.toString(cipherText2));
             c.init(Cipher.DECRYPT_MODE, getDecryptKey(algorithm), decryptSpec);
             if (isAEAD(algorithm)) {
                 c.updateAAD(new byte[24]);
@@ -1602,18 +1625,21 @@
     }
 
     private void testInputPKCS1Padding(String provider) throws Exception {
-        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
+        // Type 1 is for signatures (PrivateKey to "encrypt")
+        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
         try {
-            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
+            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
             fail();
         } catch (BadPaddingException expected) {
         }
+
+        // Type 2 is for enciphering (PublicKey to "encrypt")
+        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
         try {
-            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
+            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
             fail();
         } catch (BadPaddingException expected) {
         }
-        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
     }
 
     private void testInputPKCS1Padding(String provider, byte[] prePaddedPlainText, Key encryptKey, Key decryptKey) throws Exception {
@@ -1645,8 +1671,10 @@
     }
 
     private void testOutputPKCS1Padding(String provider) throws Exception {
-       testOutputPKCS1Padding(provider, (byte) 1, getEncryptKey("RSA"), getDecryptKey("RSA"));
-       testOutputPKCS1Padding(provider, (byte) 2, getDecryptKey("RSA"), getEncryptKey("RSA"));
+        // Type 1 is for signatures (PrivateKey to "encrypt")
+        testOutputPKCS1Padding(provider, (byte) 1, getDecryptKey("RSA"), getEncryptKey("RSA"));
+        // Type 2 is for enciphering (PublicKey to "encrypt")
+        testOutputPKCS1Padding(provider, (byte) 2, getEncryptKey("RSA"), getDecryptKey("RSA"));
     }
 
     private void testOutputPKCS1Padding(String provider, byte expectedBlockType, Key encryptKey, Key decryptKey) throws Exception {
@@ -1918,6 +1946,63 @@
         (byte) 0x39,
     });
 
+    private static final BigInteger RSA_2048_primeExponentP = new BigInteger(1, new byte[] {
+        (byte) 0x51, (byte) 0x82, (byte) 0x8F, (byte) 0x1E, (byte) 0xC6, (byte) 0xFD, (byte) 0x99, (byte) 0x60,
+        (byte) 0x29, (byte) 0x90, (byte) 0x1B, (byte) 0xAF, (byte) 0x1D, (byte) 0x7E, (byte) 0x33, (byte) 0x7B,
+        (byte) 0xA5, (byte) 0xF0, (byte) 0xAF, (byte) 0x27, (byte) 0xE9, (byte) 0x84, (byte) 0xEA, (byte) 0xD8,
+        (byte) 0x95, (byte) 0xAC, (byte) 0xE6, (byte) 0x2B, (byte) 0xD7, (byte) 0xDF, (byte) 0x4E, (byte) 0xE4,
+        (byte) 0x5A, (byte) 0x22, (byte) 0x40, (byte) 0x89, (byte) 0xF2, (byte) 0xCC, (byte) 0x15, (byte) 0x1A,
+        (byte) 0xF3, (byte) 0xCD, (byte) 0x17, (byte) 0x3F, (byte) 0xCE, (byte) 0x04, (byte) 0x74, (byte) 0xBC,
+        (byte) 0xB0, (byte) 0x4F, (byte) 0x38, (byte) 0x6A, (byte) 0x2C, (byte) 0xDC, (byte) 0xC0, (byte) 0xE0,
+        (byte) 0x03, (byte) 0x6B, (byte) 0xA2, (byte) 0x41, (byte) 0x9F, (byte) 0x54, (byte) 0x57, (byte) 0x92,
+        (byte) 0x62, (byte) 0xD4, (byte) 0x71, (byte) 0x00, (byte) 0xBE, (byte) 0x93, (byte) 0x19, (byte) 0x84,
+        (byte) 0xA3, (byte) 0xEF, (byte) 0xA0, (byte) 0x5B, (byte) 0xEC, (byte) 0xF1, (byte) 0x41, (byte) 0x57,
+        (byte) 0x4D, (byte) 0xC0, (byte) 0x79, (byte) 0xB3, (byte) 0xA9, (byte) 0x5C, (byte) 0x4A, (byte) 0x83,
+        (byte) 0xE6, (byte) 0xC4, (byte) 0x3F, (byte) 0x32, (byte) 0x14, (byte) 0xD6, (byte) 0xDF, (byte) 0x32,
+        (byte) 0xD5, (byte) 0x12, (byte) 0xDE, (byte) 0x19, (byte) 0x80, (byte) 0x85, (byte) 0xE5, (byte) 0x31,
+        (byte) 0xE6, (byte) 0x16, (byte) 0xB8, (byte) 0x3F, (byte) 0xD7, (byte) 0xDD, (byte) 0x9D, (byte) 0x1F,
+        (byte) 0x4E, (byte) 0x26, (byte) 0x07, (byte) 0xC3, (byte) 0x33, (byte) 0x3D, (byte) 0x07, (byte) 0xC5,
+        (byte) 0x5D, (byte) 0x10, (byte) 0x7D, (byte) 0x1D, (byte) 0x38, (byte) 0x93, (byte) 0x58, (byte) 0x71,
+    });
+
+    private static final BigInteger RSA_2048_primeExponentQ = new BigInteger(1, new byte[] {
+        (byte) 0xDB, (byte) 0x4F, (byte) 0xB5, (byte) 0x0F, (byte) 0x50, (byte) 0xDE, (byte) 0x8E, (byte) 0xDB,
+        (byte) 0x53, (byte) 0xFF, (byte) 0x34, (byte) 0xC8, (byte) 0x09, (byte) 0x31, (byte) 0x88, (byte) 0xA0,
+        (byte) 0x51, (byte) 0x28, (byte) 0x67, (byte) 0xDA, (byte) 0x2C, (byte) 0xCA, (byte) 0x04, (byte) 0x89,
+        (byte) 0x77, (byte) 0x59, (byte) 0xE5, (byte) 0x87, (byte) 0xC2, (byte) 0x44, (byte) 0x01, (byte) 0x0D,
+        (byte) 0xAF, (byte) 0x86, (byte) 0x64, (byte) 0xD5, (byte) 0x9E, (byte) 0x80, (byte) 0x83, (byte) 0xD1,
+        (byte) 0x6C, (byte) 0x16, (byte) 0x47, (byte) 0x89, (byte) 0x30, (byte) 0x1F, (byte) 0x67, (byte) 0xA9,
+        (byte) 0xF0, (byte) 0x78, (byte) 0x06, (byte) 0x0D, (byte) 0x83, (byte) 0x4A, (byte) 0x2A, (byte) 0xDB,
+        (byte) 0xD3, (byte) 0x67, (byte) 0x57, (byte) 0x5B, (byte) 0x68, (byte) 0xA8, (byte) 0xA8, (byte) 0x42,
+        (byte) 0xC2, (byte) 0xB0, (byte) 0x2A, (byte) 0x89, (byte) 0xB3, (byte) 0xF3, (byte) 0x1F, (byte) 0xCC,
+        (byte) 0xEC, (byte) 0x8A, (byte) 0x22, (byte) 0xFE, (byte) 0x39, (byte) 0x57, (byte) 0x95, (byte) 0xC5,
+        (byte) 0xC6, (byte) 0xC7, (byte) 0x42, (byte) 0x2B, (byte) 0x4E, (byte) 0x5D, (byte) 0x74, (byte) 0xA1,
+        (byte) 0xE9, (byte) 0xA8, (byte) 0xF3, (byte) 0x0E, (byte) 0x77, (byte) 0x59, (byte) 0xB9, (byte) 0xFC,
+        (byte) 0x2D, (byte) 0x63, (byte) 0x9C, (byte) 0x1F, (byte) 0x15, (byte) 0x67, (byte) 0x3E, (byte) 0x84,
+        (byte) 0xE9, (byte) 0x3A, (byte) 0x5E, (byte) 0xF1, (byte) 0x50, (byte) 0x6F, (byte) 0x43, (byte) 0x15,
+        (byte) 0x38, (byte) 0x3C, (byte) 0x38, (byte) 0xD4, (byte) 0x5C, (byte) 0xBD, (byte) 0x1B, (byte) 0x14,
+        (byte) 0x04, (byte) 0x8F, (byte) 0x47, (byte) 0x21, (byte) 0xDC, (byte) 0x82, (byte) 0x32, (byte) 0x61,
+    });
+
+    private static final BigInteger RSA_2048_crtCoefficient = new BigInteger(1, new byte[] {
+        (byte) 0xD8, (byte) 0x11, (byte) 0x45, (byte) 0x93, (byte) 0xAF, (byte) 0x41, (byte) 0x5F, (byte) 0xB6,
+        (byte) 0x12, (byte) 0xDB, (byte) 0xF1, (byte) 0x92, (byte) 0x37, (byte) 0x10, (byte) 0xD5, (byte) 0x4D,
+        (byte) 0x07, (byte) 0x48, (byte) 0x62, (byte) 0x05, (byte) 0xA7, (byte) 0x6A, (byte) 0x3B, (byte) 0x43,
+        (byte) 0x19, (byte) 0x49, (byte) 0x68, (byte) 0xC0, (byte) 0xDF, (byte) 0xF1, (byte) 0xF1, (byte) 0x1E,
+        (byte) 0xF0, (byte) 0xF6, (byte) 0x1A, (byte) 0x4A, (byte) 0x33, (byte) 0x7D, (byte) 0x5F, (byte) 0xD3,
+        (byte) 0x74, (byte) 0x1B, (byte) 0xBC, (byte) 0x96, (byte) 0x40, (byte) 0xE4, (byte) 0x47, (byte) 0xB8,
+        (byte) 0xB6, (byte) 0xB6, (byte) 0xC4, (byte) 0x7C, (byte) 0x3A, (byte) 0xC1, (byte) 0x20, (byte) 0x43,
+        (byte) 0x57, (byte) 0xD3, (byte) 0xB0, (byte) 0xC5, (byte) 0x5B, (byte) 0xA9, (byte) 0x28, (byte) 0x6B,
+        (byte) 0xDA, (byte) 0x73, (byte) 0xF6, (byte) 0x29, (byte) 0x29, (byte) 0x6F, (byte) 0x5F, (byte) 0xA9,
+        (byte) 0x14, (byte) 0x6D, (byte) 0x89, (byte) 0x76, (byte) 0x35, (byte) 0x7D, (byte) 0x3C, (byte) 0x75,
+        (byte) 0x1E, (byte) 0x75, (byte) 0x14, (byte) 0x86, (byte) 0x96, (byte) 0xA4, (byte) 0x0B, (byte) 0x74,
+        (byte) 0x68, (byte) 0x5C, (byte) 0x82, (byte) 0xCE, (byte) 0x30, (byte) 0x90, (byte) 0x2D, (byte) 0x63,
+        (byte) 0x9D, (byte) 0x72, (byte) 0x4F, (byte) 0xF2, (byte) 0x4D, (byte) 0x5E, (byte) 0x2E, (byte) 0x94,
+        (byte) 0x07, (byte) 0xEE, (byte) 0x34, (byte) 0xED, (byte) 0xED, (byte) 0x2E, (byte) 0x3B, (byte) 0x4D,
+        (byte) 0xF6, (byte) 0x5A, (byte) 0xA9, (byte) 0xBC, (byte) 0xFE, (byte) 0xB6, (byte) 0xDF, (byte) 0x28,
+        (byte) 0xD0, (byte) 0x7B, (byte) 0xA6, (byte) 0x90, (byte) 0x3F, (byte) 0x16, (byte) 0x57, (byte) 0x68,
+    });
+
     /**
      * Test data is PKCS#1 padded "Android.\n" which can be generated by:
      * echo "Android." | openssl rsautl -inkey rsa.key -sign | openssl rsautl -inkey rsa.key -raw -verify | recode ../x1
@@ -2119,6 +2204,319 @@
         (byte) 0x4b, (byte) 0x98, (byte) 0x3f, (byte) 0xae, (byte) 0x20, (byte) 0xfd,
         (byte) 0x8a, (byte) 0x50, (byte) 0x73, (byte) 0xe4,
     };
+    /*
+     * echo -n 'This is a test of OAEP' | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_Plaintext = new byte[] {
+            (byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69,
+            (byte) 0x73, (byte) 0x20, (byte) 0x61, (byte) 0x20, (byte) 0x74, (byte) 0x65,
+            (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x6f, (byte) 0x66, (byte) 0x20,
+            (byte) 0x4f, (byte) 0x41, (byte) 0x45, (byte) 0x50
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey rsakey.pem \
+     * -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 \
+     * | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA1_MGF1_SHA1 = new byte[] {
+            (byte) 0x53, (byte) 0x71, (byte) 0x84, (byte) 0x2e, (byte) 0x01, (byte) 0x74,
+            (byte) 0x82, (byte) 0xb3, (byte) 0x01, (byte) 0xac, (byte) 0x2b, (byte) 0xbd,
+            (byte) 0x40, (byte) 0xa7, (byte) 0x5b, (byte) 0x60, (byte) 0xf1, (byte) 0xde,
+            (byte) 0x54, (byte) 0x1d, (byte) 0x94, (byte) 0xc1, (byte) 0x10, (byte) 0x31,
+            (byte) 0x6f, (byte) 0xa3, (byte) 0xd8, (byte) 0x41, (byte) 0x2e, (byte) 0x82,
+            (byte) 0xad, (byte) 0x07, (byte) 0x6f, (byte) 0x25, (byte) 0x6c, (byte) 0xb5,
+            (byte) 0xef, (byte) 0xc6, (byte) 0xa6, (byte) 0xfb, (byte) 0xb1, (byte) 0x9d,
+            (byte) 0x75, (byte) 0x67, (byte) 0xb0, (byte) 0x97, (byte) 0x21, (byte) 0x3c,
+            (byte) 0x17, (byte) 0x04, (byte) 0xdc, (byte) 0x4e, (byte) 0x7e, (byte) 0x3f,
+            (byte) 0x5c, (byte) 0x13, (byte) 0x5e, (byte) 0x15, (byte) 0x0f, (byte) 0xe2,
+            (byte) 0xa7, (byte) 0x62, (byte) 0x6a, (byte) 0x08, (byte) 0xb1, (byte) 0xbc,
+            (byte) 0x2f, (byte) 0xcb, (byte) 0xb5, (byte) 0x96, (byte) 0x2d, (byte) 0xec,
+            (byte) 0x71, (byte) 0x4d, (byte) 0x59, (byte) 0x6e, (byte) 0x27, (byte) 0x85,
+            (byte) 0x87, (byte) 0x9b, (byte) 0xcc, (byte) 0x40, (byte) 0x32, (byte) 0x09,
+            (byte) 0x06, (byte) 0xe6, (byte) 0x7d, (byte) 0xdf, (byte) 0xeb, (byte) 0x2f,
+            (byte) 0xa8, (byte) 0x1c, (byte) 0x53, (byte) 0xdb, (byte) 0xa7, (byte) 0x48,
+            (byte) 0xf5, (byte) 0xbf, (byte) 0x2f, (byte) 0xbb, (byte) 0xee, (byte) 0xc7,
+            (byte) 0x55, (byte) 0x5e, (byte) 0xc4, (byte) 0x1c, (byte) 0x84, (byte) 0xed,
+            (byte) 0x97, (byte) 0x7e, (byte) 0xce, (byte) 0xa5, (byte) 0x69, (byte) 0x73,
+            (byte) 0xb3, (byte) 0xe0, (byte) 0x8c, (byte) 0x2a, (byte) 0xf2, (byte) 0xc7,
+            (byte) 0x65, (byte) 0xff, (byte) 0x10, (byte) 0xed, (byte) 0x25, (byte) 0xf0,
+            (byte) 0xf8, (byte) 0xda, (byte) 0x2f, (byte) 0x7f, (byte) 0xe0, (byte) 0x69,
+            (byte) 0xed, (byte) 0xb1, (byte) 0x0e, (byte) 0xcb, (byte) 0x43, (byte) 0xe4,
+            (byte) 0x31, (byte) 0xe6, (byte) 0x52, (byte) 0xfd, (byte) 0xa7, (byte) 0xe5,
+            (byte) 0x21, (byte) 0xd0, (byte) 0x67, (byte) 0x0a, (byte) 0xc1, (byte) 0xa1,
+            (byte) 0xb9, (byte) 0x04, (byte) 0xdb, (byte) 0x98, (byte) 0x4f, (byte) 0xf9,
+            (byte) 0x5c, (byte) 0x60, (byte) 0x4d, (byte) 0xac, (byte) 0x7a, (byte) 0x69,
+            (byte) 0xbd, (byte) 0x63, (byte) 0x0d, (byte) 0xb2, (byte) 0x01, (byte) 0x83,
+            (byte) 0xd7, (byte) 0x22, (byte) 0x5d, (byte) 0xed, (byte) 0xbd, (byte) 0x32,
+            (byte) 0x98, (byte) 0xd1, (byte) 0x4a, (byte) 0x2e, (byte) 0xb7, (byte) 0xb1,
+            (byte) 0x6d, (byte) 0x8a, (byte) 0x8f, (byte) 0xef, (byte) 0xc3, (byte) 0x89,
+            (byte) 0xdf, (byte) 0xa5, (byte) 0xac, (byte) 0xfb, (byte) 0x38, (byte) 0x61,
+            (byte) 0x32, (byte) 0xc5, (byte) 0x19, (byte) 0x83, (byte) 0x1f, (byte) 0x9c,
+            (byte) 0x45, (byte) 0x58, (byte) 0xdd, (byte) 0xa3, (byte) 0x57, (byte) 0xe4,
+            (byte) 0x91, (byte) 0xd2, (byte) 0x11, (byte) 0xf8, (byte) 0x96, (byte) 0x36,
+            (byte) 0x67, (byte) 0x99, (byte) 0x2b, (byte) 0x62, (byte) 0x21, (byte) 0xe3,
+            (byte) 0xa8, (byte) 0x5e, (byte) 0xa4, (byte) 0x2e, (byte) 0x0c, (byte) 0x29,
+            (byte) 0xf9, (byte) 0xcd, (byte) 0xfa, (byte) 0xbe, (byte) 0x3f, (byte) 0xd8,
+            (byte) 0xec, (byte) 0x6b, (byte) 0x32, (byte) 0xb3, (byte) 0x40, (byte) 0x4f,
+            (byte) 0x48, (byte) 0xe3, (byte) 0x14, (byte) 0x87, (byte) 0xa7, (byte) 0x5c,
+            (byte) 0xba, (byte) 0xdf, (byte) 0x0e, (byte) 0x64, (byte) 0xdc, (byte) 0xe2,
+            (byte) 0x51, (byte) 0xf4, (byte) 0x41, (byte) 0x25, (byte) 0x23, (byte) 0xc8,
+            (byte) 0x50, (byte) 0x1e, (byte) 0x9e, (byte) 0xb0
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey rsakey.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha1 | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA256_MGF1_SHA1 = new byte[] {
+            (byte) 0x25, (byte) 0x9f, (byte) 0xc3, (byte) 0x69, (byte) 0xbc, (byte) 0x3f,
+            (byte) 0xe7, (byte) 0x9e, (byte) 0x76, (byte) 0xef, (byte) 0x6c, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0x7b, (byte) 0xf0, (byte) 0xeb, (byte) 0xc2, (byte) 0x28,
+            (byte) 0x40, (byte) 0x4e, (byte) 0x9b, (byte) 0x2a, (byte) 0x4e, (byte) 0xa4,
+            (byte) 0x79, (byte) 0x66, (byte) 0xf1, (byte) 0x10, (byte) 0x96, (byte) 0x8c,
+            (byte) 0x58, (byte) 0x92, (byte) 0xb7, (byte) 0x70, (byte) 0xed, (byte) 0x3a,
+            (byte) 0xe0, (byte) 0x99, (byte) 0xd1, (byte) 0x80, (byte) 0x4b, (byte) 0x53,
+            (byte) 0x70, (byte) 0x9b, (byte) 0x51, (byte) 0xbf, (byte) 0xc1, (byte) 0x3a,
+            (byte) 0x70, (byte) 0xc5, (byte) 0x79, (byte) 0x21, (byte) 0x6e, (byte) 0xb3,
+            (byte) 0xf7, (byte) 0xa9, (byte) 0xe6, (byte) 0xcb, (byte) 0x70, (byte) 0xe4,
+            (byte) 0xf3, (byte) 0x4f, (byte) 0x45, (byte) 0xcf, (byte) 0xb7, (byte) 0x2b,
+            (byte) 0x38, (byte) 0xfd, (byte) 0x5d, (byte) 0x9a, (byte) 0x53, (byte) 0xc5,
+            (byte) 0x05, (byte) 0x74, (byte) 0x8d, (byte) 0x1d, (byte) 0x6e, (byte) 0x83,
+            (byte) 0xaa, (byte) 0x71, (byte) 0xc5, (byte) 0xe1, (byte) 0xa1, (byte) 0xa6,
+            (byte) 0xf3, (byte) 0xee, (byte) 0x5f, (byte) 0x9e, (byte) 0x4f, (byte) 0xe8,
+            (byte) 0x15, (byte) 0xd5, (byte) 0xa9, (byte) 0x1b, (byte) 0xa6, (byte) 0x41,
+            (byte) 0x2b, (byte) 0x18, (byte) 0x13, (byte) 0x20, (byte) 0x9f, (byte) 0x6b,
+            (byte) 0xf1, (byte) 0xd8, (byte) 0xf4, (byte) 0x87, (byte) 0xfa, (byte) 0x80,
+            (byte) 0xec, (byte) 0x0e, (byte) 0xa4, (byte) 0x4b, (byte) 0x24, (byte) 0x03,
+            (byte) 0x14, (byte) 0x25, (byte) 0xf2, (byte) 0x20, (byte) 0xfc, (byte) 0x52,
+            (byte) 0xf9, (byte) 0xd6, (byte) 0x7a, (byte) 0x4a, (byte) 0x45, (byte) 0x33,
+            (byte) 0xec, (byte) 0xde, (byte) 0x3c, (byte) 0x5b, (byte) 0xf2, (byte) 0xdc,
+            (byte) 0x8e, (byte) 0xc6, (byte) 0xb3, (byte) 0x26, (byte) 0xd3, (byte) 0x68,
+            (byte) 0xa7, (byte) 0xd8, (byte) 0x3a, (byte) 0xde, (byte) 0xa9, (byte) 0x25,
+            (byte) 0x1d, (byte) 0x42, (byte) 0x75, (byte) 0x66, (byte) 0x16, (byte) 0x29,
+            (byte) 0xad, (byte) 0x09, (byte) 0x74, (byte) 0x41, (byte) 0xbb, (byte) 0x45,
+            (byte) 0x39, (byte) 0x04, (byte) 0x7a, (byte) 0x93, (byte) 0xad, (byte) 0x1c,
+            (byte) 0xa6, (byte) 0x38, (byte) 0xf4, (byte) 0xac, (byte) 0xca, (byte) 0x5a,
+            (byte) 0xab, (byte) 0x92, (byte) 0x76, (byte) 0x26, (byte) 0x3c, (byte) 0xeb,
+            (byte) 0xda, (byte) 0xfc, (byte) 0x25, (byte) 0x93, (byte) 0x23, (byte) 0x01,
+            (byte) 0xe2, (byte) 0xac, (byte) 0x5e, (byte) 0x4c, (byte) 0xb7, (byte) 0xbc,
+            (byte) 0x5b, (byte) 0xaa, (byte) 0x14, (byte) 0xe9, (byte) 0xbf, (byte) 0x2d,
+            (byte) 0x3a, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x4d, (byte) 0x0e,
+            (byte) 0x0a, (byte) 0x82, (byte) 0x3c, (byte) 0xd9, (byte) 0x32, (byte) 0xc1,
+            (byte) 0xc4, (byte) 0xa2, (byte) 0x46, (byte) 0x71, (byte) 0x10, (byte) 0x54,
+            (byte) 0x1a, (byte) 0xa6, (byte) 0xaa, (byte) 0x64, (byte) 0xe7, (byte) 0xc2,
+            (byte) 0xae, (byte) 0xbc, (byte) 0x3d, (byte) 0xa4, (byte) 0xa8, (byte) 0xd1,
+            (byte) 0xb7, (byte) 0x27, (byte) 0xef, (byte) 0x5f, (byte) 0xe7, (byte) 0xa7,
+            (byte) 0x5d, (byte) 0xa0, (byte) 0xcd, (byte) 0x57, (byte) 0xf1, (byte) 0xe0,
+            (byte) 0xd8, (byte) 0x42, (byte) 0x10, (byte) 0x77, (byte) 0xc3, (byte) 0xa7,
+            (byte) 0x1e, (byte) 0x0c, (byte) 0x37, (byte) 0x16, (byte) 0x11, (byte) 0x94,
+            (byte) 0x21, (byte) 0xf2, (byte) 0xca, (byte) 0x60, (byte) 0xce, (byte) 0xca,
+            (byte) 0x59, (byte) 0xf9, (byte) 0xe5, (byte) 0xe4
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey rsakey.pem \
+     * -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha224 -pkeyopt rsa_mgf1_md:sha224 \
+     * | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA224_MGF1_SHA224 = new byte[] {
+            (byte) 0xae, (byte) 0xdd, (byte) 0xe6, (byte) 0xab, (byte) 0x00, (byte) 0xd6,
+            (byte) 0x1e, (byte) 0x7e, (byte) 0x85, (byte) 0x63, (byte) 0xab, (byte) 0x51,
+            (byte) 0x79, (byte) 0x92, (byte) 0xf1, (byte) 0xb9, (byte) 0x4f, (byte) 0x23,
+            (byte) 0xae, (byte) 0xf7, (byte) 0x1b, (byte) 0x5f, (byte) 0x10, (byte) 0x5b,
+            (byte) 0xa5, (byte) 0x15, (byte) 0x87, (byte) 0xa3, (byte) 0xbb, (byte) 0x26,
+            (byte) 0xfe, (byte) 0x7f, (byte) 0xc0, (byte) 0xa3, (byte) 0x67, (byte) 0x95,
+            (byte) 0xda, (byte) 0xc4, (byte) 0x6f, (byte) 0x6e, (byte) 0x08, (byte) 0x23,
+            (byte) 0x28, (byte) 0x0b, (byte) 0xdd, (byte) 0x29, (byte) 0x29, (byte) 0xdc,
+            (byte) 0xb0, (byte) 0x35, (byte) 0x16, (byte) 0x2e, (byte) 0x0f, (byte) 0xb9,
+            (byte) 0x1d, (byte) 0x90, (byte) 0x27, (byte) 0x68, (byte) 0xc7, (byte) 0x92,
+            (byte) 0x52, (byte) 0x8a, (byte) 0x1d, (byte) 0x48, (byte) 0x6a, (byte) 0x7d,
+            (byte) 0x0b, (byte) 0xf6, (byte) 0x35, (byte) 0xca, (byte) 0xe1, (byte) 0x57,
+            (byte) 0xdd, (byte) 0x36, (byte) 0x3b, (byte) 0x51, (byte) 0x45, (byte) 0x77,
+            (byte) 0x28, (byte) 0x4f, (byte) 0x98, (byte) 0xc0, (byte) 0xe0, (byte) 0xa7,
+            (byte) 0x51, (byte) 0x98, (byte) 0x84, (byte) 0x7a, (byte) 0x29, (byte) 0x05,
+            (byte) 0x9f, (byte) 0x60, (byte) 0x66, (byte) 0xf6, (byte) 0x83, (byte) 0xcd,
+            (byte) 0x03, (byte) 0x3e, (byte) 0x82, (byte) 0x0f, (byte) 0x57, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x14, (byte) 0xf6, (byte) 0xc8, (byte) 0x5b, (byte) 0xed,
+            (byte) 0xc3, (byte) 0x77, (byte) 0x6f, (byte) 0xec, (byte) 0x0e, (byte) 0xae,
+            (byte) 0x59, (byte) 0xbe, (byte) 0x68, (byte) 0x76, (byte) 0x16, (byte) 0x17,
+            (byte) 0x77, (byte) 0xe2, (byte) 0xbd, (byte) 0xe0, (byte) 0x5a, (byte) 0x14,
+            (byte) 0xd9, (byte) 0xf4, (byte) 0x3f, (byte) 0x50, (byte) 0x31, (byte) 0xf0,
+            (byte) 0x0c, (byte) 0x82, (byte) 0x6c, (byte) 0xcc, (byte) 0x81, (byte) 0x84,
+            (byte) 0x3e, (byte) 0x63, (byte) 0x93, (byte) 0xe7, (byte) 0x12, (byte) 0x2d,
+            (byte) 0xc9, (byte) 0xa3, (byte) 0xe3, (byte) 0xce, (byte) 0xfd, (byte) 0xc7,
+            (byte) 0xe1, (byte) 0xef, (byte) 0xa4, (byte) 0x16, (byte) 0x5c, (byte) 0x60,
+            (byte) 0xb1, (byte) 0x80, (byte) 0x31, (byte) 0x15, (byte) 0x5c, (byte) 0x35,
+            (byte) 0x25, (byte) 0x0b, (byte) 0x89, (byte) 0xe4, (byte) 0x56, (byte) 0x74,
+            (byte) 0x8b, (byte) 0xaf, (byte) 0x8e, (byte) 0xe9, (byte) 0xe2, (byte) 0x37,
+            (byte) 0x17, (byte) 0xe6, (byte) 0x7b, (byte) 0x78, (byte) 0xd8, (byte) 0x2c,
+            (byte) 0x27, (byte) 0x52, (byte) 0x21, (byte) 0x96, (byte) 0xa0, (byte) 0x92,
+            (byte) 0x95, (byte) 0x64, (byte) 0xc3, (byte) 0x7f, (byte) 0x45, (byte) 0xfc,
+            (byte) 0x3d, (byte) 0x48, (byte) 0x4a, (byte) 0xd5, (byte) 0xa4, (byte) 0x0a,
+            (byte) 0x57, (byte) 0x07, (byte) 0x57, (byte) 0x95, (byte) 0x9f, (byte) 0x2f,
+            (byte) 0x75, (byte) 0x32, (byte) 0x2a, (byte) 0x4d, (byte) 0x64, (byte) 0xbd,
+            (byte) 0xb1, (byte) 0xe0, (byte) 0x46, (byte) 0x4f, (byte) 0xe8, (byte) 0x6c,
+            (byte) 0x4b, (byte) 0x77, (byte) 0xcc, (byte) 0x36, (byte) 0x87, (byte) 0x05,
+            (byte) 0x56, (byte) 0x9a, (byte) 0xe4, (byte) 0x2c, (byte) 0x43, (byte) 0xfd,
+            (byte) 0x34, (byte) 0x97, (byte) 0xf8, (byte) 0xd7, (byte) 0x91, (byte) 0xff,
+            (byte) 0x56, (byte) 0x86, (byte) 0x17, (byte) 0x49, (byte) 0x0a, (byte) 0x52,
+            (byte) 0xfb, (byte) 0xe5, (byte) 0x49, (byte) 0xdf, (byte) 0xc1, (byte) 0x28,
+            (byte) 0x9d, (byte) 0x85, (byte) 0x66, (byte) 0x9d, (byte) 0x1d, (byte) 0xa4,
+            (byte) 0x7e, (byte) 0x9a, (byte) 0x5b, (byte) 0x30
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey /tmp/rsakey.txt \
+     * -pkeyopt rsa_padding_mode:oaep -pkey rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 \
+     * | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA256_MGF1_SHA256 = new byte[] {
+            (byte) 0x6a, (byte) 0x2b, (byte) 0xb2, (byte) 0xa3, (byte) 0x26, (byte) 0xa6,
+            (byte) 0x7a, (byte) 0x4a, (byte) 0x1f, (byte) 0xe5, (byte) 0xc8, (byte) 0x94,
+            (byte) 0x11, (byte) 0x1a, (byte) 0x92, (byte) 0x07, (byte) 0x0a, (byte) 0xf4,
+            (byte) 0x07, (byte) 0x0b, (byte) 0xd6, (byte) 0x37, (byte) 0xa5, (byte) 0x5d,
+            (byte) 0x16, (byte) 0x0a, (byte) 0x7d, (byte) 0x13, (byte) 0x27, (byte) 0x32,
+            (byte) 0x5a, (byte) 0xc3, (byte) 0x0d, (byte) 0x7a, (byte) 0x54, (byte) 0xfe,
+            (byte) 0x02, (byte) 0x28, (byte) 0xc6, (byte) 0x8e, (byte) 0x32, (byte) 0x7b,
+            (byte) 0x0a, (byte) 0x52, (byte) 0xf8, (byte) 0xe6, (byte) 0xab, (byte) 0x16,
+            (byte) 0x77, (byte) 0x7c, (byte) 0x53, (byte) 0xcd, (byte) 0xb0, (byte) 0xb6,
+            (byte) 0x90, (byte) 0xce, (byte) 0x7b, (byte) 0xa5, (byte) 0xdb, (byte) 0xab,
+            (byte) 0xfd, (byte) 0xf5, (byte) 0xbb, (byte) 0x49, (byte) 0x63, (byte) 0xb7,
+            (byte) 0xa8, (byte) 0x3e, (byte) 0x53, (byte) 0xf1, (byte) 0x00, (byte) 0x4d,
+            (byte) 0x72, (byte) 0x15, (byte) 0x34, (byte) 0xa8, (byte) 0x5b, (byte) 0x00,
+            (byte) 0x01, (byte) 0x75, (byte) 0xdc, (byte) 0xb6, (byte) 0xd1, (byte) 0xdf,
+            (byte) 0xcb, (byte) 0x93, (byte) 0xf3, (byte) 0x31, (byte) 0x04, (byte) 0x7e,
+            (byte) 0x48, (byte) 0x3e, (byte) 0xc9, (byte) 0xaf, (byte) 0xd7, (byte) 0xbd,
+            (byte) 0x9e, (byte) 0x73, (byte) 0x01, (byte) 0x79, (byte) 0xf8, (byte) 0xdc,
+            (byte) 0x46, (byte) 0x31, (byte) 0x55, (byte) 0x83, (byte) 0x21, (byte) 0xd1,
+            (byte) 0x19, (byte) 0x0b, (byte) 0x57, (byte) 0xf1, (byte) 0x06, (byte) 0xb9,
+            (byte) 0x32, (byte) 0x0e, (byte) 0x9d, (byte) 0x38, (byte) 0x53, (byte) 0x94,
+            (byte) 0x96, (byte) 0xd4, (byte) 0x6d, (byte) 0x18, (byte) 0xe2, (byte) 0xe3,
+            (byte) 0xcd, (byte) 0xfa, (byte) 0xfe, (byte) 0xb3, (byte) 0xe3, (byte) 0x27,
+            (byte) 0xd7, (byte) 0x45, (byte) 0xe8, (byte) 0x46, (byte) 0x6b, (byte) 0x06,
+            (byte) 0x0f, (byte) 0x5e, (byte) 0x24, (byte) 0x02, (byte) 0xef, (byte) 0xa2,
+            (byte) 0x69, (byte) 0xe6, (byte) 0x15, (byte) 0xb3, (byte) 0x8f, (byte) 0x71,
+            (byte) 0x97, (byte) 0x39, (byte) 0xfb, (byte) 0x32, (byte) 0xe0, (byte) 0xe5,
+            (byte) 0xac, (byte) 0x46, (byte) 0xb4, (byte) 0xe7, (byte) 0x3d, (byte) 0x89,
+            (byte) 0xba, (byte) 0xd9, (byte) 0x4c, (byte) 0x25, (byte) 0x97, (byte) 0xef,
+            (byte) 0xe6, (byte) 0x17, (byte) 0x23, (byte) 0x4e, (byte) 0xc8, (byte) 0xdb,
+            (byte) 0x18, (byte) 0x9b, (byte) 0xba, (byte) 0xb5, (byte) 0x7e, (byte) 0x19,
+            (byte) 0x4d, (byte) 0x95, (byte) 0x7d, (byte) 0x60, (byte) 0x1b, (byte) 0xa7,
+            (byte) 0x06, (byte) 0x1e, (byte) 0x99, (byte) 0x4a, (byte) 0xf2, (byte) 0x82,
+            (byte) 0x71, (byte) 0x62, (byte) 0x41, (byte) 0xa4, (byte) 0xa7, (byte) 0xdb,
+            (byte) 0x88, (byte) 0xb0, (byte) 0x4a, (byte) 0xc7, (byte) 0x3b, (byte) 0xce,
+            (byte) 0x91, (byte) 0x4f, (byte) 0xc7, (byte) 0xca, (byte) 0x6f, (byte) 0x89,
+            (byte) 0xac, (byte) 0x1a, (byte) 0x36, (byte) 0x84, (byte) 0x0c, (byte) 0x97,
+            (byte) 0xa0, (byte) 0x1a, (byte) 0x08, (byte) 0x6f, (byte) 0x70, (byte) 0xf3,
+            (byte) 0x94, (byte) 0xa0, (byte) 0x0f, (byte) 0x44, (byte) 0xdd, (byte) 0x86,
+            (byte) 0x9d, (byte) 0x2c, (byte) 0xac, (byte) 0x43, (byte) 0xed, (byte) 0xb8,
+            (byte) 0xa1, (byte) 0x66, (byte) 0xf3, (byte) 0xd3, (byte) 0x5c, (byte) 0xe5,
+            (byte) 0xe2, (byte) 0x4c, (byte) 0x7e, (byte) 0xda, (byte) 0x20, (byte) 0xbd,
+            (byte) 0x5a, (byte) 0x75, (byte) 0x12, (byte) 0x31, (byte) 0x23, (byte) 0x02,
+            (byte) 0xb5, (byte) 0x1f, (byte) 0x38, (byte) 0x98
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey /tmp/rsakey.txt \
+     * -pkeyopt rsa_padding_mode:oaep -pkey rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 \
+     * | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA384_MGF1_SHA384 = new byte[] {
+            (byte) 0xa1, (byte) 0xb3, (byte) 0x3b, (byte) 0x34, (byte) 0x69, (byte) 0x9e,
+            (byte) 0xd8, (byte) 0xa0, (byte) 0x37, (byte) 0x2c, (byte) 0xeb, (byte) 0xef,
+            (byte) 0xf2, (byte) 0xaf, (byte) 0xfa, (byte) 0x63, (byte) 0x5d, (byte) 0x88,
+            (byte) 0xac, (byte) 0x51, (byte) 0xd4, (byte) 0x7f, (byte) 0x85, (byte) 0xf0,
+            (byte) 0x5e, (byte) 0xb4, (byte) 0x81, (byte) 0x7c, (byte) 0x82, (byte) 0x4f,
+            (byte) 0x92, (byte) 0xf7, (byte) 0x77, (byte) 0x48, (byte) 0x4c, (byte) 0xb1,
+            (byte) 0x42, (byte) 0xb3, (byte) 0x0e, (byte) 0x94, (byte) 0xc8, (byte) 0x5a,
+            (byte) 0xae, (byte) 0xed, (byte) 0x8d, (byte) 0x51, (byte) 0x72, (byte) 0x6b,
+            (byte) 0xa9, (byte) 0xd4, (byte) 0x1e, (byte) 0xbe, (byte) 0x38, (byte) 0x2c,
+            (byte) 0xd0, (byte) 0x43, (byte) 0xae, (byte) 0xb4, (byte) 0x30, (byte) 0xa9,
+            (byte) 0x93, (byte) 0x47, (byte) 0xb5, (byte) 0x9d, (byte) 0x03, (byte) 0x92,
+            (byte) 0x25, (byte) 0x74, (byte) 0xed, (byte) 0xfa, (byte) 0xfe, (byte) 0xf1,
+            (byte) 0xba, (byte) 0x04, (byte) 0x3a, (byte) 0x4d, (byte) 0x6d, (byte) 0x9a,
+            (byte) 0x0d, (byte) 0x95, (byte) 0x02, (byte) 0xb0, (byte) 0xac, (byte) 0x77,
+            (byte) 0x11, (byte) 0x44, (byte) 0xeb, (byte) 0xd2, (byte) 0x02, (byte) 0x90,
+            (byte) 0xea, (byte) 0x2f, (byte) 0x68, (byte) 0x2a, (byte) 0x69, (byte) 0xcf,
+            (byte) 0x45, (byte) 0x34, (byte) 0xff, (byte) 0x00, (byte) 0xc6, (byte) 0x3c,
+            (byte) 0x0b, (byte) 0x2c, (byte) 0x5f, (byte) 0x8c, (byte) 0x2c, (byte) 0xbf,
+            (byte) 0xc2, (byte) 0x4b, (byte) 0x16, (byte) 0x07, (byte) 0x84, (byte) 0x74,
+            (byte) 0xf0, (byte) 0x7a, (byte) 0x01, (byte) 0x7e, (byte) 0x74, (byte) 0x01,
+            (byte) 0x88, (byte) 0xce, (byte) 0xda, (byte) 0xe4, (byte) 0x21, (byte) 0x89,
+            (byte) 0xfc, (byte) 0xac, (byte) 0x68, (byte) 0xdb, (byte) 0xfc, (byte) 0x5f,
+            (byte) 0x3f, (byte) 0x00, (byte) 0xd9, (byte) 0x32, (byte) 0x1d, (byte) 0xa5,
+            (byte) 0xec, (byte) 0x72, (byte) 0x46, (byte) 0x23, (byte) 0xe5, (byte) 0x7f,
+            (byte) 0x49, (byte) 0x0e, (byte) 0x3e, (byte) 0xf2, (byte) 0x2b, (byte) 0x16,
+            (byte) 0x52, (byte) 0x9f, (byte) 0x9d, (byte) 0x0c, (byte) 0xfe, (byte) 0xab,
+            (byte) 0xdd, (byte) 0x77, (byte) 0x77, (byte) 0x94, (byte) 0xa4, (byte) 0x92,
+            (byte) 0xa2, (byte) 0x41, (byte) 0x0d, (byte) 0x4b, (byte) 0x57, (byte) 0x80,
+            (byte) 0xd6, (byte) 0x74, (byte) 0x63, (byte) 0xd5, (byte) 0xbf, (byte) 0x5c,
+            (byte) 0xa0, (byte) 0xda, (byte) 0x3c, (byte) 0xe6, (byte) 0xbf, (byte) 0xa4,
+            (byte) 0xc3, (byte) 0xfb, (byte) 0x46, (byte) 0x3b, (byte) 0x73, (byte) 0x30,
+            (byte) 0x4b, (byte) 0x57, (byte) 0x27, (byte) 0x0c, (byte) 0x81, (byte) 0xde,
+            (byte) 0x8a, (byte) 0x01, (byte) 0xe5, (byte) 0x7e, (byte) 0xe0, (byte) 0x16,
+            (byte) 0x11, (byte) 0x24, (byte) 0x34, (byte) 0x22, (byte) 0x01, (byte) 0x9f,
+            (byte) 0xe6, (byte) 0xa9, (byte) 0xfb, (byte) 0xad, (byte) 0x55, (byte) 0x17,
+            (byte) 0x2a, (byte) 0x92, (byte) 0x87, (byte) 0xf3, (byte) 0x72, (byte) 0xc9,
+            (byte) 0x3d, (byte) 0xc9, (byte) 0x2e, (byte) 0x32, (byte) 0x8e, (byte) 0xbb,
+            (byte) 0xdc, (byte) 0x1b, (byte) 0xa7, (byte) 0x7b, (byte) 0x73, (byte) 0xd7,
+            (byte) 0xf4, (byte) 0xad, (byte) 0xa9, (byte) 0x3a, (byte) 0xf7, (byte) 0xa8,
+            (byte) 0x82, (byte) 0x92, (byte) 0x40, (byte) 0xd4, (byte) 0x51, (byte) 0x87,
+            (byte) 0xe1, (byte) 0xb7, (byte) 0x4f, (byte) 0x91, (byte) 0x75, (byte) 0x5b,
+            (byte) 0x03, (byte) 0x9d, (byte) 0xa1, (byte) 0xd4, (byte) 0x00, (byte) 0x05,
+            (byte) 0x79, (byte) 0x42, (byte) 0x93, (byte) 0x76
+    };
+
+    /*
+     * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey /tmp/rsakey.txt \
+     * -pkeyopt rsa_padding_mode:oaep -pkey rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 \
+     * | xxd -p -i | sed 's/0x/(byte) 0x/g'
+     */
+    public static final byte[] RSA_Vector2_OAEP_SHA512_MGF1_SHA512 = new byte[] {
+            (byte) 0x75, (byte) 0x0f, (byte) 0xf9, (byte) 0x21, (byte) 0xca, (byte) 0xcc,
+            (byte) 0x0e, (byte) 0x13, (byte) 0x9e, (byte) 0x38, (byte) 0xa4, (byte) 0xa7,
+            (byte) 0xee, (byte) 0x61, (byte) 0x6d, (byte) 0x56, (byte) 0xea, (byte) 0x36,
+            (byte) 0xeb, (byte) 0xec, (byte) 0xfa, (byte) 0x1a, (byte) 0xeb, (byte) 0x0c,
+            (byte) 0xb2, (byte) 0x58, (byte) 0x9d, (byte) 0xde, (byte) 0x47, (byte) 0x27,
+            (byte) 0x2d, (byte) 0xbd, (byte) 0x8b, (byte) 0xa7, (byte) 0xf1, (byte) 0x8b,
+            (byte) 0xba, (byte) 0x4c, (byte) 0xab, (byte) 0x39, (byte) 0x6a, (byte) 0x82,
+            (byte) 0x0d, (byte) 0xaf, (byte) 0x4c, (byte) 0xde, (byte) 0xdb, (byte) 0x5e,
+            (byte) 0xdb, (byte) 0x08, (byte) 0x98, (byte) 0x06, (byte) 0xc5, (byte) 0x99,
+            (byte) 0xb6, (byte) 0x6d, (byte) 0xbc, (byte) 0x5b, (byte) 0xf9, (byte) 0xe4,
+            (byte) 0x97, (byte) 0x0b, (byte) 0xba, (byte) 0xe3, (byte) 0x17, (byte) 0xa9,
+            (byte) 0x3c, (byte) 0x4b, (byte) 0x21, (byte) 0xd8, (byte) 0x29, (byte) 0xf8,
+            (byte) 0xa7, (byte) 0x1c, (byte) 0x15, (byte) 0xd7, (byte) 0xf6, (byte) 0xfc,
+            (byte) 0x53, (byte) 0x64, (byte) 0x97, (byte) 0x9e, (byte) 0x22, (byte) 0xb1,
+            (byte) 0x93, (byte) 0x26, (byte) 0x80, (byte) 0xdc, (byte) 0xaa, (byte) 0x1b,
+            (byte) 0xae, (byte) 0x69, (byte) 0x0f, (byte) 0x74, (byte) 0x3d, (byte) 0x61,
+            (byte) 0x80, (byte) 0x68, (byte) 0xb8, (byte) 0xaf, (byte) 0x63, (byte) 0x72,
+            (byte) 0x37, (byte) 0x4f, (byte) 0xf3, (byte) 0x29, (byte) 0x4a, (byte) 0x75,
+            (byte) 0x4f, (byte) 0x29, (byte) 0x40, (byte) 0x01, (byte) 0xd3, (byte) 0xc6,
+            (byte) 0x56, (byte) 0x1a, (byte) 0xaf, (byte) 0xc3, (byte) 0xb3, (byte) 0xd2,
+            (byte) 0xb9, (byte) 0x91, (byte) 0x35, (byte) 0x1b, (byte) 0x89, (byte) 0x4c,
+            (byte) 0x61, (byte) 0xa2, (byte) 0x8e, (byte) 0x6f, (byte) 0x12, (byte) 0x4a,
+            (byte) 0x10, (byte) 0xc2, (byte) 0xcc, (byte) 0xab, (byte) 0x51, (byte) 0xec,
+            (byte) 0x1b, (byte) 0xb5, (byte) 0xfe, (byte) 0x20, (byte) 0x16, (byte) 0xb2,
+            (byte) 0xc5, (byte) 0x0f, (byte) 0xe1, (byte) 0x6a, (byte) 0xb4, (byte) 0x6c,
+            (byte) 0x27, (byte) 0xd9, (byte) 0x42, (byte) 0xb9, (byte) 0xb6, (byte) 0x55,
+            (byte) 0xa8, (byte) 0xbc, (byte) 0x1c, (byte) 0x32, (byte) 0x54, (byte) 0x84,
+            (byte) 0xec, (byte) 0x1e, (byte) 0x95, (byte) 0xd8, (byte) 0xae, (byte) 0xca,
+            (byte) 0xc1, (byte) 0xad, (byte) 0x4c, (byte) 0x65, (byte) 0xd6, (byte) 0xc2,
+            (byte) 0x19, (byte) 0x66, (byte) 0xad, (byte) 0x9f, (byte) 0x55, (byte) 0x15,
+            (byte) 0xe1, (byte) 0x5d, (byte) 0x8f, (byte) 0xab, (byte) 0x18, (byte) 0x68,
+            (byte) 0x42, (byte) 0x7c, (byte) 0x48, (byte) 0xb7, (byte) 0x2c, (byte) 0xfd,
+            (byte) 0x1a, (byte) 0x07, (byte) 0xa1, (byte) 0x6a, (byte) 0xfb, (byte) 0x81,
+            (byte) 0xc6, (byte) 0x93, (byte) 0xbf, (byte) 0xa3, (byte) 0x5d, (byte) 0xfd,
+            (byte) 0xce, (byte) 0xf3, (byte) 0x17, (byte) 0x26, (byte) 0xf0, (byte) 0xda,
+            (byte) 0x0e, (byte) 0xd1, (byte) 0x86, (byte) 0x9d, (byte) 0x61, (byte) 0xd1,
+            (byte) 0x8a, (byte) 0xdb, (byte) 0x36, (byte) 0x39, (byte) 0x1c, (byte) 0xd4,
+            (byte) 0x99, (byte) 0x53, (byte) 0x30, (byte) 0x5a, (byte) 0x01, (byte) 0xf4,
+            (byte) 0xa0, (byte) 0xca, (byte) 0x94, (byte) 0x72, (byte) 0x3d, (byte) 0xe3,
+            (byte) 0x50, (byte) 0x95, (byte) 0xcb, (byte) 0xa9, (byte) 0x37, (byte) 0xeb,
+            (byte) 0x66, (byte) 0x21, (byte) 0x20, (byte) 0x2e, (byte) 0xf2, (byte) 0xfd,
+            (byte) 0xfa, (byte) 0x54, (byte) 0xbf, (byte) 0x17, (byte) 0x23, (byte) 0xbb,
+            (byte) 0x9e, (byte) 0x77, (byte) 0xe0, (byte) 0xaa
+    };
 
     public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success() throws Exception {
         for (String provider : RSA_PROVIDERS) {
@@ -2127,11 +2525,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2158,11 +2552,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2193,11 +2583,7 @@
 
     private void testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success(String provider)
             throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2231,10 +2617,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2268,10 +2651,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
-
-        final PublicKey privKey = kf.generatePublic(keySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2280,11 +2660,11 @@
          * distinction made here. It's all keyed off of what kind of key you're
          * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
          */
-        c.init(Cipher.ENCRYPT_MODE, privKey);
+        c.init(Cipher.ENCRYPT_MODE, pubKey);
         byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private);
         assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
 
-        c.init(Cipher.DECRYPT_MODE, privKey);
+        c.init(Cipher.DECRYPT_MODE, pubKey);
         encrypted = c.doFinal(RSA_Vector1_Encrypt_Private);
         assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
     }
@@ -2296,10 +2676,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
-
-        final PublicKey pubKey = kf.generatePublic(keySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2334,10 +2711,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
-
-        final PublicKey privKey = kf.generatePublic(keySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2346,12 +2720,12 @@
          * distinction made here. It's all keyed off of what kind of key you're
          * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
          */
-        c.init(Cipher.ENCRYPT_MODE, privKey);
+        c.init(Cipher.ENCRYPT_MODE, pubKey);
         c.update(RSA_Vector1_Encrypt_Private);
         byte[] encrypted = c.doFinal();
         assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
 
-        c.init(Cipher.DECRYPT_MODE, privKey);
+        c.init(Cipher.DECRYPT_MODE, pubKey);
         c.update(RSA_Vector1_Encrypt_Private);
         encrypted = c.doFinal();
         assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
@@ -2366,10 +2740,7 @@
 
     private void testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success(String provider)
             throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
-
-        final PublicKey privKey = kf.generatePublic(keySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2378,7 +2749,7 @@
          * distinction made here. It's all keyed off of what kind of key you're
          * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
          */
-        c.init(Cipher.ENCRYPT_MODE, privKey);
+        c.init(Cipher.ENCRYPT_MODE, pubKey);
         int i;
         for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) {
             c.update(RSA_Vector1_Encrypt_Private, i, 1);
@@ -2386,7 +2757,7 @@
         byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private, i, RSA_2048_Vector1.length - i);
         assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
 
-        c.init(Cipher.DECRYPT_MODE, privKey);
+        c.init(Cipher.DECRYPT_MODE, pubKey);
         for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) {
             c.update(RSA_Vector1_Encrypt_Private, i, 1);
         }
@@ -2401,10 +2772,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Public_TooSmall_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
-
-        final PublicKey privKey = kf.generatePublic(keySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2413,12 +2781,12 @@
          * distinction made here. It's all keyed off of what kind of key you're
          * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
          */
-        c.init(Cipher.ENCRYPT_MODE, privKey);
+        c.init(Cipher.ENCRYPT_MODE, pubKey);
         byte[] encrypted = c.doFinal(TooShort_Vector);
         assertTrue("Encrypted should match expected",
                 Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted));
 
-        c.init(Cipher.DECRYPT_MODE, privKey);
+        c.init(Cipher.DECRYPT_MODE, pubKey);
         encrypted = c.doFinal(TooShort_Vector);
         assertTrue("Encrypted should match expected",
                 Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted));
@@ -2431,11 +2799,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Private_TooSmall_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2481,11 +2845,7 @@
 
     private void testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure(String provider)
             throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2516,11 +2876,7 @@
 
     private void testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure(String provider)
             throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2552,11 +2908,7 @@
     }
 
     private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
-                RSA_2048_privateExponent);
-
-        final PrivateKey privKey = kf.generatePrivate(keySpec);
+        final PrivateKey privKey = (PrivateKey) getDecryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
 
@@ -2601,10 +2953,7 @@
             }
         }
 
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
-                RSA_2048_publicExponent);
-        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
         c.init(Cipher.ENCRYPT_MODE, pubKey);
         assertEquals(getExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, provider), c.getBlockSize());
     }
@@ -2631,10 +2980,7 @@
     }
 
     private void testRSA_ECB_NoPadding_GetOutputSize_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
-                RSA_2048_publicExponent);
-        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
         c.init(Cipher.ENCRYPT_MODE, pubKey);
@@ -2652,10 +2998,7 @@
     }
 
     private void testRSA_ECB_NoPadding_GetIV_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
-                RSA_2048_publicExponent);
-        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        final PublicKey pubKey = (PublicKey) getEncryptKey("RSA");
 
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
         assertNull("ECB mode has no IV and should be null", c.getIV());
@@ -2672,11 +3015,6 @@
     }
 
     private void testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success(String provider) throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
-                RSA_2048_publicExponent);
-        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
-
         Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
         assertNull("Parameters should be null", c.getParameters());
     }
@@ -2685,85 +3023,77 @@
      * Test vector generation:
      * openssl rand -hex 16 | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] DES_112_KEY = new byte[] {
+    private static final SecretKeySpec DES_112_KEY = new SecretKeySpec(new byte[] {
             (byte) 0x6b, (byte) 0xb3, (byte) 0x85, (byte) 0x1c, (byte) 0x3d, (byte) 0x50,
             (byte) 0xd4, (byte) 0x95, (byte) 0x39, (byte) 0x48, (byte) 0x77, (byte) 0x30,
             (byte) 0x1a, (byte) 0xd7, (byte) 0x86, (byte) 0x57,
-    };
+    }, "DESede");
 
     /*
      * Test vector generation:
      * openssl rand -hex 24 | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] DES_168_KEY = new byte[] {
+    private static final SecretKeySpec DES_168_KEY = new SecretKeySpec(new byte[] {
             (byte) 0xfe, (byte) 0xd4, (byte) 0xd7, (byte) 0xc9, (byte) 0x8a, (byte) 0x13,
             (byte) 0x6a, (byte) 0xa8, (byte) 0x5a, (byte) 0xb8, (byte) 0x19, (byte) 0xb8,
             (byte) 0xcf, (byte) 0x3c, (byte) 0x5f, (byte) 0xe0, (byte) 0xa2, (byte) 0xf7,
             (byte) 0x7b, (byte) 0x65, (byte) 0x43, (byte) 0xc0, (byte) 0xc4, (byte) 0xe1,
-    };
+    }, "DESede");
 
     /*
      * Test vector generation:
      * openssl rand -hex 5 | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] ARC4_40BIT_KEY = new byte[] {
+    private static final SecretKeySpec ARC4_40BIT_KEY = new SecretKeySpec(new byte[] {
             (byte) 0x9c, (byte) 0xc8, (byte) 0xb9, (byte) 0x94, (byte) 0x98,
-    };
+    }, "ARC4");
 
     /*
      * Test vector generation:
      * openssl rand -hex 24 | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] ARC4_128BIT_KEY = new byte[] {
+    private static final SecretKeySpec ARC4_128BIT_KEY = new SecretKeySpec(new byte[] {
             (byte) 0xbc, (byte) 0x0a, (byte) 0x3c, (byte) 0xca, (byte) 0xb5, (byte) 0x42,
             (byte) 0xfa, (byte) 0x5d, (byte) 0x86, (byte) 0x5b, (byte) 0x44, (byte) 0x87,
             (byte) 0x83, (byte) 0xd8, (byte) 0xcb, (byte) 0xd4,
-    };
+    }, "ARC4");
 
     /*
      * Test vector generation:
      * openssl rand -hex 16
      * echo '3d4f8970b1f27537f40a39298a41555f' | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] AES_128_KEY = new byte[] {
+    private static final SecretKeySpec AES_128_KEY = new SecretKeySpec(new byte[] {
             (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2,
             (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29,
             (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f,
-    };
+    }, "AES");
 
     /*
      * Test key generation:
      * openssl rand -hex 24
      * echo '5a7a3d7e40b64ed996f7afa15f97fd595e27db6af428e342' | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] AES_192_KEY = new byte[] {
+    private static final SecretKeySpec AES_192_KEY = new SecretKeySpec(new byte[] {
             (byte) 0x5a, (byte) 0x7a, (byte) 0x3d, (byte) 0x7e, (byte) 0x40, (byte) 0xb6,
             (byte) 0x4e, (byte) 0xd9, (byte) 0x96, (byte) 0xf7, (byte) 0xaf, (byte) 0xa1,
             (byte) 0x5f, (byte) 0x97, (byte) 0xfd, (byte) 0x59, (byte) 0x5e, (byte) 0x27,
             (byte) 0xdb, (byte) 0x6a, (byte) 0xf4, (byte) 0x28, (byte) 0xe3, (byte) 0x42,
-    };
+    }, "AES");
 
     /*
      * Test key generation:
      * openssl rand -hex 32
      * echo 'ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935' | sed 's/\(..\)/(byte) 0x\1, /g'
      */
-    private static final byte[] AES_256_KEY = new byte[] {
+    private static final SecretKeySpec AES_256_KEY = new SecretKeySpec(new byte[] {
             (byte) 0xec, (byte) 0x53, (byte) 0xc6, (byte) 0xd5, (byte) 0x1d, (byte) 0x2c,
             (byte) 0x49, (byte) 0x73, (byte) 0x58, (byte) 0x5f, (byte) 0xb0, (byte) 0xb8,
             (byte) 0xe5, (byte) 0x1c, (byte) 0xd2, (byte) 0xe3, (byte) 0x99, (byte) 0x15,
             (byte) 0xff, (byte) 0x07, (byte) 0xa1, (byte) 0x83, (byte) 0x78, (byte) 0x72,
             (byte) 0x71, (byte) 0x5d, (byte) 0x61, (byte) 0x21, (byte) 0xbf, (byte) 0x86,
             (byte) 0x19, (byte) 0x35,
-    };
-
-    private static final String[] AES_MODES = new String[] {
-            "AES/ECB",
-            "AES/CBC",
-            "AES/CFB",
-            "AES/CTR",
-            "AES/OFB",
-    };
+    }, "AES");
 
     /*
      * Test vector generation:
@@ -2887,11 +3217,11 @@
     /*
      * Taken from BoringSSL test vectors.
      */
-    private static final byte[] AES_128_GCM_TestVector_1_Key = new byte[] {
+    private static final SecretKeySpec AES_128_GCM_TestVector_1_Key = new SecretKeySpec(new byte[] {
             (byte) 0xca, (byte) 0xbd, (byte) 0xcf, (byte) 0x54, (byte) 0x1a, (byte) 0xeb,
             (byte) 0xf9, (byte) 0x17, (byte) 0xba, (byte) 0xc0, (byte) 0x19, (byte) 0xf1,
             (byte) 0x39, (byte) 0x25, (byte) 0xd2, (byte) 0x67,
-    };
+    }, "AES");
 
     /*
      * Taken from BoringSSL test vectors.
@@ -3058,11 +3388,11 @@
     private static class CipherTestParam {
         public final String transformation;
 
-        public final byte[] key;
+        public final AlgorithmParameterSpec spec;
 
-        public final String keyAlgorithm;
+        public final Key encryptKey;
 
-        public final byte[] iv;
+        public final Key decryptKey;
 
         public final byte[] aad;
 
@@ -3074,13 +3404,13 @@
 
         public final boolean isStreamCipher;
 
-        public CipherTestParam(String transformation, String keyAlgorithm, byte[] key, byte[] iv,
-                byte[] aad, byte[] plaintext, byte[] plaintextPadded, byte[] ciphertext,
-                boolean isStreamCipher) {
+        public CipherTestParam(String transformation, AlgorithmParameterSpec spec, Key encryptKey,
+                Key decryptKey, byte[] aad, byte[] plaintext, byte[] plaintextPadded,
+                byte[] ciphertext, boolean isStreamCipher) {
             this.transformation = transformation.toUpperCase(Locale.ROOT);
-            this.keyAlgorithm = keyAlgorithm;
-            this.key = key;
-            this.iv = iv;
+            this.spec = spec;
+            this.encryptKey = encryptKey;
+            this.decryptKey = decryptKey;
             this.aad = aad;
             this.plaintext = plaintext;
             this.plaintextPadded = plaintextPadded;
@@ -3088,20 +3418,34 @@
             this.isStreamCipher = isStreamCipher;
         }
 
-        public CipherTestParam(String transformation, String keyAlgorithm, byte[] key, byte[] iv,
+        public CipherTestParam(String transformation, AlgorithmParameterSpec spec, Key key,
+                byte[] aad, byte[] plaintext, byte[] plaintextPadded, byte[] ciphertext,
+                boolean isStreamCipher) {
+            this(transformation, spec, key, key, aad, plaintext, plaintextPadded, ciphertext,
+                    isStreamCipher);
+        }
+
+        public CipherTestParam(String transformation, AlgorithmParameterSpec spec, Key key,
                 byte[] aad, byte[] plaintext, byte[] plaintextPadded, byte[] ciphertext) {
-            this(transformation, keyAlgorithm, key, iv, aad, plaintext, plaintextPadded, ciphertext,
+            this(transformation, spec, key, aad, plaintext, plaintextPadded, ciphertext,
                     false /* isStreamCipher */);
         }
     }
 
+    private static class OAEPCipherTestParam extends CipherTestParam {
+        public OAEPCipherTestParam(String transformation, OAEPParameterSpec spec,
+                PublicKey encryptKey, PrivateKey decryptKey, byte[] plaintext, byte[] ciphertext) {
+            super(transformation, spec, encryptKey, decryptKey, null, plaintext, plaintext, ciphertext,
+                    false);
+        }
+    }
+
     private static List<CipherTestParam> DES_CIPHER_TEST_PARAMS = new ArrayList<CipherTestParam>();
     static {
         DES_CIPHER_TEST_PARAMS.add(new CipherTestParam(
                 "DESede/CBC/PKCS5Padding",
-                "DESede",
+                new IvParameterSpec(DES_IV1),
                 DES_112_KEY,
-                DES_IV1,
                 null,
                 DES_Plaintext1,
                 DES_Plaintext1_PKCS5_Padded,
@@ -3109,9 +3453,8 @@
                 ));
         DES_CIPHER_TEST_PARAMS.add(new CipherTestParam(
                 "DESede/CBC/PKCS5Padding",
-                "DESede",
+                new IvParameterSpec(DES_IV1),
                 DES_168_KEY,
-                DES_IV1,
                 null,
                 DES_Plaintext1,
                 DES_Plaintext1_PKCS5_Padded,
@@ -3123,9 +3466,8 @@
     static {
         ARC4_CIPHER_TEST_PARAMS.add(new CipherTestParam(
                 "ARC4",
-                "ARC4",
+                null,
                 ARC4_40BIT_KEY,
-                null, // IV,
                 null, // aad
                 ARC4_Plaintext1,
                 null, // padded
@@ -3134,9 +3476,8 @@
         ));
         ARC4_CIPHER_TEST_PARAMS.add(new CipherTestParam(
                 "ARC4",
-                "ARC4",
+                null,
                 ARC4_128BIT_KEY,
-                null, // IV,
                 null, // aad
                 ARC4_Plaintext1,
                 null, // padded
@@ -3147,42 +3488,55 @@
 
     private static List<CipherTestParam> CIPHER_TEST_PARAMS = new ArrayList<CipherTestParam>();
     static {
-        CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/ECB/PKCS5Padding", "AES", AES_128_KEY,
+        CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                "AES/ECB/PKCS5Padding",
                 null,
+                AES_128_KEY,
                 null,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted));
         // PKCS#5 is assumed to be equivalent to PKCS#7 -- same test vectors are thus used for both.
-        CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/ECB/PKCS7Padding", "AES", AES_128_KEY,
+        CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                "AES/ECB/PKCS7Padding",
                 null,
+                AES_128_KEY,
                 null,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded,
                 AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted));
-        CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/GCM/NOPADDING",
-                "AES",
+        CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                "AES/GCM/NOPADDING",
+                new GCMParameterSpec(
+                        (AES_128_GCM_TestVector_1_Encrypted.length -
+                                AES_128_GCM_TestVector_1_Plaintext.length) * 8,
+                        AES_128_GCM_TestVector_1_IV),
                 AES_128_GCM_TestVector_1_Key,
-                AES_128_GCM_TestVector_1_IV,
                 AES_128_GCM_TestVector_1_AAD,
                 AES_128_GCM_TestVector_1_Plaintext,
                 AES_128_GCM_TestVector_1_Plaintext,
                 AES_128_GCM_TestVector_1_Encrypted));
         if (IS_UNLIMITED) {
-            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CTR/NoPadding", "AES", AES_192_KEY,
-                    AES_192_CTR_NoPadding_TestVector_1_IV,
+            CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                    "AES/CTR/NoPadding",
+                    new IvParameterSpec(AES_192_CTR_NoPadding_TestVector_1_IV),
+                    AES_192_KEY,
                     null,
                     AES_192_CTR_NoPadding_TestVector_1_Plaintext,
                     AES_192_CTR_NoPadding_TestVector_1_Plaintext,
                     AES_192_CTR_NoPadding_TestVector_1_Ciphertext));
-            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC/PKCS5Padding", "AES", AES_256_KEY,
-                    AES_256_CBC_PKCS5Padding_TestVector_1_IV,
+            CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                    "AES/CBC/PKCS5Padding",
+                    new IvParameterSpec(AES_256_CBC_PKCS5Padding_TestVector_1_IV),
+                    AES_256_KEY,
                     null,
                     AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext,
                     AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded,
                     AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext));
-            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC/PKCS7Padding", "AES", AES_256_KEY,
-                    AES_256_CBC_PKCS5Padding_TestVector_1_IV,
+            CIPHER_TEST_PARAMS.add(new CipherTestParam(
+                    "AES/CBC/PKCS7Padding",
+                    new IvParameterSpec(AES_256_CBC_PKCS5Padding_TestVector_1_IV),
+                    AES_256_KEY,
                     null,
                     AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext,
                     AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded,
@@ -3190,6 +3544,44 @@
         }
     }
 
+    private static final List<CipherTestParam> RSA_OAEP_CIPHER_TEST_PARAMS = new ArrayList<CipherTestParam>();
+    static {
+        addRsaOaepTest("SHA-1", MGF1ParameterSpec.SHA1, RSA_Vector2_OAEP_SHA1_MGF1_SHA1);
+        addRsaOaepTest("SHA-256", MGF1ParameterSpec.SHA1, RSA_Vector2_OAEP_SHA256_MGF1_SHA1);
+        addRsaOaepTest("SHA-224", MGF1ParameterSpec.SHA224, RSA_Vector2_OAEP_SHA224_MGF1_SHA224);
+        addRsaOaepTest("SHA-256", MGF1ParameterSpec.SHA256, RSA_Vector2_OAEP_SHA256_MGF1_SHA256);
+        addRsaOaepTest("SHA-384", MGF1ParameterSpec.SHA384, RSA_Vector2_OAEP_SHA384_MGF1_SHA384);
+        addRsaOaepTest("SHA-512", MGF1ParameterSpec.SHA512, RSA_Vector2_OAEP_SHA512_MGF1_SHA512);
+    }
+
+    private static void addRsaOaepTest(String digest, MGF1ParameterSpec mgf1Spec, byte[] vector) {
+        if (mgf1Spec.getDigestAlgorithm().equals(digest)) {
+            RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
+                    "RSA/ECB/OAEPWith" + digest + "AndMGF1Padding",
+                    null,
+                    (PublicKey) getEncryptKey("RSA"),
+                    (PrivateKey) getDecryptKey("RSA"),
+                    RSA_Vector2_Plaintext,
+                    vector));
+
+            RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
+                    "RSA/ECB/OAEPWith" + digest + "AndMGF1Padding",
+                    new OAEPParameterSpec(digest, "MGF1", mgf1Spec, PSource.PSpecified.DEFAULT),
+                    (PublicKey) getEncryptKey("RSA"),
+                    (PrivateKey) getDecryptKey("RSA"),
+                    RSA_Vector2_Plaintext,
+                    vector));
+        }
+
+        RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
+                "RSA/ECB/OAEPPadding",
+                new OAEPParameterSpec(digest, "MGF1", mgf1Spec, PSource.PSpecified.DEFAULT),
+                (PublicKey) getEncryptKey("RSA"),
+                (PrivateKey) getDecryptKey("RSA"),
+                RSA_Vector2_Plaintext,
+                vector));
+    }
+
     public void testCipher_Success() throws Exception {
         for (String provider : AES_PROVIDERS) {
             testCipher_Success(provider);
@@ -3199,6 +3591,8 @@
                 DES_CIPHER_TEST_PARAMS);
         testCipher_Success_ForAllSupportingProviders_AtLeastOneProviderRequired(
                 ARC4_CIPHER_TEST_PARAMS);
+        testCipher_Success_ForAllSupportingProviders_AtLeastOneProviderRequired(
+                RSA_OAEP_CIPHER_TEST_PARAMS);
     }
 
     /**
@@ -3211,19 +3605,39 @@
         ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
         PrintStream out = new PrintStream(errBuffer);
         for (CipherTestParam testVector : testVectors) {
-            Provider[] providers = Security.getProviders("Cipher." + testVector.transformation);
-            if ((providers == null) || (providers.length == 0)) {
+            ArrayList<Provider> providers = new ArrayList<>();
+
+            Provider[] providerArray = Security.getProviders("Cipher." + testVector.transformation);
+            if (providerArray != null) {
+                Collections.addAll(providers, providerArray);
+            }
+
+            if (testVector.transformation.indexOf('/') > 0) {
+                Provider[] baseTransformProviderArray = Security.getProviders("Cipher."
+                        + testVector.transformation.substring(
+                                  0, testVector.transformation.indexOf('/')));
+                if (baseTransformProviderArray != null) {
+                    Collections.addAll(providers, baseTransformProviderArray);
+                }
+            }
+
+            if (providers.isEmpty()) {
                 out.append("No providers offer " + testVector.transformation + "\n");
                 continue;
             }
+
             for (Provider provider : providers) {
+                // Do not test AndroidKeyStore's Signature. It needs an AndroidKeyStore-specific key.
+                // It's OKish not to test AndroidKeyStore's Signature here because it's tested
+                // by cts/tests/test/keystore.
+                if (provider.getName().startsWith("AndroidKeyStore")) {
+                    continue;
+                }
+
                 try {
                     checkCipher(testVector, provider.getName());
                 } catch (Throwable e) {
-                    out.append("Error encountered checking " + testVector.transformation
-                            + ", keySize=" + (testVector.key.length * 8) + " with provider "
-                            + provider.getName() + "\n");
-                    e.printStackTrace(out);
+                    logTestFailure(out, provider.getName(), testVector, e);
                 }
             }
         }
@@ -3239,12 +3653,8 @@
         for (CipherTestParam p : CIPHER_TEST_PARAMS) {
             try {
                 checkCipher(p, provider);
-            } catch (Exception e) {
-                out.append("Error encountered checking " + p.transformation + ", keySize="
-                        + (p.key.length * 8)
-                        + " with provider " + provider + "\n");
-
-                e.printStackTrace(out);
+            } catch (Throwable e) {
+                logTestFailure(out, provider, p, e);
             }
         }
         out.flush();
@@ -3253,34 +3663,49 @@
         }
     }
 
-    private void checkCipher(CipherTestParam p, String provider) throws Exception {
-        SecretKey key = new SecretKeySpec(p.key, p.keyAlgorithm);
-        Cipher c = Cipher.getInstance(p.transformation, provider);
+    private void logTestFailure(PrintStream logStream, String provider, CipherTestParam params,
+            Throwable e) {
+        logStream.append("Error encountered checking " + params.transformation);
 
-        AlgorithmParameterSpec spec = null;
-        if (p.iv != null) {
-            if (isAEAD(p.transformation)) {
-                spec = new GCMParameterSpec((p.ciphertext.length - p.plaintext.length) * 8, p.iv);
-            } else {
-                spec = new IvParameterSpec(p.iv);
-            }
+        if (params.encryptKey instanceof SecretKey) {
+            logStream.append(", keySize=" + (params.encryptKey.getEncoded().length * 8));
         }
 
-        c.init(Cipher.ENCRYPT_MODE, key, spec);
+        if (params.spec instanceof OAEPParameterSpec) {
+            OAEPParameterSpec oaepSpec = (OAEPParameterSpec) params.spec;
+            logStream.append(", OAEPSpec{digest=" + oaepSpec.getDigestAlgorithm() + ", mgfAlg="
+                    + oaepSpec.getMGFAlgorithm());
+            if (oaepSpec.getMGFParameters() instanceof MGF1ParameterSpec) {
+                MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec) oaepSpec.getMGFParameters();
+                logStream.append(", mgf1Hash=" + mgf1Spec.getDigestAlgorithm());
+            }
+            logStream.append('}');
+        }
+
+        logStream.append(" with provider " + provider + "\n");
+        e.printStackTrace(logStream);
+    }
+
+    private void checkCipher(CipherTestParam p, String provider) throws Exception {
+        Cipher c = Cipher.getInstance(p.transformation, provider);
+
+        c.init(Cipher.ENCRYPT_MODE, p.encryptKey, p.spec);
 
         if (p.aad != null) {
             c.updateAAD(p.aad);
         }
         final byte[] actualCiphertext = c.doFinal(p.plaintext);
-        assertEquals(p.transformation + " " + provider, Arrays.toString(p.ciphertext),
-                Arrays.toString(actualCiphertext));
+        if (!isRandomizedEncryption(p.transformation)) {
+            assertEquals(p.transformation + " " + provider, Arrays.toString(p.ciphertext),
+                    Arrays.toString(actualCiphertext));
+        }
 
         c = Cipher.getInstance(p.transformation, provider);
-        c.init(Cipher.ENCRYPT_MODE, key, spec);
+        c.init(Cipher.ENCRYPT_MODE, p.encryptKey, p.spec);
         byte[] emptyCipherText = c.doFinal();
         assertNotNull(emptyCipherText);
 
-        c.init(Cipher.DECRYPT_MODE, key, spec);
+        c.init(Cipher.DECRYPT_MODE, p.decryptKey, p.spec);
 
         if (!isAEAD(p.transformation)) {
             try {
@@ -3293,9 +3718,14 @@
         try {
             byte[] emptyPlainText = c.doFinal(emptyCipherText);
             assertEquals(Arrays.toString(new byte[0]), Arrays.toString(emptyPlainText));
-        } catch (AEADBadTagException e) {
+        } catch (AEADBadTagException maybe) {
             if (!"AndroidOpenSSL".equals(provider) || !isAEAD(p.transformation)) {
-                throw e;
+                throw maybe;
+            }
+        } catch (BadPaddingException maybe) {
+            // BC's OAEP has a bug where it doesn't support empty decrypt
+            if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
+                throw maybe;
             }
         }
 
@@ -3323,6 +3753,11 @@
                     if (!isAEAD(p.transformation)) {
                         throw maybe;
                     }
+                } catch (BadPaddingException maybe) {
+                    // BC's OAEP has a bug where it doesn't support empty decrypt
+                    if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
+                        throw maybe;
+                    }
                 }
                 try {
                     c.update(new byte[0]);
@@ -3336,6 +3771,11 @@
                     if (!isAEAD(p.transformation)) {
                         throw maybe;
                     }
+                } catch (BadPaddingException maybe) {
+                    // BC's OAEP has a bug where it doesn't support empty decrypt
+                    if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
+                        throw maybe;
+                    }
                 }
             } else {
                 throw new AssertionError("Define your behavior here for " + provider);
@@ -3343,7 +3783,7 @@
         }
 
         // Cipher might be in unspecified state from failures above.
-        c.init(Cipher.DECRYPT_MODE, key, spec);
+        c.init(Cipher.DECRYPT_MODE, p.decryptKey, p.spec);
 
         // .doFinal(input)
         {
@@ -3392,10 +3832,11 @@
                     Arrays.toString(Arrays.copyOfRange(actualPlaintext, 1, p.plaintext.length + 1)));
         }
 
-        if (!p.isStreamCipher && !p.transformation.endsWith("NOPADDING")) {
+        if (!p.isStreamCipher && !p.transformation.endsWith("NOPADDING")
+                && !isRandomizedEncryption(p.transformation)) {
             Cipher cNoPad = Cipher.getInstance(
                     getCipherTransformationWithNoPadding(p.transformation), provider);
-            cNoPad.init(Cipher.DECRYPT_MODE, key, spec);
+            cNoPad.init(Cipher.DECRYPT_MODE, p.decryptKey, p.spec);
 
             if (p.aad != null) {
                 c.updateAAD(p.aad);
@@ -3414,11 +3855,11 @@
 
             // Wrap it
             c = Cipher.getInstance(p.transformation, provider);
-            c.init(Cipher.WRAP_MODE, key, spec);
+            c.init(Cipher.WRAP_MODE, p.encryptKey, p.spec);
             byte[] cipherText = c.wrap(sk);
 
             // Unwrap it
-            c.init(Cipher.UNWRAP_MODE, key, spec);
+            c.init(Cipher.UNWRAP_MODE, p.decryptKey, p.spec);
             Key decryptedKey = c.unwrap(cipherText, sk.getAlgorithm(), Cipher.SECRET_KEY);
 
             assertEquals(
@@ -3556,10 +3997,7 @@
             try {
                 checkCipher_ShortBlock_Failure(p, provider);
             } catch (Exception e) {
-                out.append("Error encountered checking " + p.transformation + ", keySize="
-                        + (p.key.length * 8)
-                        + " with provider " + provider + "\n");
-                e.printStackTrace(out);
+                logTestFailure(out, provider, p, e);
             }
         }
         out.flush();
@@ -3639,9 +4077,8 @@
     }
 
     public void testCipher_Update_WithZeroLengthInput_ReturnsNull() throws Exception {
-        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
         Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
-        c.init(Cipher.ENCRYPT_MODE, key);
+        c.init(Cipher.ENCRYPT_MODE, AES_128_KEY);
         assertNull(c.update(new byte[0]));
         assertNull(c.update(new byte[c.getBlockSize() * 2], 0, 0));
 
@@ -3713,7 +4150,6 @@
             return;
         }
 
-        SecretKey key = new SecretKeySpec(p.key, "AES");
         Cipher c = Cipher.getInstance(
                 getCipherTransformationWithNoPadding(p.transformation), provider);
         if (c.getBlockSize() == 0) {
@@ -3721,7 +4157,7 @@
         }
 
         if (!p.transformation.endsWith("NOPADDING")) {
-            c.init(Cipher.ENCRYPT_MODE, key);
+            c.init(Cipher.ENCRYPT_MODE, p.encryptKey);
             try {
                 c.doFinal(new byte[] { 0x01, 0x02, 0x03 });
                 fail("Should throw IllegalBlockSizeException on wrong-sized block; transform="
@@ -3761,9 +4197,8 @@
     }
 
     private void testAES_ECB_PKCS5Padding_ShortBuffer_Failure(String provider) throws Exception {
-        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
         Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding", provider);
-        c.init(Cipher.ENCRYPT_MODE, key);
+        c.init(Cipher.ENCRYPT_MODE, AES_128_KEY);
 
         final byte[] fragmentOutput = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext);
         if (fragmentOutput != null) {
@@ -3815,10 +4250,9 @@
     }
 
     private void testAES_ECB_NoPadding_IncrementalUpdate_Success(String provider) throws Exception {
-        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
         Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider);
         assertEquals(provider, c.getProvider().getName());
-        c.init(Cipher.ENCRYPT_MODE, key);
+        c.init(Cipher.ENCRYPT_MODE, AES_128_KEY);
 
         for (int i = 0; i < AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length - 1; i++) {
             final byte[] outputFragment = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded, i, 1);
@@ -3849,12 +4283,11 @@
     }
 
     private void testAES_ECB_NoPadding_IvParameters_Failure(String provider) throws Exception {
-        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
         Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider);
 
         AlgorithmParameterSpec spec = new IvParameterSpec(AES_IV_ZEROES);
         try {
-            c.init(Cipher.ENCRYPT_MODE, key, spec);
+            c.init(Cipher.ENCRYPT_MODE, AES_128_KEY, spec);
             fail("Should not accept an IV in ECB mode; provider=" + provider);
         } catch (InvalidAlgorithmParameterException expected) {
         }
@@ -4122,17 +4555,27 @@
 
         assertEquals(Arrays.toString(c1.doFinal()), Arrays.toString(c2.doFinal()));
 
-        // .doFinal should also reset the state, so check that as well.
+        // .doFinal should also not allow reuse without re-initialization
         byte[] aad2 = new byte[] {
                 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
         };
+        try {
+            c1.updateAAD(aad2);
+            fail("Should not allow updateAAD without re-initialization");
+        } catch (IllegalStateException expected) {
+        }
 
-        Cipher c3 = Cipher.getInstance("AES/GCM/NoPadding");
-        c3.init(Cipher.ENCRYPT_MODE, key, spec);
+        try {
+            c1.update(new byte[8]);
+            fail("Should not allow update without re-initialization");
+        } catch (IllegalStateException expected) {
+        }
 
-        c1.updateAAD(aad2);
-        c3.updateAAD(aad2);
-        assertEquals(Arrays.toString(c1.doFinal()), Arrays.toString(c3.doFinal()));
+        try {
+            c1.doFinal();
+            fail("Should not allow doFinal without re-initialization");
+        } catch (IllegalStateException expected) {
+        }
     }
 
     /**
@@ -4205,9 +4648,8 @@
 
     private static Cipher createAesCipher(int opmode) {
         try {
-            SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
             final Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
-            c.init(opmode, key);
+            c.init(opmode, AES_128_KEY);
             return c;
         } catch (Exception e) {
             fail("Unexpected Exception: " + e.getMessage());
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
index 603baa1..f23c48b 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
@@ -582,6 +582,20 @@
         testContext.close();
     }
 
+    public void test_SSLContext_SSLv3Unsupported() throws Exception {
+        try {
+            SSLContext context = SSLContext.getInstance("SSLv3");
+            fail("SSLv3 should not be supported");
+        } catch (NoSuchAlgorithmException expected) {
+        }
+
+        try {
+            SSLContext context = SSLContext.getInstance("SSL");
+            fail("SSL should not be supported");
+        } catch (NoSuchAlgorithmException expected) {
+        }
+    }
+
     private static void assertContentsInOrder(List<String> expected, String... actual) {
         if (expected.size() != actual.length) {
             fail("Unexpected length. Expected len <" + expected.size()
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index 8990f62..1628260 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -220,8 +220,7 @@
                 assertConnected(pair);
 
                 boolean needsRecordSplit =
-                        ("TLS".equalsIgnoreCase(c.clientContext.getProtocol())
-                                || "SSLv3".equalsIgnoreCase(c.clientContext.getProtocol()))
+                        "TLS".equalsIgnoreCase(c.clientContext.getProtocol())
                                 && cipherSuite.contains("_CBC_");
 
                 assertSendsCorrectly("This is the client. Hello!".getBytes(),
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 5e94b21..d2ad9fd 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -1992,14 +1992,14 @@
         ExecutorService executor = Executors.newFixedThreadPool(2);
         Future<Void> s = executor.submit(new Callable<Void>() {
                 public Void call() throws Exception {
-                    server.setEnabledProtocols(new String[] { "TLSv1", "SSLv3" });
+                    server.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1" });
                     server.startHandshake();
                     return null;
                 }
             });
         Future<Void> c = executor.submit(new Callable<Void>() {
                 public Void call() throws Exception {
-                    client.setEnabledProtocols(new String[] { "SSLv3" });
+                    client.setEnabledProtocols(new String[] { "TLSv1.1" });
                     client.startHandshake();
                     return null;
                 }
@@ -2035,7 +2035,7 @@
         ExecutorService executor = Executors.newFixedThreadPool(2);
         Future<Void> s = executor.submit(new Callable<Void>() {
                 public Void call() throws Exception {
-                    server.setEnabledProtocols(new String[] { "TLSv1", "SSLv3" });
+                    server.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1" });
                     server.setEnabledCipherSuites(serverCipherSuites);
                     try {
                         server.startHandshake();
@@ -2050,7 +2050,7 @@
             });
         Future<Void> c = executor.submit(new Callable<Void>() {
                 public Void call() throws Exception {
-                    client.setEnabledProtocols(new String[] { "SSLv3" });
+                    client.setEnabledProtocols(new String[] { "TLSv1" });
                     client.setEnabledCipherSuites(clientCipherSuites);
                     try {
                         client.startHandshake();
@@ -2219,6 +2219,25 @@
         context.close();
     }
 
+    public void test_SSLSocket_SSLv3Unsupported() throws Exception {
+        TestSSLContext context = TestSSLContext.create();
+
+        final SSLSocket client = (SSLSocket)
+            context.clientContext.getSocketFactory().createSocket();
+
+        try {
+            client.setEnabledProtocols(new String[] {"SSLv3"});
+            fail("SSLSocket should not support SSLv3 protocol");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            client.setEnabledProtocols(new String[] {"SSL"});
+            fail("SSLSocket should not support SSL protocol");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     /**
      * Not run by default by JUnit, but can be run by Vogar by
      * specifying it explicitly (or with main method below)
diff --git a/luni/src/test/java/libcore/sun/invoke/util/VerifyAccessTest.java b/luni/src/test/java/libcore/sun/invoke/util/VerifyAccessTest.java
new file mode 100644
index 0000000..0c02754
--- /dev/null
+++ b/luni/src/test/java/libcore/sun/invoke/util/VerifyAccessTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.sun.invoke.util;
+
+
+import junit.framework.TestCase;
+import sun.invoke.util.VerifyAccess;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Locale;
+import java.util.Vector;
+
+
+public class VerifyAccessTest extends TestCase {
+    public void testIsClassAccessible() {
+        // Always returns false when allowedModes == 0. Note that the "modes" allowed here
+        // are different from the ones used in MethodHandles.
+        assertFalse(VerifyAccess.isClassAccessible(Inner1.class, Inner2.class, 0));
+
+        // Classes in the same package are accessible when Lookup.PACKAGE is specified.
+        assertTrue(VerifyAccess.isClassAccessible(Inner1.class, Inner2.class,
+                MethodHandles.Lookup.PACKAGE));
+        assertTrue(VerifyAccess.isClassAccessible(Inner1.class, Sibling.class,
+                MethodHandles.Lookup.PACKAGE));
+
+        // Public classes are always accessible.
+        assertTrue(VerifyAccess.isClassAccessible(String.class, Inner1.class,
+                MethodHandles.Lookup.PACKAGE));
+    }
+
+    public static class Inner1 {
+    }
+
+    public static class Inner2 {
+    }
+
+    public void testIsSamePackageMember() {
+        assertTrue(VerifyAccess.isSamePackageMember(Inner1.class, Inner2.class));
+        assertTrue(VerifyAccess.isSamePackageMember(Inner1.class, VerifyAccessTest.class));
+
+        assertFalse(VerifyAccess.isSamePackageMember(Sibling.class, Inner1.class));
+    }
+
+    public void testIsSamePackage() {
+        // Both classes are in package java.util.
+        assertTrue(VerifyAccess.isSamePackage(Vector.class, List.class));
+        // Make sure this works for inner classes.
+        assertTrue(VerifyAccess.isSamePackage(Vector.class, Locale.Builder.class));
+        // Differing packages: java.lang vs java.util.
+        assertFalse(VerifyAccess.isSamePackage(Vector.class, String.class));
+
+        try {
+            VerifyAccess.isSamePackage(String[].class, List.class);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+}
+
+class Sibling {
+}
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherOutputStream1Test.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherOutputStream1Test.java
index 359ac66..5c88e71 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherOutputStream1Test.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherOutputStream1Test.java
@@ -23,20 +23,27 @@
 package org.apache.harmony.crypto.tests.javax.crypto;
 
 import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.Arrays;
 
+import javax.crypto.BadPaddingException;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.KeyGenerator;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.NullCipher;
 import javax.crypto.CipherOutputStream;
 import javax.crypto.Cipher;
+import javax.crypto.ShortBufferException;
 
 import junit.framework.TestCase;
 
@@ -205,5 +212,121 @@
 
         assertNotNull(cos);
     }
+
+    private static class CipherSpiThatThrowsOnSecondDoFinal extends CipherSpi {
+
+        private boolean wasDoFinalCalled = false;
+
+        @Override
+        protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+
+        }
+
+        @Override
+        protected void engineSetPadding(String padding) throws NoSuchPaddingException {
+
+        }
+
+        @Override
+        protected int engineGetBlockSize() {
+            return 0;
+        }
+
+        @Override
+        protected int engineGetOutputSize(int inputLen) {
+            return 0;
+        }
+
+        @Override
+        protected byte[] engineGetIV() {
+            return new byte[0];
+        }
+
+        @Override
+        protected AlgorithmParameters engineGetParameters() {
+            return null;
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, SecureRandom random)
+                throws InvalidKeyException {
+
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                SecureRandom random)
+                throws InvalidKeyException, InvalidAlgorithmParameterException {
+
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                SecureRandom random)
+                throws InvalidKeyException, InvalidAlgorithmParameterException {
+
+        }
+
+        @Override
+        protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+            return new byte[0];
+        }
+
+        @Override
+        protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
+                int outputOffset) throws ShortBufferException {
+            return 0;
+        }
+
+        @Override
+        protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
+                throws IllegalBlockSizeException, BadPaddingException {
+            // Just call the other overriding for engineDoFinal.
+            try {
+                engineDoFinal(input, inputOffset, inputLen, new byte[10], 0);
+            } catch (ShortBufferException e) {
+                throw new RuntimeException(e);
+            }
+            return new byte[0];
+        }
+
+        @Override
+        protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
+                int outputOffset)
+                throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+            if (wasDoFinalCalled) {
+                throw new UnsupportedOperationException(
+                        "doFinal not supposed to be called two times");
+            }
+            wasDoFinalCalled = true;
+            return 0;
+        }
+    };
+
+
+    public void test_close_doubleCloseDoesntCallDoFinal() throws Exception {
+        CipherSpi cipherSpiThatThrowsOnSecondDoFinal = new CipherSpiThatThrowsOnSecondDoFinal();
+        Cipher cipherThatThrowsOnSecondDoFinal = new Cipher(
+                cipherSpiThatThrowsOnSecondDoFinal,
+                Security.getProviders()[0],
+                "SomeTransformation") {
+        };
+
+        TestOutputStream testOutputStream = new TestOutputStream();
+        CipherOutputStream cipherOutputStream = new CipherOutputStream(
+                testOutputStream, cipherThatThrowsOnSecondDoFinal);
+
+        cipherThatThrowsOnSecondDoFinal.init(Cipher.ENCRYPT_MODE, (Key) null);
+
+        cipherOutputStream.close();
+        // Should just check that it's already closed and return, without calling doFinal, thus
+        // throwing any exception
+        cipherOutputStream.close();
+
+        // Check that the spi didn't change, as it might be changed dynamically by the Cipher
+        // methods.
+        assertEquals(cipherSpiThatThrowsOnSecondDoFinal,
+                cipherThatThrowsOnSecondDoFinal.getCurrentSpi());
+    }
 }
 
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/luni/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
index d90c8ec..2fc09c6 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
@@ -594,6 +594,67 @@
                        Arrays.equals(digestResult, expected));
     }
 
+    private class MessageDigestWithUnsupportedUpdate extends MessageDigest {
+        private MessageDigestWithUnsupportedUpdate() {
+            super("SomeAlgorithm");
+        }
+
+        @Override
+        protected void engineUpdate(byte input) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        protected void engineUpdate(byte[] input, int offset, int len) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        protected byte[] engineDigest() {
+            return new byte[0];
+        }
+
+        @Override
+        protected void engineReset() {
+
+        }
+    }
+
+    public void test_write_writeToUnderlyingStreamBeforeUpdatingDigest() {
+        MessageDigest messageDigestWithUnsupportedUpdate = new MessageDigestWithUnsupportedUpdate();
+        OutputStream outputStreamThatThrowsIOException = new OutputStream() {
+            @Override
+            public void write(int b) throws IOException {
+                throw new IOException();
+            }
+        };
+
+        DigestOutputStream digestOutputStream = new DigestOutputStream(
+                outputStreamThatThrowsIOException, messageDigestWithUnsupportedUpdate);
+
+        // Writing throws an IOException (and not an UnsupportedOperationException) meaning than
+        // it tried to write to the underlying stream before updating the digest.
+        digestOutputStream.on(true);
+        try {
+            digestOutputStream.write(3);
+            fail();
+        } catch (IOException expected) {
+        }
+
+        digestOutputStream.on(true);
+        try {
+            digestOutputStream.write(new byte[10], 0, 10);
+            fail();
+        } catch (IOException expected) {
+        }
+
+        digestOutputStream.on(true);
+        try {
+            digestOutputStream.write(new byte[10]);
+            fail();
+        } catch (IOException expected) {
+        }
+    }
 
     private class MyOutputStream extends OutputStream {
         @Override
diff --git a/luni/src/test/resources/libcore/java/lang/reflect/parameter/metadata_variations.dex b/luni/src/test/resources/libcore/java/lang/reflect/parameter/metadata_variations.dex
new file mode 100644
index 0000000..2cade45
--- /dev/null
+++ b/luni/src/test/resources/libcore/java/lang/reflect/parameter/metadata_variations.dex
Binary files differ
diff --git a/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex b/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex
new file mode 100644
index 0000000..ad7a53d
--- /dev/null
+++ b/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex
Binary files differ
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index 9a3ef03..81f78b9 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -32,6 +32,7 @@
   dalvik/src/main/java/dalvik/annotation/InnerClass.java \
   dalvik/src/main/java/dalvik/annotation/KnownFailure.java \
   dalvik/src/main/java/dalvik/annotation/MemberClasses.java \
+  dalvik/src/main/java/dalvik/annotation/MethodParameters.java \
   dalvik/src/main/java/dalvik/annotation/Signature.java \
   dalvik/src/main/java/dalvik/annotation/TestTarget.java \
   dalvik/src/main/java/dalvik/annotation/TestTargetClass.java \
@@ -66,7 +67,6 @@
   luni/src/main/java/java/lang/FindBugsSuppressWarnings.java \
   libart/src/main/java/java/lang/VMClassLoader.java \
   luni/src/main/java/java/lang/ref/FinalizerReference.java \
-  libart/src/main/java/java/lang/reflect/AbstractMethod.java \
   luni/src/main/java/java/math/BigDecimal.java \
   luni/src/main/java/java/math/BigInt.java \
   luni/src/main/java/java/math/BigInteger.java \
@@ -378,6 +378,7 @@
   luni/src/main/java/libcore/io/EventLogger.java \
   luni/src/main/java/libcore/io/ForwardingOs.java \
   luni/src/main/java/libcore/io/IoBridge.java \
+  luni/src/main/java/libcore/io/IoTracker.java \
   luni/src/main/java/libcore/io/IoUtils.java \
   luni/src/main/java/libcore/io/Libcore.java \
   luni/src/main/java/libcore/io/Memory.java \
diff --git a/ojluni/src/main/java/java/io/BufferedInputStream.java b/ojluni/src/main/java/java/io/BufferedInputStream.java
index fcc7e70..e39c20c 100644
--- a/ojluni/src/main/java/java/io/BufferedInputStream.java
+++ b/ojluni/src/main/java/java/io/BufferedInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, 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
@@ -50,7 +50,17 @@
 public
 class BufferedInputStream extends FilterInputStream {
 
-    private static int defaultBufferSize = 8192;
+    // Android-changed: made final
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /**
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    // Android-changed: made final
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
 
     /**
      * The internal buffer array where the data is stored. When necessary,
@@ -172,7 +182,7 @@
      * @param   in   the underlying input stream.
      */
     public BufferedInputStream(InputStream in) {
-        this(in, defaultBufferSize);
+        this(in, DEFAULT_BUFFER_SIZE);
     }
 
     /**
@@ -185,7 +195,7 @@
      *
      * @param   in     the underlying input stream.
      * @param   size   the buffer size.
-     * @exception IllegalArgumentException if size <= 0.
+     * @exception IllegalArgumentException if {@code size <= 0}.
      */
     public BufferedInputStream(InputStream in, int size) {
         super(in);
@@ -215,8 +225,11 @@
             } else if (buffer.length >= marklimit) {
                 markpos = -1;   /* buffer got too big, invalidate mark */
                 pos = 0;        /* drop buffer contents */
+            } else if (buffer.length >= MAX_BUFFER_SIZE) {
+                throw new OutOfMemoryError("Required array size too large");
             } else {            /* grow buffer */
-                int nsz = pos * 2;
+                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
+                        pos * 2 : MAX_BUFFER_SIZE;
                 if (nsz > marklimit)
                     nsz = marklimit;
                 byte nbuf[] = new byte[nsz];
diff --git a/ojluni/src/main/java/java/io/BufferedReader.java b/ojluni/src/main/java/java/io/BufferedReader.java
index 5a45f4b..d00209e 100644
--- a/ojluni/src/main/java/java/io/BufferedReader.java
+++ b/ojluni/src/main/java/java/io/BufferedReader.java
@@ -96,7 +96,7 @@
      * @param  in   A Reader
      * @param  sz   Input-buffer size
      *
-     * @exception  IllegalArgumentException  If sz is <= 0
+     * @exception  IllegalArgumentException  If {@code sz <= 0}
      */
     public BufferedReader(Reader in, int sz) {
         super(in);
@@ -495,7 +495,7 @@
      *                         whose size is no smaller than limit.
      *                         Therefore large values should be used with care.
      *
-     * @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 {
@@ -532,9 +532,12 @@
         synchronized (lock) {
             if (in == null)
                 return;
-            in.close();
-            in = null;
-            cb = null;
+            try {
+                in.close();
+            } finally {
+                in = null;
+                cb = null;
+            }
         }
     }
 
diff --git a/ojluni/src/main/java/java/io/BufferedWriter.java b/ojluni/src/main/java/java/io/BufferedWriter.java
index 220a47e..a5d810a 100644
--- a/ojluni/src/main/java/java/io/BufferedWriter.java
+++ b/ojluni/src/main/java/java/io/BufferedWriter.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
@@ -95,7 +95,7 @@
      * @param  out  A Writer
      * @param  sz   Output-buffer size, a positive integer
      *
-     * @exception  IllegalArgumentException  If sz is <= 0
+     * @exception  IllegalArgumentException  If {@code sz <= 0}
      */
     public BufferedWriter(Writer out, int sz) {
         super(out);
@@ -255,15 +255,15 @@
         }
     }
 
+    @SuppressWarnings("try")
     public void close() throws IOException {
         synchronized (lock) {
             if (out == null) {
                 return;
             }
-            try {
+            try (Writer w = out) {
                 flushBuffer();
             } finally {
-                out.close();
                 out = null;
                 cb = null;
             }
diff --git a/ojluni/src/main/java/java/io/ByteArrayInputStream.java b/ojluni/src/main/java/java/io/ByteArrayInputStream.java
index e58c6e6..d07f074 100644
--- a/ojluni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/ojluni/src/main/java/java/io/ByteArrayInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, 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
@@ -275,7 +275,6 @@
      * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
      * this class can be called after the stream has been closed without
      * generating an <tt>IOException</tt>.
-     * <p>
      */
     public void close() throws IOException {
     }
diff --git a/ojluni/src/main/java/java/io/ByteArrayOutputStream.java b/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
index c4df675..f1d429b 100644
--- a/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, 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
@@ -94,6 +94,14 @@
     }
 
     /**
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+    /**
      * Increases the capacity to ensure that it can hold at least the
      * number of elements specified by the minimum capacity argument.
      *
@@ -105,14 +113,19 @@
         int newCapacity = oldCapacity << 1;
         if (newCapacity - minCapacity < 0)
             newCapacity = minCapacity;
-        if (newCapacity < 0) {
-            if (minCapacity < 0) // overflow
-                throw new OutOfMemoryError();
-            newCapacity = Integer.MAX_VALUE;
-        }
+        if (newCapacity - MAX_ARRAY_SIZE > 0)
+            newCapacity = hugeCapacity(minCapacity);
         buf = Arrays.copyOf(buf, newCapacity);
     }
 
+    private static int hugeCapacity(int minCapacity) {
+        if (minCapacity < 0) // overflow
+            throw new OutOfMemoryError();
+        return (minCapacity > MAX_ARRAY_SIZE) ?
+            Integer.MAX_VALUE :
+            MAX_ARRAY_SIZE;
+    }
+
     /**
      * Writes the specified byte to this byte array output stream.
      *
@@ -210,21 +223,21 @@
 
     /**
      * Converts the buffer's contents into a string by decoding the bytes using
-     * the specified {@link java.nio.charset.Charset charsetName}. The length of
-     * the new <tt>String</tt> is a function of the charset, and hence may not be
-     * equal to the length of the byte array.
+     * the named {@link java.nio.charset.Charset charset}. The length of the new
+     * <tt>String</tt> is a function of the charset, and hence may not be equal
+     * to the length of the byte array.
      *
      * <p> This method always replaces malformed-input and unmappable-character
      * sequences with this charset's default replacement string. The {@link
      * java.nio.charset.CharsetDecoder} class should be used when more control
      * over the decoding process is required.
      *
-     * @param  charsetName  the name of a supported
-     *              {@linkplain java.nio.charset.Charset </code>charset<code>}
-     * @return String decoded from the buffer's contents.
+     * @param      charsetName  the name of a supported
+     *             {@link java.nio.charset.Charset charset}
+     * @return     String decoded from the buffer's contents.
      * @exception  UnsupportedEncodingException
      *             If the named charset is not supported
-     * @since   JDK1.1
+     * @since      JDK1.1
      */
     public synchronized String toString(String charsetName)
         throws UnsupportedEncodingException
@@ -263,8 +276,6 @@
      * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
      * this class can be called after the stream has been closed without
      * generating an <tt>IOException</tt>.
-     * <p>
-     *
      */
     public void close() throws IOException {
     }
diff --git a/ojluni/src/main/java/java/io/Closeable.java b/ojluni/src/main/java/java/io/Closeable.java
index 7f3cc8d..b4a1c81 100644
--- a/ojluni/src/main/java/java/io/Closeable.java
+++ b/ojluni/src/main/java/java/io/Closeable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,6 @@
  *
  * @since 1.5
  */
-
 public interface Closeable extends AutoCloseable {
 
     /**
@@ -42,6 +41,12 @@
      * with it. If the stream is already closed then invoking this
      * method has no effect.
      *
+     * <p> As noted in {@link AutoCloseable#close()}, cases where the
+     * close may fail require careful attention. It is strongly advised
+     * to relinquish the underlying resources and to internally
+     * <em>mark</em> the {@code Closeable} as closed, prior to throwing
+     * the {@code IOException}.
+     *
      * @throws IOException if an I/O error occurs
      */
     public void close() throws IOException;
diff --git a/ojluni/src/main/java/java/io/Console.java b/ojluni/src/main/java/java/io/Console.java
index 4eca41c..3cab03e 100644
--- a/ojluni/src/main/java/java/io/Console.java
+++ b/ojluni/src/main/java/java/io/Console.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,7 @@
  * manually zero the returned character array after processing to minimize the
  * lifetime of sensitive data in memory.
  *
- * <blockquote><pre>
+ * <blockquote><pre>{@code
  * Console cons;
  * char[] passwd;
  * if ((cons = System.console()) != null &&
@@ -84,7 +84,7 @@
  *     ...
  *     java.util.Arrays.fill(passwd, ' ');
  * }
- * </pre></blockquote>
+ * }</pre></blockquote>
  *
  * @author  Xueming Shen
  * @since   1.6
@@ -125,9 +125,11 @@
     * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)}
     * on the returned object will not read in characters beyond the line
     * bound for each invocation, even if the destination buffer has space for
-    * more characters. A line bound is considered to be any one of a line feed
-    * (<tt>'\n'</tt>), a carriage return (<tt>'\r'</tt>), a carriage return
-    * followed immediately by a linefeed, or an end of stream.
+    * more characters. The {@code Reader}'s {@code read} methods may block if a
+    * line bound has not been entered or reached on the console's input device.
+    * A line bound is considered to be any one of a line feed (<tt>'\n'</tt>),
+    * a carriage return (<tt>'\r'</tt>), a carriage return followed immediately
+    * by a linefeed, or an end of stream.
     *
     * @return  The reader associated with this console
     */
diff --git a/ojluni/src/main/java/java/io/DataOutput.java b/ojluni/src/main/java/java/io/DataOutput.java
index 07fbc3a..c6692a6 100644
--- a/ojluni/src/main/java/java/io/DataOutput.java
+++ b/ojluni/src/main/java/java/io/DataOutput.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -134,11 +134,11 @@
      * Writes two bytes to the output
      * stream to represent the value of the argument.
      * The byte values to be written, in the  order
-     * shown, are: <p>
-     * <pre><code>
-     * (byte)(0xff &amp; (v &gt;&gt; 8))
-     * (byte)(0xff &amp; v)
-     * </code> </pre> <p>
+     * shown, are:
+     * <pre>{@code
+     * (byte)(0xff & (v >> 8))
+     * (byte)(0xff & v)
+     * }</pre> <p>
      * The bytes written by this method may be
      * read by the <code>readShort</code> method
      * of interface <code>DataInput</code> , which
@@ -156,10 +156,10 @@
      * output stream.
      * The byte values to be written, in the  order
      * shown, are:
-     * <p><pre><code>
-     * (byte)(0xff &amp; (v &gt;&gt; 8))
-     * (byte)(0xff &amp; v)
-     * </code></pre><p>
+     * <pre>{@code
+     * (byte)(0xff & (v >> 8))
+     * (byte)(0xff & v)
+     * }</pre><p>
      * The bytes written by this method may be
      * read by the <code>readChar</code> method
      * of interface <code>DataInput</code> , which
@@ -176,12 +176,12 @@
      * comprised of four bytes, to the output stream.
      * The byte values to be written, in the  order
      * shown, are:
-     * <p><pre><code>
-     * (byte)(0xff &amp; (v &gt;&gt; 24))
-     * (byte)(0xff &amp; (v &gt;&gt; 16))
-     * (byte)(0xff &amp; (v &gt;&gt; &#32; &#32;8))
-     * (byte)(0xff &amp; v)
-     * </code></pre><p>
+     * <pre>{@code
+     * (byte)(0xff & (v >> 24))
+     * (byte)(0xff & (v >> 16))
+     * (byte)(0xff & (v >>  8))
+     * (byte)(0xff & v)
+     * }</pre><p>
      * The bytes written by this method may be read
      * by the <code>readInt</code> method of interface
      * <code>DataInput</code> , which will then
@@ -197,16 +197,16 @@
      * comprised of eight bytes, to the output stream.
      * The byte values to be written, in the  order
      * shown, are:
-     * <p><pre><code>
-     * (byte)(0xff &amp; (v &gt;&gt; 56))
-     * (byte)(0xff &amp; (v &gt;&gt; 48))
-     * (byte)(0xff &amp; (v &gt;&gt; 40))
-     * (byte)(0xff &amp; (v &gt;&gt; 32))
-     * (byte)(0xff &amp; (v &gt;&gt; 24))
-     * (byte)(0xff &amp; (v &gt;&gt; 16))
-     * (byte)(0xff &amp; (v &gt;&gt;  8))
-     * (byte)(0xff &amp; v)
-     * </code></pre><p>
+     * <pre>{@code
+     * (byte)(0xff & (v >> 56))
+     * (byte)(0xff & (v >> 48))
+     * (byte)(0xff & (v >> 40))
+     * (byte)(0xff & (v >> 32))
+     * (byte)(0xff & (v >> 24))
+     * (byte)(0xff & (v >> 16))
+     * (byte)(0xff & (v >>  8))
+     * (byte)(0xff & v)
+     * }</pre><p>
      * The bytes written by this method may be
      * read by the <code>readLong</code> method
      * of interface <code>DataInput</code> , which
@@ -314,24 +314,24 @@
      * If a character <code>c</code>
      * is in the range <code>&#92;u0001</code> through
      * <code>&#92;u007f</code>, it is represented
-     * by one byte:<p>
+     * by one byte:
      * <pre>(byte)c </pre>  <p>
      * If a character <code>c</code> is <code>&#92;u0000</code>
      * or is in the range <code>&#92;u0080</code>
      * through <code>&#92;u07ff</code>, then it is
      * represented by two bytes, to be written
-     * in the order shown:<p> <pre><code>
-     * (byte)(0xc0 | (0x1f &amp; (c &gt;&gt; 6)))
-     * (byte)(0x80 | (0x3f &amp; c))
-     *  </code></pre>  <p> If a character
+     * in the order shown: <pre>{@code
+     * (byte)(0xc0 | (0x1f & (c >> 6)))
+     * (byte)(0x80 | (0x3f & c))
+     * }</pre> <p> If a character
      * <code>c</code> is in the range <code>&#92;u0800</code>
      * through <code>uffff</code>, then it is
      * represented by three bytes, to be written
-     * in the order shown:<p> <pre><code>
-     * (byte)(0xe0 | (0x0f &amp; (c &gt;&gt; 12)))
-     * (byte)(0x80 | (0x3f &amp; (c &gt;&gt;  6)))
-     * (byte)(0x80 | (0x3f &amp; c))
-     *  </code></pre>  <p> First,
+     * in the order shown: <pre>{@code
+     * (byte)(0xe0 | (0x0f & (c >> 12)))
+     * (byte)(0x80 | (0x3f & (c >>  6)))
+     * (byte)(0x80 | (0x3f & c))
+     * }</pre>  <p> First,
      * the total number of bytes needed to represent
      * all the characters of <code>s</code> is
      * calculated. If this number is larger than
diff --git a/ojluni/src/main/native/FileSystem_md.c b/ojluni/src/main/java/java/io/DefaultFileSystem.java
similarity index 63%
rename from ojluni/src/main/native/FileSystem_md.c
rename to ojluni/src/main/java/java/io/DefaultFileSystem.java
index 33a3652..8e8cf08 100644
--- a/ojluni/src/main/native/FileSystem_md.c
+++ b/ojluni/src/main/java/java/io/DefaultFileSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,24 +23,18 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jni_util.h"
-#include "JNIHelp.h"
+package java.io;
 
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
+/**
+ *
+ * @since 1.8
+ */
+class DefaultFileSystem {
 
-JNIEXPORT jobject JNICALL
-FileSystem_getFileSystem(JNIEnv *env, jclass ignored)
-{
-    return JNU_NewObjectByName(env, "java/io/UnixFileSystem", "()V");
-}
-
-
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(FileSystem, getFileSystem, "()Ljava/io/FileSystem;"),
-};
-
-void register_java_io_FileSystem(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "java/io/FileSystem", gMethods, NELEM(gMethods));
+    /**
+     * Return the FileSystem object for Unix-based platform.
+     */
+    public static FileSystem getFileSystem() {
+        return new UnixFileSystem();
+    }
 }
diff --git a/ojluni/src/main/java/java/io/EOFException.java b/ojluni/src/main/java/java/io/EOFException.java
index ed6ca0f..536669f 100644
--- a/ojluni/src/main/java/java/io/EOFException.java
+++ b/ojluni/src/main/java/java/io/EOFException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, 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
@@ -32,7 +32,6 @@
  * This exception is mainly used by data input streams to signal end of
  * stream. Note that many other input operations return a special value on
  * end of stream rather than throwing an exception.
- * <p>
  *
  * @author  Frank Yellin
  * @see     java.io.DataInputStream
diff --git a/ojluni/src/main/java/java/io/ExpiringCache.java b/ojluni/src/main/java/java/io/ExpiringCache.java
index 8c07afb..02fd222 100644
--- a/ojluni/src/main/java/java/io/ExpiringCache.java
+++ b/ojluni/src/main/java/java/io/ExpiringCache.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -35,7 +35,7 @@
 
 class ExpiringCache {
     private long millisUntilExpiration;
-    private Map  map;
+    private Map<String,Entry> map;
     // Clear out old entries every few queries
     private int queryCount;
     private int queryOverflow = 300;
@@ -61,9 +61,11 @@
         this(30000);
     }
 
+    @SuppressWarnings("serial")
     ExpiringCache(long millisUntilExpiration) {
         this.millisUntilExpiration = millisUntilExpiration;
-        map = new LinkedHashMap() {
+        map = new LinkedHashMap<String,Entry>() {
+            @Override
             protected boolean removeEldestEntry(Map.Entry eldest) {
               return size() > MAX_ENTRIES;
             }
@@ -99,7 +101,7 @@
     }
 
     private Entry entryFor(String key) {
-        Entry entry = (Entry) map.get(key);
+        Entry entry = map.get(key);
         if (entry != null) {
             long delta = System.currentTimeMillis() - entry.timestamp();
             if (delta < 0 || delta >= millisUntilExpiration) {
@@ -111,12 +113,11 @@
     }
 
     private void cleanup() {
-        Set keySet = map.keySet();
+        Set<String> keySet = map.keySet();
         // Avoid ConcurrentModificationExceptions
         String[] keys = new String[keySet.size()];
         int i = 0;
-        for (Iterator iter = keySet.iterator(); iter.hasNext(); ) {
-            String key = (String) iter.next();
+        for (String key: keySet) {
             keys[i++] = key;
         }
         for (int j = 0; j < keys.length; j++) {
diff --git a/ojluni/src/main/java/java/io/File.java b/ojluni/src/main/java/java/io/File.java
index 0b152cc..01e41f1 100644
--- a/ojluni/src/main/java/java/io/File.java
+++ b/ojluni/src/main/java/java/io/File.java
@@ -32,8 +32,10 @@
 import java.net.URISyntaxException;
 import java.util.List;
 import java.util.ArrayList;
+import java.security.AccessController;
 import java.nio.file.Path;
 import java.nio.file.FileSystems;
+import sun.security.action.GetPropertyAction;
 
 /**
  * An abstract representation of file and directory pathnames.
@@ -127,7 +129,7 @@
  * created, the abstract pathname represented by a <code>File</code> object
  * will never change.
  *
- * <h4>Interoperability with {@code java.nio.file} package</h4>
+ * <h3>Interoperability with {@code java.nio.file} package</h3>
  *
  * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
  * package defines interfaces and classes for the Java virtual machine to access
@@ -156,7 +158,7 @@
     /**
      * The FileSystem object representing the platform's local file system.
      */
-    static private final FileSystem fs = FileSystem.getFileSystem();
+    private static final FileSystem fs = DefaultFileSystem.getFileSystem();
 
     /**
      * This abstract pathname's normalized pathname string. A normalized
@@ -165,7 +167,7 @@
      *
      * @serial
      */
-    private String path;
+    private final String path;
 
     /**
      * Enum type that indicates the status of a file path.
@@ -197,7 +199,7 @@
      * The length of this abstract pathname's prefix, or zero if it has no
      * prefix.
      */
-    private transient int prefixLength;
+    private final transient int prefixLength;
 
     /**
      * Returns the length of this abstract pathname's prefix.
@@ -728,6 +730,8 @@
 
     /* -- Attribute accessors -- */
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Tests whether the application can read the file denoted by this
      * abstract pathname.
@@ -752,6 +756,8 @@
         return fs.checkAccess(this, FileSystem.ACCESS_READ);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Tests whether the application can modify the file denoted by this
      * abstract pathname.
@@ -1434,11 +1440,13 @@
         return fs.setLastModifiedTime(this, time);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Marks the file or directory named by this abstract pathname so that
-     * only read operations are allowed.  After invoking this method the file
-     * or directory is guaranteed not to change until it is either deleted or
-     * marked to allow write access.  Whether or not a read-only file or
+     * only read operations are allowed. After invoking this method the file
+     * or directory will not change until it is either deleted or marked
+     * to allow write access. Whether or not a read-only file or
      * directory may be deleted depends upon the underlying system.
      *
      * @return <code>true</code> if and only if the operation succeeded;
@@ -1462,6 +1470,8 @@
         return fs.setReadOnly(this);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Sets the owner's or everybody's write permission for this abstract
      * pathname.
@@ -1503,6 +1513,8 @@
         return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * A convenience method to set the owner's write permission for this abstract
      * pathname.
@@ -1532,6 +1544,8 @@
         return setWritable(writable, true);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Sets the owner's or everybody's read permission for this abstract
      * pathname.
@@ -1576,6 +1590,8 @@
         return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * A convenience method to set the owner's read permission for this abstract
      * pathname.
@@ -1608,6 +1624,8 @@
         return setReadable(readable, true);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Sets the owner's or everybody's execute permission for this abstract
      * pathname.
@@ -1652,9 +1670,11 @@
         return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
-     * A convenience method to set the owner's execute permission for this abstract
-     * pathname.
+     * A convenience method to set the owner's execute permission for this
+     * abstract pathname.
      *
      * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
      * behaves in exactly the same way as the invocation
@@ -1670,7 +1690,7 @@
      *           operation will fail if the user does not have permission to
      *           change the access permissions of this abstract pathname.  If
      *           <code>executable</code> is <code>false</code> and the underlying
-     *           file system does not implement an excute permission, then the
+     *           file system does not implement an execute permission, then the
      *           operation will fail.
      *
      * @throws  SecurityException
@@ -1684,6 +1704,8 @@
         return setExecutable(executable, true);
     }
 
+    // Android-changed. Removed javadoc comment about special privileges
+    // that doesn't make sense on android
     /**
      * Tests whether the application can execute the file denoted by this
      * abstract pathname.
@@ -1836,24 +1858,45 @@
     }
 
     /* -- Temporary files -- */
+    private static class TempDirectory {
+        private TempDirectory() { }
 
-    // file name generation
-    private static File generateTempFile(String prefix, String suffix, File dir)
+        // Android-changed: Don't cache java.io.tmpdir value
+        // temporary directory location
+        // private static final File tmpdir = new File(AccessController
+        //     .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+        // static File location() {
+        //     return tmpdir;
+        // }
+
+        // file name generation
+        static File generateFile(String prefix, String suffix, File dir)
             throws IOException
-    {
-        // Android-changed: Use Math.randomIntInternal. This (pseudo) random number
-        // is initialized post-fork
-        int n = Math.randomIntInternal();
-        if (n == Integer.MIN_VALUE) {
-            n = 0;      // corner case
-        } else {
-            n = Math.abs(n);
+        {
+            // Android-changed: Use Math.randomIntInternal. This (pseudo) random number
+            // is initialized post-fork
+
+            long n = Math.randomLongInternal();
+            if (n == Long.MIN_VALUE) {
+                n = 0;      // corner case
+            } else {
+                n = Math.abs(n);
+            }
+
+            // Android changed: Reject invalid file prefixes
+            // Use only the file name from the supplied prefix
+            //prefix = (new File(prefix)).getName();
+
+            String name = prefix + Long.toString(n) + suffix;
+            File f = new File(dir, name);
+            if (!name.equals(f.getName()) || f.isInvalid()) {
+                if (System.getSecurityManager() != null)
+                    throw new IOException("Unable to create temporary file");
+                else
+                    throw new IOException("Unable to create temporary file, " + f);
+            }
+            return f;
         }
-        String name = prefix + Integer.toString(n) + suffix;
-        File f = new File(dir, name);
-        if (!name.equals(f.getName()))
-            throw new IOException("Unable to create temporary file");
-        return f;
     }
 
     /**
@@ -1934,21 +1977,30 @@
         if (suffix == null)
             suffix = ".tmp";
 
+
         File tmpdir = (directory != null) ? directory
                                           : new File(System.getProperty("java.io.tmpdir", "."));
+        //SecurityManager sm = System.getSecurityManager();
         File f;
-        try {
-            do {
-                f = generateTempFile(prefix, suffix, tmpdir);
-            } while (f.exists());
-            if (!f.createNewFile())
-                throw new IOException("Unable to create temporary file");
-        } catch (SecurityException se) {
-            // don't reveal temporary directory location
-            if (directory == null)
-                throw new SecurityException("Unable to create temporary file");
-            throw se;
-        }
+        do {
+            f = TempDirectory.generateFile(prefix, suffix, tmpdir);
+
+            // Android change: sm is always null on android
+            // if (sm != null) {
+            //     try {
+            //         sm.checkWrite(f.getPath());
+            //     } catch (SecurityException se) {
+            //         // don't reveal temporary directory location
+            //         if (directory == null)
+            //             throw new SecurityException("Unable to create temporary file");
+            //         throw se;
+            //     }
+            // }
+        } while ((fs.getBooleanAttributes(f) & FileSystem.BA_EXISTS) != 0);
+
+        if (!fs.createFileExclusively(f.getPath()))
+            throw new IOException("Unable to create temporary file");
+
         return f;
     }
 
@@ -2078,7 +2130,7 @@
         throws IOException
     {
         s.defaultWriteObject();
-        s.writeChar(this.separatorChar); // Add the separator character
+        s.writeChar(separatorChar); // Add the separator character
     }
 
     /**
@@ -2095,10 +2147,28 @@
         char sep = s.readChar(); // read the previous separator char
         if (sep != separatorChar)
             pathField = pathField.replace(sep, separatorChar);
-        this.path = fs.normalize(pathField);
-        this.prefixLength = fs.prefixLength(this.path);
+        String path = fs.normalize(pathField);
+        UNSAFE.putObject(this, PATH_OFFSET, path);
+        UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));
     }
 
+    private static final long PATH_OFFSET;
+    private static final long PREFIX_LENGTH_OFFSET;
+    private static final sun.misc.Unsafe UNSAFE;
+    static {
+        try {
+            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            PATH_OFFSET = unsafe.objectFieldOffset(
+                    File.class.getDeclaredField("path"));
+            PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
+                    File.class.getDeclaredField("prefixLength"));
+            UNSAFE = unsafe;
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+    }
+
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = 301077366599181567L;
 
diff --git a/ojluni/src/main/java/java/io/FileDescriptor.java b/ojluni/src/main/java/java/io/FileDescriptor.java
index fb2f43e..7c82505 100644
--- a/ojluni/src/main/java/java/io/FileDescriptor.java
+++ b/ojluni/src/main/java/java/io/FileDescriptor.java
@@ -46,6 +46,8 @@
  * @see     java.io.FileOutputStream
  * @since   JDK1.0
  */
+// Android-changed: Removed parent reference counting. Creator is responsible for closing
+// the file descriptor.
 public final class FileDescriptor {
 
     private int descriptor;
diff --git a/ojluni/src/main/java/java/io/FileFilter.java b/ojluni/src/main/java/java/io/FileFilter.java
index 15f00d6..f973d77 100644
--- a/ojluni/src/main/java/java/io/FileFilter.java
+++ b/ojluni/src/main/java/java/io/FileFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
  *
  * @since 1.2
  */
+@FunctionalInterface
 public interface FileFilter {
 
     /**
@@ -46,5 +47,4 @@
      *          should be included
      */
     boolean accept(File pathname);
-
 }
diff --git a/ojluni/src/main/java/java/io/FileInputStream.java b/ojluni/src/main/java/java/io/FileInputStream.java
old mode 100644
new mode 100755
index 9191f28..a286aaa
--- a/ojluni/src/main/java/java/io/FileInputStream.java
+++ b/ojluni/src/main/java/java/io/FileInputStream.java
@@ -31,8 +31,8 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.nio.ch.FileChannelImpl;
-import sun.misc.IoTrace;
 import libcore.io.IoBridge;
+import libcore.io.IoTracker;
 
 
 /**
@@ -57,7 +57,10 @@
     /* File Descriptor - handle to the open file */
     private final FileDescriptor fd;
 
-    /* The path of the referenced file (null if the stream is created with a file descriptor) */
+    /**
+     * The path of the referenced file
+     * (null if the stream is created with a file descriptor)
+     */
     private final String path;
 
     private FileChannel channel = null;
@@ -67,6 +70,7 @@
     private final boolean isFdOwner;
 
     private final CloseGuard guard = CloseGuard.get();
+    private final IoTracker tracker = new IoTracker();
 
     /**
      * Creates a <code>FileInputStream</code> by
@@ -185,7 +189,16 @@
      * Opens the specified file for reading.
      * @param name the name of the file
      */
-    private native void open(String name) throws FileNotFoundException;
+    private native void open0(String name) throws FileNotFoundException;
+
+    // wrap native call to allow instrumentation
+    /**
+     * Opens the specified file for reading.
+     * @param name the name of the file
+     */
+    private void open(String name) throws FileNotFoundException {
+        open0(name);
+    }
 
     /**
      * Reads a byte of data from this input stream. This method blocks
@@ -196,16 +209,8 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public int read() throws IOException {
-        Object traceContext = IoTrace.fileReadBegin(path);
-
         byte[] b = new byte[1];
-        int res = -1;
-        try {
-            res = read(b, 0, 1);
-        } finally {
-            IoTrace.fileReadEnd(traceContext, res);
-        }
-        return (res != -1) ? b[0] & 0xff : -1;
+        return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
     }
 
     /**
@@ -245,15 +250,8 @@
         if (closed && len > 0) {
             throw new IOException("Stream Closed");
         }
-
-        Object traceContext = IoTrace.fileReadBegin(path);
-        int bytesRead = 0;
-        try {
-            bytesRead = IoBridge.read(fd, b, off, len);
-        } finally {
-            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
-        }
-        return bytesRead;
+        tracker.trackIo(len);
+        return IoBridge.read(fd, b, off, len);
     }
 
     /**
@@ -262,13 +260,15 @@
      *
      * <p>The <code>skip</code> method may, for a variety of
      * reasons, end up skipping over some smaller number of bytes,
-     * possibly <code>0</code>. If <code>n</code> is negative, an
-     * <code>IOException</code> is thrown, even though the <code>skip</code>
-     * method of the {@link InputStream} superclass does nothing in this case.
-     * The actual number of bytes skipped is returned.
+     * possibly <code>0</code>. If <code>n</code> is negative, the method
+     * will try to skip backwards. In case the backing file does not support
+     * backward skip at its current position, an <code>IOException</code> is
+     * thrown. The actual number of bytes skipped is returned. If it skips
+     * forwards, it returns a positive value. If it skips backwards, it
+     * returns a negative value.
      *
-     * <p>This method may skip more bytes than are remaining in the backing
-     * file. This produces no exception and the number of bytes skipped
+     * <p>This method may skip more bytes than what are remaining in the
+     * backing file. This produces no exception and the number of bytes skipped
      * may include some number of bytes that were beyond the EOF of the
      * backing file. Attempting to read from the stream after skipping past
      * the end will result in -1 indicating the end of the file.
@@ -302,9 +302,10 @@
     /**
      * Returns an estimate of the number of remaining bytes that can be read (or
      * skipped over) from this input stream without blocking by the next
-     * invocation of a method for this input stream. The next invocation might be
-     * the same thread or another thread.  A single read or skip of this
-     * many bytes will not block, but may read or skip fewer bytes.
+     * invocation of a method for this input stream. Returns 0 when the file
+     * position is beyond EOF. The next invocation might be the same thread
+     * or another thread. A single read or skip of this many bytes will not
+     * block, but may read or skip fewer bytes.
      *
      * <p> In some cases, a non-blocking read (or skip) may appear to be
      * blocked when it is merely slow, for example when reading large
@@ -372,7 +373,9 @@
      * @see        java.io.FileDescriptor
      */
     public final FileDescriptor getFD() throws IOException {
-        if (fd != null) return fd;
+        if (fd != null) {
+            return fd;
+        }
         throw new IOException();
     }
 
@@ -381,7 +384,7 @@
      * object associated with this file input stream.
      *
      * <p> The initial {@link java.nio.channels.FileChannel#position()
-     * </code>position<code>} of the returned channel will be equal to the
+     * position} of the returned channel will be equal to the
      * number of bytes read from the file so far.  Reading bytes from this
      * stream will increment the channel's position.  Changing the channel's
      * position, either explicitly or by reading, will change this stream's
diff --git a/ojluni/src/main/java/java/io/FileOutputStream.java b/ojluni/src/main/java/java/io/FileOutputStream.java
old mode 100644
new mode 100755
index 9691c24..249e337
--- a/ojluni/src/main/java/java/io/FileOutputStream.java
+++ b/ojluni/src/main/java/java/io/FileOutputStream.java
@@ -31,8 +31,8 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.nio.ch.FileChannelImpl;
-import sun.misc.IoTrace;
 import libcore.io.IoBridge;
+import libcore.io.IoTracker;
 
 /**
  * A file output stream is an output stream for writing data to a
@@ -63,25 +63,27 @@
     private final FileDescriptor fd;
 
     /**
-     * The path of the referenced file (null if the stream is created with a file descriptor)
-     */
-    private final String path;
-
-    /**
      * True if the file is opened for append.
      */
     private final boolean append;
 
     /**
-     * The associated channel, initalized lazily.
+     * The associated channel, initialized lazily.
      */
     private FileChannel channel;
 
     private final Object closeLock = new Object();
     private volatile boolean closed = false;
 
+    /**
+     * The path of the referenced file
+     * (null if the stream is created with a file descriptor)
+     */
+    private final String path;
+
     private final CloseGuard guard = CloseGuard.get();
     private final boolean isFdOwner;
+    private final IoTracker tracker = new IoTracker();
 
     /**
      * Creates a file output stream to write to the file with the
@@ -271,9 +273,20 @@
      * @param name name of file to be opened
      * @param append whether the file is to be opened in append mode
      */
-    private native void open(String name, boolean append)
+    private native void open0(String name, boolean append)
         throws FileNotFoundException;
 
+    // wrap native call to allow instrumentation
+    /**
+     * Opens a file, with the specified name, for overwriting or appending.
+     * @param name name of file to be opened
+     * @param append whether the file is to be opened in append mode
+     */
+    private void open(String name, boolean append)
+        throws FileNotFoundException {
+        open0(name, append);
+    }
+
     /**
      * Writes the specified byte to this file output stream. Implements
      * the <code>write</code> method of <code>OutputStream</code>.
@@ -309,15 +322,8 @@
         if (closed && len > 0) {
             throw new IOException("Stream Closed");
         }
-
-        Object traceContext = IoTrace.fileWriteBegin(path);
-        int bytesWritten = 0;
-        try {
-            IoBridge.write(fd, b, off, len);
-            bytesWritten = len;
-        } finally {
-            IoTrace.fileWriteEnd(traceContext, bytesWritten);
-        }
+        tracker.trackIo(len);
+        IoBridge.write(fd, b, off, len);
     }
 
     /**
@@ -369,16 +375,18 @@
      * @see        java.io.FileDescriptor
      */
      public final FileDescriptor getFD()  throws IOException {
-        if (fd != null) return fd;
+        if (fd != null) {
+            return fd;
+        }
         throw new IOException();
      }
 
     /**
      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
-     * object associated with this file output stream. </p>
+     * object associated with this file output stream.
      *
      * <p> The initial {@link java.nio.channels.FileChannel#position()
-     * </code>position<code>} of the returned channel will be equal to the
+     * position} of the returned channel will be equal to the
      * number of bytes written to the file so far unless this stream is in
      * append mode, in which case it will be equal to the size of the file.
      * Writing bytes to this stream will increment the channel's position
diff --git a/ojluni/src/main/java/java/io/FilePermission.java b/ojluni/src/main/java/java/io/FilePermission.java
index 21b0a1e..814a695 100644
--- a/ojluni/src/main/java/java/io/FilePermission.java
+++ b/ojluni/src/main/java/java/io/FilePermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,5 @@
     public FilePermission(String path, String actions) { super(""); }
 
     public boolean implies(Permission p) { return true; }
-
     public String getActions() { return null; }
 }
diff --git a/ojluni/src/main/java/java/io/FileSystem.java b/ojluni/src/main/java/java/io/FileSystem.java
index aa00fa9..4b0260d 100644
--- a/ojluni/src/main/java/java/io/FileSystem.java
+++ b/ojluni/src/main/java/java/io/FileSystem.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 package java.io;
 
+import java.lang.annotation.Native;
 
 /**
  * Package-private abstract class for the local filesystem abstraction.
@@ -33,13 +34,6 @@
 
 abstract class FileSystem {
 
-    /**
-     * Return the FileSystem object representing this platform's local
-     * filesystem.
-     */
-    public static native FileSystem getFileSystem();
-
-
     /* -- Normalization and construction -- */
 
     /**
@@ -106,10 +100,10 @@
     /* -- Attribute accessors -- */
 
     /* Constants for simple boolean attributes */
-    public static final int BA_EXISTS    = 0x01;
-    public static final int BA_REGULAR   = 0x02;
-    public static final int BA_DIRECTORY = 0x04;
-    public static final int BA_HIDDEN    = 0x08;
+    @Native public static final int BA_EXISTS    = 0x01;
+    @Native public static final int BA_REGULAR   = 0x02;
+    @Native public static final int BA_DIRECTORY = 0x04;
+    @Native public static final int BA_HIDDEN    = 0x08;
 
     /**
      * Return the simple boolean attributes for the file or directory denoted
@@ -118,9 +112,9 @@
      */
     public abstract int getBooleanAttributes(File f);
 
-    public static final int ACCESS_READ    = 0x04;
-    public static final int ACCESS_WRITE   = 0x02;
-    public static final int ACCESS_EXECUTE = 0x01;
+    @Native public static final int ACCESS_READ    = 0x04;
+    @Native public static final int ACCESS_WRITE   = 0x02;
+    @Native public static final int ACCESS_EXECUTE = 0x01;
     public static final int ACCESS_OK      = 0x08;
 
     /**
@@ -212,9 +206,9 @@
     public abstract File[] listRoots();
 
     /* -- Disk usage -- */
-    public static final int SPACE_TOTAL  = 0;
-    public static final int SPACE_FREE   = 1;
-    public static final int SPACE_USABLE = 2;
+    @Native public static final int SPACE_TOTAL  = 0;
+    @Native public static final int SPACE_FREE   = 1;
+    @Native public static final int SPACE_USABLE = 2;
 
     public abstract long getSpace(File f, int t);
 
diff --git a/ojluni/src/main/java/java/io/FilenameFilter.java b/ojluni/src/main/java/java/io/FilenameFilter.java
index 915adf5..71b88af 100644
--- a/ojluni/src/main/java/java/io/FilenameFilter.java
+++ b/ojluni/src/main/java/java/io/FilenameFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 1998, 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
@@ -39,8 +39,8 @@
  * @see     java.io.File#list(java.io.FilenameFilter)
  * @since   JDK1.0
  */
-public
-interface FilenameFilter {
+@FunctionalInterface
+public interface FilenameFilter {
     /**
      * Tests if a specified file should be included in a file list.
      *
diff --git a/ojluni/src/main/java/java/io/FilterOutputStream.java b/ojluni/src/main/java/java/io/FilterOutputStream.java
index 6de18f0..209e63b 100644
--- a/ojluni/src/main/java/java/io/FilterOutputStream.java
+++ b/ojluni/src/main/java/java/io/FilterOutputStream.java
@@ -152,11 +152,10 @@
      * @see        java.io.FilterOutputStream#flush()
      * @see        java.io.FilterOutputStream#out
      */
+    @SuppressWarnings("try")
     public void close() throws IOException {
-        try {
-          flush();
-        } catch (IOException ignored) {
+        try (OutputStream ostream = out) {
+            flush();
         }
-        out.close();
     }
 }
diff --git a/ojluni/src/main/java/java/io/Flushable.java b/ojluni/src/main/java/java/io/Flushable.java
index e598ea8..fe90fbd 100644
--- a/ojluni/src/main/java/java/io/Flushable.java
+++ b/ojluni/src/main/java/java/io/Flushable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,6 @@
  *
  * @since 1.5
  */
-
 public interface Flushable {
 
     /**
diff --git a/ojluni/src/main/java/java/io/InputStream.java b/ojluni/src/main/java/java/io/InputStream.java
index 63d31d5..6c46a40 100644
--- a/ojluni/src/main/java/java/io/InputStream.java
+++ b/ojluni/src/main/java/java/io/InputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2006, 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
@@ -193,8 +193,10 @@
      * up skipping over some smaller number of bytes, possibly <code>0</code>.
      * This may result from any of a number of conditions; reaching end of file
      * before <code>n</code> bytes have been skipped is only one possibility.
-     * The actual number of bytes skipped is returned.  If <code>n</code> is
-     * negative, no bytes are skipped.
+     * The actual number of bytes skipped is returned. If {@code n} is
+     * negative, the {@code skip} method for class {@code InputStream} always
+     * returns 0, and no bytes are skipped. Subclasses may handle the negative
+     * value differently.
      *
      * <p> The <code>skip</code> method of this class creates a
      * byte array and then repeatedly reads into it until <code>n</code> bytes
@@ -304,8 +306,7 @@
      *
      * <p> The general contract of <code>reset</code> is:
      *
-     * <p><ul>
-     *
+     * <ul>
      * <li> If the method <code>markSupported</code> returns
      * <code>true</code>, then:
      *
diff --git a/ojluni/src/main/java/java/io/InputStreamReader.java b/ojluni/src/main/java/java/io/InputStreamReader.java
index 2cda0ce..e131dca 100644
--- a/ojluni/src/main/java/java/io/InputStreamReader.java
+++ b/ojluni/src/main/java/java/io/InputStreamReader.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
@@ -33,7 +33,7 @@
 /**
  * An InputStreamReader is a bridge from byte streams to character streams: It
  * reads bytes and decodes them into characters using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}.  The charset that it uses
+ * java.nio.charset.Charset charset}.  The charset that it uses
  * may be specified by name or may be given explicitly, or the platform's
  * default charset may be accepted.
  *
@@ -86,7 +86,7 @@
      *
      * @param  charsetName
      *         The name of a supported
-     *         {@link java.nio.charset.Charset </code>charset<code>}
+     *         {@link java.nio.charset.Charset charset}
      *
      * @exception  UnsupportedEncodingException
      *             If the named charset is not supported
@@ -101,7 +101,7 @@
     }
 
     /**
-     * Creates an InputStreamReader that uses the given charset. </p>
+     * Creates an InputStreamReader that uses the given charset.
      *
      * @param  in       An InputStream
      * @param  cs       A charset
@@ -117,7 +117,7 @@
     }
 
     /**
-     * Creates an InputStreamReader that uses the given charset decoder.  </p>
+     * Creates an InputStreamReader that uses the given charset decoder.
      *
      * @param  in       An InputStream
      * @param  dec      A charset decoder
diff --git a/ojluni/src/main/java/java/io/LineNumberInputStream.java b/ojluni/src/main/java/java/io/LineNumberInputStream.java
index d3b5d9b..1f37a98 100644
--- a/ojluni/src/main/java/java/io/LineNumberInputStream.java
+++ b/ojluni/src/main/java/java/io/LineNumberInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2004, 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
@@ -30,13 +30,13 @@
  * functionality of keeping track of the current line number.
  * <p>
  * A line is a sequence of bytes ending with a carriage return
- * character (<code>'&#92;r'</code>), a newline character
- * (<code>'&#92;n'</code>), or a carriage return character followed
+ * character ({@code '\u005Cr'}), a newline character
+ * ({@code '\u005Cn'}), or a carriage return character followed
  * immediately by a linefeed character. In all three cases, the line
  * terminating character(s) are returned as a single newline character.
  * <p>
- * The line number begins at <code>0</code>, and is incremented by
- * <code>1</code> when a <code>read</code> returns a newline character.
+ * The line number begins at {@code 0}, and is incremented by
+ * {@code 1} when a {@code read} returns a newline character.
  *
  * @author     Arthur van Hoff
  * @see        java.io.LineNumberReader
@@ -66,27 +66,28 @@
 
     /**
      * Reads the next byte of data from this input stream. The value
-     * byte is returned as an <code>int</code> in the range
-     * <code>0</code> to <code>255</code>. If no byte is available
+     * byte is returned as an {@code int} in the range
+     * {@code 0} to {@code 255}. If no byte is available
      * because the end of the stream has been reached, the value
-     * <code>-1</code> is returned. This method blocks until input data
+     * {@code -1} is returned. This method blocks until input data
      * is available, the end of the stream is detected, or an exception
      * is thrown.
      * <p>
-     * The <code>read</code> method of
-     * <code>LineNumberInputStream</code> calls the <code>read</code>
+     * The {@code read} method of
+     * {@code LineNumberInputStream} calls the {@code read}
      * method of the underlying input stream. It checks for carriage
      * returns and newline characters in the input, and modifies the
      * current line number as appropriate. A carriage-return character or
      * a carriage return followed by a newline character are both
      * converted into a single newline character.
      *
-     * @return     the next byte of data, or <code>-1</code> if the end of this
+     * @return     the next byte of data, or {@code -1} if the end of this
      *             stream is reached.
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.FilterInputStream#in
      * @see        java.io.LineNumberInputStream#getLineNumber()
      */
+    @SuppressWarnings("fallthrough")
     public int read() throws IOException {
         int c = pushBack;
 
@@ -110,18 +111,18 @@
     }
 
     /**
-     * Reads up to <code>len</code> bytes of data from this input stream
+     * Reads up to {@code len} bytes of data from this input stream
      * into an array of bytes. This method blocks until some input is available.
      * <p>
-     * The <code>read</code> method of
-     * <code>LineNumberInputStream</code> repeatedly calls the
-     * <code>read</code> method of zero arguments to fill in the byte array.
+     * The {@code read} method of
+     * {@code LineNumberInputStream} repeatedly calls the
+     * {@code read} method of zero arguments to fill in the byte array.
      *
      * @param      b     the buffer into which the data is read.
      * @param      off   the start offset of the data.
      * @param      len   the maximum number of bytes read.
      * @return     the total number of bytes read into the buffer, or
-     *             <code>-1</code> if there is no more data because the end of
+     *             {@code -1} if there is no more data because the end of
      *             this stream has been reached.
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.LineNumberInputStream#read()
@@ -159,15 +160,15 @@
     }
 
     /**
-     * Skips over and discards <code>n</code> bytes of data from this
-     * input stream. The <code>skip</code> method may, for a variety of
+     * Skips over and discards {@code n} bytes of data from this
+     * input stream. The {@code skip} method may, for a variety of
      * reasons, end up skipping over some smaller number of bytes,
-     * possibly <code>0</code>. The actual number of bytes skipped is
-     * returned.  If <code>n</code> is negative, no bytes are skipped.
+     * possibly {@code 0}. The actual number of bytes skipped is
+     * returned.  If {@code n} is negative, no bytes are skipped.
      * <p>
-     * The <code>skip</code> method of <code>LineNumberInputStream</code> creates
+     * The {@code skip} method of {@code LineNumberInputStream} creates
      * a byte array and then repeatedly reads into it until
-     * <code>n</code> bytes have been read or the end of the stream has
+     * {@code n} bytes have been read or the end of the stream has
      * been reached.
      *
      * @param      n   the number of bytes to be skipped.
@@ -224,12 +225,12 @@
      * <p>
      * Note that if the underlying input stream is able to supply
      * <i>k</i> input characters without blocking, the
-     * <code>LineNumberInputStream</code> can guarantee only to provide
+     * {@code LineNumberInputStream} can guarantee only to provide
      * <i>k</i>/2 characters without blocking, because the
      * <i>k</i> characters from the underlying input stream might
-     * consist of <i>k</i>/2 pairs of <code>'&#92;r'</code> and
-     * <code>'&#92;n'</code>, which are converted to just
-     * <i>k</i>/2 <code>'&#92;n'</code> characters.
+     * consist of <i>k</i>/2 pairs of {@code '\u005Cr'} and
+     * {@code '\u005Cn'}, which are converted to just
+     * <i>k</i>/2 {@code '\u005Cn'} characters.
      *
      * @return     the number of bytes that can be read from this input stream
      *             without blocking.
@@ -242,12 +243,12 @@
 
     /**
      * Marks the current position in this input stream. A subsequent
-     * call to the <code>reset</code> method repositions this stream at
+     * call to the {@code reset} method repositions this stream at
      * the last marked position so that subsequent reads re-read the same bytes.
      * <p>
-     * The <code>mark</code> method of
-     * <code>LineNumberInputStream</code> remembers the current line
-     * number in a private variable, and then calls the <code>mark</code>
+     * The {@code mark} method of
+     * {@code LineNumberInputStream} remembers the current line
+     * number in a private variable, and then calls the {@code mark}
      * method of the underlying input stream.
      *
      * @param   readlimit   the maximum limit of bytes that can be read before
@@ -263,12 +264,12 @@
 
     /**
      * Repositions this stream to the position at the time the
-     * <code>mark</code> method was last called on this input stream.
+     * {@code mark} method was last called on this input stream.
      * <p>
-     * The <code>reset</code> method of
-     * <code>LineNumberInputStream</code> resets the line number to be
-     * the line number at the time the <code>mark</code> method was
-     * called, and then calls the <code>reset</code> method of the
+     * The {@code reset} method of
+     * {@code LineNumberInputStream} resets the line number to be
+     * the line number at the time the {@code mark} method was
+     * called, and then calls the {@code reset} method of the
      * underlying input stream.
      * <p>
      * Stream marks are intended to be used in
diff --git a/ojluni/src/main/java/java/io/LineNumberReader.java b/ojluni/src/main/java/java/io/LineNumberReader.java
index 31f1e87..29884fd 100644
--- a/ojluni/src/main/java/java/io/LineNumberReader.java
+++ b/ojluni/src/main/java/java/io/LineNumberReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, 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
@@ -120,6 +120,7 @@
      * @throws  IOException
      *          If an I/O error occurs
      */
+    @SuppressWarnings("fallthrough")
     public int read() throws IOException {
         synchronized (lock) {
             int c = super.read();
@@ -159,6 +160,7 @@
      * @throws  IOException
      *          If an I/O error occurs
      */
+    @SuppressWarnings("fallthrough")
     public int read(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
             int n = super.read(cbuf, off, len);
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 419d095..0d66339 100644
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2010, 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
@@ -111,7 +111,7 @@
  *
  * <p>Serializable classes that require special handling during the
  * serialization and deserialization process should implement the following
- * methods:<p>
+ * methods:
  *
  * <pre>
  * private void writeObject(java.io.ObjectOutputStream stream)
@@ -316,6 +316,7 @@
      * @throws  SecurityException if a security manager exists and its
      *          <code>checkPermission</code> method denies enabling
      *          subclassing.
+     * @throws  IOException if an I/O error occurs while creating this stream
      * @see SecurityManager#checkPermission
      * @see java.io.SerializablePermission
      */
@@ -493,11 +494,12 @@
     public void defaultReadObject()
         throws IOException, ClassNotFoundException
     {
-        if (curContext == null) {
+        SerialCallbackContext ctx = curContext;
+        if (ctx == null) {
             throw new NotActiveException("not in call to readObject");
         }
-        Object curObj = curContext.getObj();
-        ObjectStreamClass curDesc = curContext.getDesc();
+        Object curObj = ctx.getObj();
+        ObjectStreamClass curDesc = ctx.getDesc();
         bin.setBlockDataMode(false);
         defaultReadFields(curObj, curDesc);
         bin.setBlockDataMode(true);
@@ -531,11 +533,12 @@
     public ObjectInputStream.GetField readFields()
         throws IOException, ClassNotFoundException
     {
-        if (curContext == null) {
+        SerialCallbackContext ctx = curContext;
+        if (ctx == null) {
             throw new NotActiveException("not in call to readObject");
         }
-        Object curObj = curContext.getObj();
-        ObjectStreamClass curDesc = curContext.getDesc();
+        Object curObj = ctx.getObj();
+        ObjectStreamClass curDesc = ctx.getDesc();
         bin.setBlockDataMode(false);
         GetFieldImpl getField = new GetFieldImpl(curDesc);
         getField.readFields();
@@ -693,9 +696,9 @@
         boolean hasNonPublicInterface = false;
 
         // define proxy in class loader of non-public interface(s), if any
-        Class[] classObjs = new Class[interfaces.length];
+        Class<?>[] classObjs = new Class<?>[interfaces.length];
         for (int i = 0; i < interfaces.length; i++) {
-            Class cl = Class.forName(interfaces[i], false, latestLoader);
+            Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
             if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
                 if (hasNonPublicInterface) {
                     if (nonPublicLoader != cl.getClassLoader()) {
@@ -1233,7 +1236,7 @@
      * "enableSubclassImplementation" SerializablePermission is checked.
      */
     private void verifySubclass() {
-        Class cl = getClass();
+        Class<?> cl = getClass();
         if (cl == ObjectInputStream.class) {
             return;
         }
@@ -1477,12 +1480,12 @@
      * ClassNotFoundException will be associated with the class' handle in the
      * handle table).
      */
-    private Class readClass(boolean unshared) throws IOException {
+    private Class<?> readClass(boolean unshared) throws IOException {
         if (bin.readByte() != TC_CLASS) {
             throw new InternalError();
         }
         ObjectStreamClass desc = readClassDesc(false);
-        Class cl = desc.forClass();
+        Class<?> cl = desc.forClass();
         passHandle = handles.assign(unshared ? unsharedMarker : cl);
 
         ClassNotFoundException resolveEx = desc.getResolveException();
@@ -1552,7 +1555,7 @@
             ifaces[i] = bin.readUTF();
         }
 
-        Class cl = null;
+        Class<?> cl = null;
         ClassNotFoundException resolveEx = null;
         bin.setBlockDataMode(true);
         try {
@@ -1605,7 +1608,7 @@
                 "failed to read class descriptor").initCause(ex);
         }
 
-        Class cl = null;
+        Class<?> cl = null;
         ClassNotFoundException resolveEx = null;
         bin.setBlockDataMode(true);
         final boolean checksRequired = isCustomSubclass();
@@ -1665,7 +1668,7 @@
         int len = bin.readInt();
 
         Object array = null;
-        Class cl, ccl = null;
+        Class<?> cl, ccl = null;
         if ((cl = desc.forClass()) != null) {
             ccl = cl.getComponentType();
             array = Array.newInstance(ccl, len);
@@ -1718,7 +1721,7 @@
      * Reads in and returns enum constant, or null if enum type is
      * unresolvable.  Sets passHandle to enum constant's assigned handle.
      */
-    private Enum readEnum(boolean unshared) throws IOException {
+    private Enum<?> readEnum(boolean unshared) throws IOException {
         if (bin.readByte() != TC_ENUM) {
             throw new InternalError();
         }
@@ -1735,24 +1738,26 @@
         }
 
         String name = readString(false);
-        Enum en = null;
-        Class cl = desc.forClass();
+        Enum<?> result = null;
+        Class<?> cl = desc.forClass();
         if (cl != null) {
             try {
-                en = Enum.valueOf(cl, name);
+                @SuppressWarnings("unchecked")
+                Enum<?> en = Enum.valueOf((Class)cl, name);
+                result = en;
             } catch (IllegalArgumentException ex) {
                 throw (IOException) new InvalidObjectException(
                     "enum constant " + name + " does not exist in " +
                     cl).initCause(ex);
             }
             if (!unshared) {
-                handles.setObject(enumHandle, en);
+                handles.setObject(enumHandle, result);
             }
         }
 
         handles.finish(enumHandle);
         passHandle = enumHandle;
-        return en;
+        return result;
     }
 
     /**
@@ -1879,7 +1884,6 @@
         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() &&
@@ -1968,8 +1972,7 @@
     private void defaultReadFields(Object obj, ObjectStreamClass desc)
         throws IOException
     {
-        // REMIND: is isInstance check necessary?
-        Class cl = desc.forClass();
+        Class<?> cl = desc.forClass();
         if (cl != null && obj != null && !cl.isInstance(obj)) {
             throw new ClassCastException();
         }
@@ -2172,7 +2175,7 @@
          * class descriptor, returns -1.  Throws IllegalArgumentException if
          * neither incoming nor local class descriptor contains a match.
          */
-        private int getFieldOffset(String name, Class type) {
+        private int getFieldOffset(String name, Class<?> type) {
             ObjectStreamField field = desc.getField(name, type);
             if (field != null) {
                 return field.getOffset();
@@ -2870,6 +2873,7 @@
             return readUTFBody(readUnsignedShort());
         }
 
+        @SuppressWarnings("deprecation")
         public String readLine() throws IOException {
             return din.readLine();      // deprecated, not worth optimizing
         }
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index f2abe23..5de2175 100644
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2010, 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
@@ -264,6 +264,7 @@
      * @throws  SecurityException if a security manager exists and its
      *          <code>checkPermission</code> method denies enabling
      *          subclassing.
+     * @throws  IOException if an I/O error occurs while creating this stream
      * @see SecurityManager#checkPermission
      * @see java.io.SerializablePermission
      */
@@ -445,11 +446,12 @@
      *          <code>OutputStream</code>
      */
     public void defaultWriteObject() throws IOException {
-        if ( curContext == null ) {
+        SerialCallbackContext ctx = curContext;
+        if (ctx == null) {
             throw new NotActiveException("not in call to writeObject");
         }
-        Object curObj = curContext.getObj();
-        ObjectStreamClass curDesc = curContext.getDesc();
+        Object curObj = ctx.getObj();
+        ObjectStreamClass curDesc = ctx.getDesc();
         bout.setBlockDataMode(false);
         defaultWriteFields(curObj, curDesc);
         bout.setBlockDataMode(true);
@@ -467,11 +469,12 @@
      */
     public ObjectOutputStream.PutField putFields() throws IOException {
         if (curPut == null) {
-            if (curContext == null) {
+            SerialCallbackContext ctx = curContext;
+            if (ctx == null) {
                 throw new NotActiveException("not in call to writeObject");
             }
-            Object curObj = curContext.getObj();
-            ObjectStreamClass curDesc = curContext.getDesc();
+            Object curObj = ctx.getObj();
+            ObjectStreamClass curDesc = ctx.getDesc();
             curPut = new PutFieldImpl(curDesc);
         }
         return curPut;
@@ -500,7 +503,7 @@
      * stream.  The state is reset to be the same as a new ObjectOutputStream.
      * The current point in the stream is marked as reset so the corresponding
      * ObjectInputStream will be reset at the same point.  Objects previously
-     * written to the stream will not be refered to as already being in the
+     * written to the stream will not be referred to as already being in the
      * stream.  They will be written to the stream again.
      *
      * @throws  IOException if reset() is invoked while serializing an object.
@@ -1051,7 +1054,7 @@
      * "enableSubclassImplementation" SerializablePermission is checked.
      */
     private void verifySubclass() {
-        Class cl = getClass();
+        Class<?> cl = getClass();
         if (cl == ObjectOutputStream.class) {
             return;
         }
@@ -1077,22 +1080,22 @@
      * override security-sensitive non-final methods.  Returns true if subclass
      * is "safe", false otherwise.
      */
-    private static boolean auditSubclass(final Class subcl) {
+    private static boolean auditSubclass(final Class<?> subcl) {
         Boolean result = AccessController.doPrivileged(
             new PrivilegedAction<Boolean>() {
                 public Boolean run() {
-                    for (Class cl = subcl;
+                    for (Class<?> cl = subcl;
                          cl != ObjectOutputStream.class;
                          cl = cl.getSuperclass())
                     {
                         try {
                             cl.getDeclaredMethod(
-                                "writeUnshared", new Class[] { Object.class });
+                                "writeUnshared", new Class<?>[] { Object.class });
                             return Boolean.FALSE;
                         } catch (NoSuchMethodException ex) {
                         }
                         try {
-                            cl.getDeclaredMethod("putFields", (Class[]) null);
+                            cl.getDeclaredMethod("putFields", (Class<?>[]) null);
                             return Boolean.FALSE;
                         } catch (NoSuchMethodException ex) {
                         }
@@ -1141,13 +1144,13 @@
 
             // check for replacement object
             Object orig = obj;
-            Class cl = obj.getClass();
+            Class<?> cl = obj.getClass();
             ObjectStreamClass desc;
 
             /* ----- BEGIN android -----
             for (;;) {
                 // REMIND: skip this check for strings/arrays?
-                Class repCl;
+                Class<?> repCl;
                 desc = ObjectStreamClass.lookup(cl, true);
                 if (!desc.hasWriteReplaceMethod() ||
                     (obj = desc.invokeWriteReplace(obj)) == null ||
@@ -1213,7 +1216,7 @@
             } else if (cl.isArray()) {
                 writeArray(obj, desc, unshared);
             } else if (obj instanceof Enum) {
-                writeEnum((Enum) obj, desc, unshared);
+                writeEnum((Enum<?>) obj, desc, unshared);
             } else if (obj instanceof Serializable) {
                 writeOrdinaryObject(obj, desc, unshared);
             } else {
@@ -1248,7 +1251,7 @@
     /**
      * Writes representation of given class to stream.
      */
-    private void writeClass(Class cl, boolean unshared) throws IOException {
+    private void writeClass(Class<?> cl, boolean unshared) throws IOException {
         bout.writeByte(TC_CLASS);
         writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
         handles.assign(unshared ? null : cl);
@@ -1287,8 +1290,8 @@
         bout.writeByte(TC_PROXYCLASSDESC);
         handles.assign(unshared ? null : desc);
 
-        Class cl = desc.forClass();
-        Class[] ifaces = cl.getInterfaces();
+        Class<?> cl = desc.forClass();
+        Class<?>[] ifaces = cl.getInterfaces();
         bout.writeInt(ifaces.length);
         for (int i = 0; i < ifaces.length; i++) {
             bout.writeUTF(ifaces[i].getName());
@@ -1322,7 +1325,7 @@
             writeClassDescriptor(desc);
         }
 
-        Class cl = desc.forClass();
+        Class<?> cl = desc.forClass();
         bout.setBlockDataMode(true);
         if (isCustomSubclass()) {
             ReflectUtil.checkPackageAccess(cl);
@@ -1362,7 +1365,7 @@
         writeClassDesc(desc, false);
         handles.assign(unshared ? null : array);
 
-        Class ccl = desc.forClass().getComponentType();
+        Class<?> ccl = desc.forClass().getComponentType();
         if (ccl.isPrimitive()) {
             if (ccl == Integer.TYPE) {
                 int[] ia = (int[]) array;
@@ -1433,7 +1436,7 @@
     /**
      * Writes given enum constant to stream.
      */
-    private void writeEnum(Enum en,
+    private void writeEnum(Enum<?> en,
                            ObjectStreamClass desc,
                            boolean unshared)
         throws IOException
@@ -1756,7 +1759,7 @@
          * types, and any other non-null type matches assignable types only.
          * Throws IllegalArgumentException if no matching field found.
          */
-        private int getFieldOffset(String name, Class type) {
+        private int getFieldOffset(String name, Class<?> type) {
             ObjectStreamField field = desc.getField(name, type);
             if (field == null) {
                 throw new IllegalArgumentException("no such field " + name +
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index ffbde98..ff1cf82 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.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
@@ -169,7 +169,7 @@
     private volatile ClassDataSlot[] dataLayout;
 
     /** serialization-appropriate constructor, or null if none */
-    private Constructor cons;
+    private Constructor<?> cons;
     /** class-defined writeObject method, or null if none */
     private Method writeObjectMethod;
     /** class-defined readObject method, or null if none */
@@ -506,7 +506,7 @@
             fieldRefl = getReflector(fields, this);
         } catch (InvalidClassException ex) {
             // field mismatches impossible when matching local fields vs. self
-            throw new InternalError();
+            throw new InternalError(ex);
         }
 
         if (deserializeEx == null) {
@@ -956,7 +956,7 @@
                 return cons.newInstance();
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -984,7 +984,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1015,7 +1015,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1043,7 +1043,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1068,11 +1068,11 @@
                     throw (ObjectStreamException) th;
                 } else {
                     throwMiscException(th);
-                    throw new InternalError();  // never reached
+                    throw new InternalError(th);  // never reached
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1097,11 +1097,11 @@
                     throw (ObjectStreamException) th;
                 } else {
                     throwMiscException(th);
-                    throw new InternalError();  // never reached
+                    throw new InternalError(th);  // never reached
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1330,9 +1330,9 @@
      * Access checks are disabled on the returned constructor (if any), since
      * the defining class may still be non-public.
      */
-    private static Constructor getExternalizableConstructor(Class<?> cl) {
+    private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
         try {
-            Constructor cons = cl.getDeclaredConstructor((Class<?>[]) null);
+            Constructor<?> cons = cl.getDeclaredConstructor((Class<?>[]) null);
             cons.setAccessible(true);
             return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
                 cons : null;
@@ -1346,7 +1346,7 @@
      * superclass, or null if none found.  Access checks are disabled on the
      * returned constructor (if any).
      */
-    private static Constructor getSerializableConstructor(Class<?> cl) {
+    private static Constructor<?> getSerializableConstructor(Class<?> cl) {
         Class<?> initCl = cl;
         while (Serializable.class.isAssignableFrom(initCl)) {
             if ((initCl = initCl.getSuperclass()) == null) {
@@ -1354,7 +1354,7 @@
             }
         }
         try {
-            Constructor cons = initCl.getDeclaredConstructor((Class<?>[]) null);
+            Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
             int mods = cons.getModifiers();
             if ((mods & Modifier.PRIVATE) != 0 ||
                 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
@@ -1739,7 +1739,7 @@
                 dout.writeUTF("()V");
             }
 
-            Constructor[] cons = cl.getDeclaredConstructors();
+            Constructor<?>[] cons = cl.getDeclaredConstructors();
             MemberSignature[] consSigs = new MemberSignature[cons.length];
             for (int i = 0; i < cons.length; i++) {
                 consSigs[i] = new MemberSignature(cons[i]);
@@ -1800,7 +1800,7 @@
             }
             return hash;
         } catch (IOException ex) {
-            throw new InternalError();
+            throw new InternalError(ex);
         } catch (NoSuchAlgorithmException ex) {
             throw new SecurityException(ex.getMessage());
         }
@@ -1834,7 +1834,7 @@
             signature = getClassSignature(field.getType());
         }
 
-        public MemberSignature(Constructor cons) {
+        public MemberSignature(Constructor<?> cons) {
             member = cons;
             name = cons.getName();
             signature = getMethodSignature(
@@ -2274,24 +2274,36 @@
     // **** THESE METHODS WILL BE REMOVED IN A FUTURE ANDROID RELEASE ****.
     //
     private static long getConstructorId(Class<?> clazz) {
-        System.logE("WARNING: ObjectStreamClass.getConstructorId(Class<?>) is private API and" +
-                "will be removed in a future Android release.");
-        // NOTE: This method is a stub that returns a fixed value. It's meant to be used
-        // with newInstance(Class<?>, long) and our current implementation of that method ignores
-        // the "constructorId" argument. We return :
-        //
-        // oh one one eight nine nine nine
-        // eight eight one nine nine
-        // nine one one nine seven two five
-        // three
-        //
-        // in all cases.
-        return 1189998819991197253L;
+        final int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+        if (targetSdkVersion > 0 && targetSdkVersion <= 24) {
+            System.logE("WARNING: ObjectStreamClass.getConstructorId(Class<?>) is private API and" +
+                        "will be removed in a future Android release.");
+            // NOTE: This method is a stub that returns a fixed value. It's meant to be used
+            // with newInstance(Class<?>, long) and our current implementation of that method ignores
+            // the "constructorId" argument. We return :
+            //
+            // oh one one eight nine nine nine
+            // eight eight one nine nine
+            // nine one one nine seven two five
+            // three
+            //
+            // in all cases.
+            return 1189998819991197253L;
+        }
+
+        throw new UnsupportedOperationException("ObjectStreamClass.getConstructorId(Class<?>) is " +
+                                                "not supported on SDK " + targetSdkVersion);
     }
     private static Object newInstance(Class<?> clazz, long constructorId) {
-        System.logE("WARNING: ObjectStreamClass.newInstance(Class<?>, long) is private API and" +
-                "will be removed in a future Android release.");
-        return sun.misc.Unsafe.getUnsafe().allocateInstance(clazz);
+        final int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+        if (targetSdkVersion > 0 && targetSdkVersion <= 24) {
+            System.logE("WARNING: ObjectStreamClass.newInstance(Class<?>, long) is private API and" +
+                        "will be removed in a future Android release.");
+            return sun.misc.Unsafe.getUnsafe().allocateInstance(clazz);
+        }
+
+        throw new UnsupportedOperationException("ObjectStreamClass.newInstance(Class<?>, long) " +
+                                                "is not supported on SDK " + targetSdkVersion);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/io/ObjectStreamConstants.java b/ojluni/src/main/java/java/io/ObjectStreamConstants.java
index ddbada9..23f72b4 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamConstants.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamConstants.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -219,7 +219,7 @@
     * This protocol is written by JVM 1.2.
     *
     * Externalizable data is written in block data mode and is
-    * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
+    * terminated with TC_ENDBLOCKDATA. Externalizable class descriptor
     * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
     * read this format change.
     *
diff --git a/ojluni/src/main/java/java/io/ObjectStreamField.java b/ojluni/src/main/java/java/io/ObjectStreamField.java
index 0eee71f..c49bcac 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamField.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamField.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -235,6 +235,8 @@
      * Returns boolean value indicating whether or not the serializable field
      * represented by this ObjectStreamField instance is unshared.
      *
+     * @return {@code true} if this field is unshared
+     *
      * @since 1.4
      */
     public boolean isUnshared() {
diff --git a/ojluni/src/main/java/java/io/OutputStreamWriter.java b/ojluni/src/main/java/java/io/OutputStreamWriter.java
index b4e4b9e..5f7b9e3 100644
--- a/ojluni/src/main/java/java/io/OutputStreamWriter.java
+++ b/ojluni/src/main/java/java/io/OutputStreamWriter.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -33,7 +33,7 @@
 /**
  * An OutputStreamWriter is a bridge from character streams to byte streams:
  * Characters written to it are encoded into bytes using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}.  The charset that it uses
+ * java.nio.charset.Charset charset}.  The charset that it uses
  * may be specified by name or may be given explicitly, or the platform's
  * default charset may be accepted.
  *
@@ -86,7 +86,7 @@
      *
      * @param  charsetName
      *         The name of a supported
-     *         {@link java.nio.charset.Charset </code>charset<code>}
+     *         {@link java.nio.charset.Charset charset}
      *
      * @exception  UnsupportedEncodingException
      *             If the named encoding is not supported
@@ -115,7 +115,7 @@
     }
 
     /**
-     * Creates an OutputStreamWriter that uses the given charset. </p>
+     * Creates an OutputStreamWriter that uses the given charset.
      *
      * @param  out
      *         An OutputStream
@@ -134,7 +134,7 @@
     }
 
     /**
-     * Creates an OutputStreamWriter that uses the given charset encoder.  </p>
+     * Creates an OutputStreamWriter that uses the given charset encoder.
      *
      * @param  out
      *         An OutputStream
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/RandomAccessFile.java b/ojluni/src/main/java/java/io/RandomAccessFile.java
old mode 100644
new mode 100755
index fc645cf..80ffb95
--- a/ojluni/src/main/java/java/io/RandomAccessFile.java
+++ b/ojluni/src/main/java/java/io/RandomAccessFile.java
@@ -31,6 +31,7 @@
 import android.system.ErrnoException;
 import dalvik.system.CloseGuard;
 import libcore.io.IoBridge;
+import libcore.io.IoTracker;
 import libcore.io.Libcore;
 import static android.system.OsConstants.*;
 
@@ -81,6 +82,11 @@
 
     private Object closeLock = new Object();
     private volatile boolean closed = false;
+    /**
+     * A single tracker to track both read and write. The tracker resets when the operation
+     * performed is different from the operation last performed.
+     */
+    private final IoTracker ioTracker = new IoTracker();
 
     /**
      * Creates a random access file stream to read from, and optionally
@@ -326,6 +332,7 @@
      * @exception IOException If an I/O error has occurred.
      */
     private int readBytes(byte b[], int off, int len) throws IOException {
+        ioTracker.trackIo(len, IoTracker.Mode.READ);
         return IoBridge.read(fd, b, off, len);
     }
 
@@ -479,6 +486,7 @@
      * @exception IOException If an I/O error has occurred.
      */
     private void writeBytes(byte b[], int off, int len) throws IOException {
+        ioTracker.trackIo(len, IoTracker.Mode.WRITE);
         IoBridge.write(fd, b, off, len);
         // if we are in "rws" mode, attempt to sync file+metadata
         if (syncMetadata) {
@@ -547,6 +555,7 @@
         }
         try {
             Libcore.os.lseek(fd, offset, SEEK_SET);
+            ioTracker.reset();
         } catch (ErrnoException errnoException) {
             throw errnoException.rethrowAsIOException();
         }
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/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/Math.java b/ojluni/src/main/java/java/lang/Math.java
index e96cc58..930d6c2 100644
--- a/ojluni/src/main/java/java/lang/Math.java
+++ b/ojluni/src/main/java/java/lang/Math.java
@@ -754,6 +754,13 @@
     }
 
     /**
+     * @hide for internal use only.
+     */
+    public static long randomLongInternal() {
+        return RandomNumberGeneratorHolder.randomNumberGenerator.nextLong();
+    }
+
+    /**
      * Returns the sum of its arguments,
      * throwing an exception if the result overflows an {@code int}.
      *
diff --git a/ojluni/src/main/java/java/lang/annotation/ElementType.java b/ojluni/src/main/java/java/lang/annotation/ElementType.java
index 9dd2851..13b48f6 100644
--- a/ojluni/src/main/java/java/lang/annotation/ElementType.java
+++ b/ojluni/src/main/java/java/lang/annotation/ElementType.java
@@ -65,7 +65,6 @@
      * Type parameter declaration
      *
      * @since 1.8
-     * @hide 1.8
      */
     TYPE_PARAMETER,
 
@@ -73,7 +72,6 @@
      * Use of a type
      *
      * @since 1.8
-     * @hide 1.8
      */
     TYPE_USE
 }
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
index ffbc401..0c27b99 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
@@ -446,6 +446,38 @@
     private final MethodType type;
     /*private*/ MethodHandle asTypeCache;
     // asTypeCache is not private so that invokers can easily fetch it
+    // Used by the runtime.
+
+    /**
+     * The INVOKE* constants and SGET/SPUT and IGET/IPUT constants specify the behaviour of this
+     * method handle with respect to the ArtField* or the ArtMethod* that it operates on. These
+     * behaviours are equivalent to the dex bytecode behaviour on the respective method_id or
+     * field_id in the equivalent instruction.
+     */
+
+    /** @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 = 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.
+    private final int handleKind;
+
+    // The ArtMethod* or ArtField* associated with this method handle (used by the runtime).
+    private final long artFieldOrMethod;
+
+    protected MethodHandle(long artFieldOrMethod, int handleKind, MethodType type) {
+        this.artFieldOrMethod = artFieldOrMethod;
+        this.handleKind = handleKind;
+        this.type = type;
+    }
 
     /**
      * Reports the type of this method handle.
@@ -457,19 +489,6 @@
     }
 
     /**
-     * Package-private constructor for the method handle implementation hierarchy.
-     * Method handle inheritance will be contained completely within
-     * the {@code java.lang.invoke} package.
-     */
-    // @param type type (permanently assigned) of the new method handle
-    /*non-public*/ MethodHandle(MethodType type) {
-        type.getClass();  // explicit NPE
-        this.type = type;
-
-        // Android-changed: No LambdaForms associated with this MH.
-    }
-
-    /**
      * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
      * The symbolic type descriptor at the call site of {@code invokeExact} must
      * exactly match this method handle's {@link #type type}.
@@ -1262,6 +1281,11 @@
         return "MethodHandle"+type;
     }
 
+    /** @hide */
+    public int getHandleKind() {
+        return handleKind;
+    }
+
     // Android-changed: Removed implementation details :
     //
     // String standardString();
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java b/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java
new file mode 100644
index 0000000..06ff553
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * 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.  Google designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Google 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.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A method handle that's directly associated with an ArtField or an ArtMethod and
+ * specifies no additional transformations.
+ *
+ * @hide
+ */
+public class MethodHandleImpl extends MethodHandle {
+
+    MethodHandleImpl(long artFieldOrMethod, int handleKind, MethodType type) {
+        super(artFieldOrMethod, handleKind, type);
+    }
+}
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java b/ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java
index 6928c22..17d7882 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java
@@ -25,8 +25,6 @@
 
 package java.lang.invoke;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import sun.misc.Unsafe;
 
 /**
@@ -41,56 +39,8 @@
 
     static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
-    static final boolean DEBUG_METHOD_HANDLE_NAMES;
-    static final boolean DUMP_CLASS_FILES;
-    static final boolean TRACE_INTERPRETER;
-    static final boolean TRACE_METHOD_LINKAGE;
-    static final int COMPILE_THRESHOLD;
-    static final int DONT_INLINE_THRESHOLD;
-    static final int PROFILE_LEVEL;
-    static final boolean PROFILE_GWT;
-    static final int CUSTOMIZE_THRESHOLD;
-
-    static {
-        final Object[] values = new Object[9];
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
-                    values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
-                    values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
-                    values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
-                    values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0);
-                    values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30);
-                    values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
-                    values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
-                    values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
-                    return null;
-                }
-            });
-        DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
-        DUMP_CLASS_FILES          = (Boolean) values[1];
-        TRACE_INTERPRETER         = (Boolean) values[2];
-        TRACE_METHOD_LINKAGE      = (Boolean) values[3];
-        COMPILE_THRESHOLD         = (Integer) values[4];
-        DONT_INLINE_THRESHOLD     = (Integer) values[5];
-        PROFILE_LEVEL             = (Integer) values[6];
-        PROFILE_GWT               = (Boolean) values[7];
-        CUSTOMIZE_THRESHOLD       = (Integer) values[8];
-
-        if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
-            throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
-        }
-    }
-
-    /** Tell if any of the debugging switches are turned on.
-     *  If this is the case, it is reasonable to perform extra checks or save extra information.
-     */
-    /*non-public*/ static boolean debugEnabled() {
-        return (DEBUG_METHOD_HANDLE_NAMES |
-                DUMP_CLASS_FILES |
-                TRACE_INTERPRETER |
-                TRACE_METHOD_LINKAGE);
-    }
+    // Android-changed: Remove debugging related static fields. They are unused and have
+    // no equivalent on Android.
 
     // Android-changed: Temporarily hide methods that operate on MethodHandles until the
     // MethodHandle class is imported.
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
new file mode 100644
index 0000000..bd2f60d
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -0,0 +1,2672 @@
+/*
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.*;
+import java.util.List;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+
+import dalvik.system.VMStack;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * This class consists exclusively of static methods that operate on or return
+ * method handles. They fall into several categories:
+ * <ul>
+ * <li>Lookup methods which help create method handles for methods and fields.
+ * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
+ * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
+ * </ul>
+ * <p>
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public class MethodHandles {
+
+    private MethodHandles() { }  // do not instantiate
+
+    // Android-changed: We do not use MemberName / MethodHandleImpl.
+    //
+    // private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
+    // static { MethodHandleImpl.initStatics(); }
+    // See IMPL_LOOKUP below.
+
+    //// Method handle creation from ordinary methods.
+
+    /**
+     * Returns a {@link Lookup lookup object} with
+     * full capabilities to emulate all supported bytecode behaviors of the caller.
+     * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller.
+     * Factory methods on the lookup object can create
+     * <a href="MethodHandleInfo.html#directmh">direct method handles</a>
+     * for any member that the caller has access to via bytecodes,
+     * including protected and private fields and methods.
+     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
+     * Do not store it in place where untrusted code can access it.
+     * <p>
+     * This method is caller sensitive, which means that it may return different
+     * values to different callers.
+     * <p>
+     * For any given caller class {@code C}, the lookup object returned by this call
+     * has equivalent capabilities to any lookup object
+     * supplied by the JVM to the bootstrap method of an
+     * <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
+     * executing in the same caller class {@code C}.
+     * @return a lookup object for the caller of this method, with private access
+     */
+    // Android-changed: Remove caller sensitive.
+    // @CallerSensitive
+    public static Lookup lookup() {
+        // Android-changed: Do not use Reflection.getCallerClass().
+        return new Lookup(VMStack.getStackClass1());
+    }
+
+    /**
+     * Returns a {@link Lookup lookup object} which is trusted minimally.
+     * It can only be used to create method handles to
+     * publicly accessible fields and methods.
+     * <p>
+     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
+     * of this lookup object will be {@link java.lang.Object}.
+     *
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * The lookup class can be changed to any other class {@code C} using an expression of the form
+     * {@link Lookup#in publicLookup().in(C.class)}.
+     * Since all classes have equal access to public names,
+     * such a change would confer no new access rights.
+     * A public lookup object is always subject to
+     * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
+     * Also, it cannot access
+     * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>.
+     * @return a lookup object which is trusted minimally
+     */
+    public static Lookup publicLookup() {
+        return Lookup.PUBLIC_LOOKUP;
+    }
+
+    /**
+     * Performs an unchecked "crack" of a
+     * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
+     * The result is as if the user had obtained a lookup object capable enough
+     * to crack the target method handle, called
+     * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
+     * on the target to obtain its symbolic reference, and then called
+     * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
+     * to resolve the symbolic reference to a member.
+     * <p>
+     * If there is a security manager, its {@code checkPermission} method
+     * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
+     * @param <T> the desired type of the result, either {@link Member} or a subtype
+     * @param target a direct method handle to crack into symbolic reference components
+     * @param expected a class object representing the desired result type {@code T}
+     * @return a reference to the method, constructor, or field object
+     * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
+     * @exception NullPointerException if either argument is {@code null}
+     * @exception IllegalArgumentException if the target is not a direct method handle
+     * @exception ClassCastException if the member is not of the expected type
+     * @since 1.8
+     */
+    public static <T extends Member> T
+    reflectAs(Class<T> expected, MethodHandle target) {
+        throw new UnsupportedOperationException("MethodHandles.reflectAs is not implemented.");
+    }
+
+    /**
+     * A <em>lookup object</em> is a factory for creating method handles,
+     * when the creation requires access checking.
+     * Method handles do not perform
+     * access checks when they are called, but rather when they are created.
+     * Therefore, method handle access
+     * restrictions must be enforced when a method handle is created.
+     * The caller class against which those restrictions are enforced
+     * is known as the {@linkplain #lookupClass lookup class}.
+     * <p>
+     * A lookup class which needs to create method handles will call
+     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
+     * When the {@code Lookup} factory object is created, the identity of the lookup class is
+     * determined, and securely stored in the {@code Lookup} object.
+     * The lookup class (or its delegates) may then use factory methods
+     * on the {@code Lookup} object to create method handles for access-checked members.
+     * This includes all methods, constructors, and fields which are allowed to the lookup class,
+     * even private ones.
+     *
+     * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
+     * The factory methods on a {@code Lookup} object correspond to all major
+     * use cases for methods, constructors, and fields.
+     * Each method handle created by a factory method is the functional
+     * equivalent of a particular <em>bytecode behavior</em>.
+     * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.)
+     * Here is a summary of the correspondence between these factory methods and
+     * the behavior the resulting method handles:
+     * <table border=1 cellpadding=5 summary="lookup method behaviors">
+     * <tr>
+     *     <th><a name="equiv"></a>lookup expression</th>
+     *     <th>member</th>
+     *     <th>bytecode behavior</th>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
+     *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
+     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
+     *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
+     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
+     *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
+     *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
+     *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
+     *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
+     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
+     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
+     *     <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
+     * </tr>
+     * <tr>
+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
+     * </tr>
+     * </table>
+     *
+     * Here, the type {@code C} is the class or interface being searched for a member,
+     * documented as a parameter named {@code refc} in the lookup methods.
+     * The method type {@code MT} is composed from the return type {@code T}
+     * and the sequence of argument types {@code A*}.
+     * The constructor also has a sequence of argument types {@code A*} and
+     * is deemed to return the newly-created object of type {@code C}.
+     * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
+     * The formal parameter {@code this} stands for the self-reference of type {@code C};
+     * if it is present, it is always the leading argument to the method handle invocation.
+     * (In the case of some {@code protected} members, {@code this} may be
+     * restricted in type to the lookup class; see below.)
+     * The name {@code arg} stands for all the other method handle arguments.
+     * In the code examples for the Core Reflection API, the name {@code thisOrNull}
+     * stands for a null reference if the accessed method or field is static,
+     * and {@code this} otherwise.
+     * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
+     * for reflective objects corresponding to the given members.
+     * <p>
+     * In cases where the given member is of variable arity (i.e., a method or constructor)
+     * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}.
+     * In all other cases, the returned method handle will be of fixed arity.
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * The equivalence between looked-up method handles and underlying
+     * class members and bytecode behaviors
+     * can break down in a few ways:
+     * <ul style="font-size:smaller;">
+     * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
+     * the lookup can still succeed, even when there is no equivalent
+     * Java expression or bytecoded constant.
+     * <li>Likewise, if {@code T} or {@code MT}
+     * is not symbolically accessible from the lookup class's loader,
+     * the lookup can still succeed.
+     * For example, lookups for {@code MethodHandle.invokeExact} and
+     * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
+     * <li>If there is a security manager installed, it can forbid the lookup
+     * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>).
+     * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle}
+     * constant is not subject to security manager checks.
+     * <li>If the looked-up method has a
+     * <a href="MethodHandle.html#maxarity">very large arity</a>,
+     * the method handle creation may fail, due to the method handle
+     * type having too many parameters.
+     * </ul>
+     *
+     * <h1><a name="access"></a>Access checking</h1>
+     * Access checks are applied in the factory methods of {@code Lookup},
+     * when a method handle is created.
+     * This is a key difference from the Core Reflection API, since
+     * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
+     * performs access checking against every caller, on every call.
+     * <p>
+     * All access checks start from a {@code Lookup} object, which
+     * compares its recorded lookup class against all requests to
+     * create method handles.
+     * A single {@code Lookup} object can be used to create any number
+     * of access-checked method handles, all checked against a single
+     * lookup class.
+     * <p>
+     * A {@code Lookup} object can be shared with other trusted code,
+     * such as a metaobject protocol.
+     * A shared {@code Lookup} object delegates the capability
+     * to create method handles on private members of the lookup class.
+     * Even if privileged code uses the {@code Lookup} object,
+     * the access checking is confined to the privileges of the
+     * original lookup class.
+     * <p>
+     * A lookup can fail, because
+     * the containing class is not accessible to the lookup class, or
+     * because the desired class member is missing, or because the
+     * desired class member is not accessible to the lookup class, or
+     * because the lookup object is not trusted enough to access the member.
+     * In any of these cases, a {@code ReflectiveOperationException} will be
+     * thrown from the attempted lookup.  The exact class will be one of
+     * the following:
+     * <ul>
+     * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
+     * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
+     * <li>IllegalAccessException &mdash; if the member exists but an access check fails
+     * </ul>
+     * <p>
+     * In general, the conditions under which a method handle may be
+     * looked up for a method {@code M} are no more restrictive than the conditions
+     * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
+     * Where the JVM would raise exceptions like {@code NoSuchMethodError},
+     * a method handle lookup will generally raise a corresponding
+     * checked exception, such as {@code NoSuchMethodException}.
+     * And the effect of invoking the method handle resulting from the lookup
+     * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
+     * to executing the compiled, verified, and resolved call to {@code M}.
+     * The same point is true of fields and constructors.
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * Access checks only apply to named and reflected methods,
+     * constructors, and fields.
+     * Other method handle creation methods, such as
+     * {@link MethodHandle#asType MethodHandle.asType},
+     * do not require any access checks, and are used
+     * independently of any {@code Lookup} object.
+     * <p>
+     * If the desired member is {@code protected}, the usual JVM rules apply,
+     * including the requirement that the lookup class must be either be in the
+     * same package as the desired member, or must inherit that member.
+     * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.)
+     * In addition, if the desired member is a non-static field or method
+     * in a different package, the resulting method handle may only be applied
+     * to objects of the lookup class or one of its subclasses.
+     * This requirement is enforced by narrowing the type of the leading
+     * {@code this} parameter from {@code C}
+     * (which will necessarily be a superclass of the lookup class)
+     * to the lookup class itself.
+     * <p>
+     * The JVM imposes a similar requirement on {@code invokespecial} instruction,
+     * that the receiver argument must match both the resolved method <em>and</em>
+     * the current class.  Again, this requirement is enforced by narrowing the
+     * type of the leading parameter to the resulting method handle.
+     * (See the Java Virtual Machine Specification, section 4.10.1.9.)
+     * <p>
+     * The JVM represents constructors and static initializer blocks as internal methods
+     * with special names ({@code "<init>"} and {@code "<clinit>"}).
+     * The internal syntax of invocation instructions allows them to refer to such internal
+     * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
+     * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
+     * <p>
+     * In some cases, access between nested classes is obtained by the Java compiler by creating
+     * an wrapper method to access a private method of another class
+     * in the same top-level declaration.
+     * For example, a nested class {@code C.D}
+     * can access private members within other related classes such as
+     * {@code C}, {@code C.D.E}, or {@code C.B},
+     * but the Java compiler may need to generate wrapper methods in
+     * those related classes.  In such cases, a {@code Lookup} object on
+     * {@code C.E} would be unable to those private members.
+     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
+     * which can transform a lookup on {@code C.E} into one on any of those other
+     * classes, without special elevation of privilege.
+     * <p>
+     * The accesses permitted to a given lookup object may be limited,
+     * according to its set of {@link #lookupModes lookupModes},
+     * to a subset of members normally accessible to the lookup class.
+     * For example, the {@link MethodHandles#publicLookup publicLookup}
+     * method produces a lookup object which is only allowed to access
+     * public members in public classes.
+     * The caller sensitive method {@link MethodHandles#lookup lookup}
+     * produces a lookup object with full capabilities relative to
+     * its caller class, to emulate all supported bytecode behaviors.
+     * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
+     * with fewer access modes than the original lookup object.
+     *
+     * <p style="font-size:smaller;">
+     * <a name="privacc"></a>
+     * <em>Discussion of private access:</em>
+     * We say that a lookup has <em>private access</em>
+     * if its {@linkplain #lookupModes lookup modes}
+     * include the possibility of accessing {@code private} members.
+     * As documented in the relevant methods elsewhere,
+     * only lookups with private access possess the following capabilities:
+     * <ul style="font-size:smaller;">
+     * <li>access private fields, methods, and constructors of the lookup class
+     * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
+     *     such as {@code Class.forName}
+     * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
+     * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
+     *     for classes accessible to the lookup class
+     * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
+     *     within the same package member
+     * </ul>
+     * <p style="font-size:smaller;">
+     * Each of these permissions is a consequence of the fact that a lookup object
+     * with private access can be securely traced back to an originating class,
+     * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
+     * can be reliably determined and emulated by method handles.
+     *
+     * <h1><a name="secmgr"></a>Security manager interactions</h1>
+     * Although bytecode instructions can only refer to classes in
+     * a related class loader, this API can search for methods in any
+     * class, as long as a reference to its {@code Class} object is
+     * available.  Such cross-loader references are also possible with the
+     * Core Reflection API, and are impossible to bytecode instructions
+     * such as {@code invokestatic} or {@code getfield}.
+     * There is a {@linkplain java.lang.SecurityManager security manager API}
+     * to allow applications to check such cross-loader references.
+     * These checks apply to both the {@code MethodHandles.Lookup} API
+     * and the Core Reflection API
+     * (as found on {@link java.lang.Class Class}).
+     * <p>
+     * If a security manager is present, member lookups are subject to
+     * additional checks.
+     * From one to three calls are made to the security manager.
+     * Any of these calls can refuse access by throwing a
+     * {@link java.lang.SecurityException SecurityException}.
+     * Define {@code smgr} as the security manager,
+     * {@code lookc} as the lookup class of the current lookup object,
+     * {@code refc} as the containing class in which the member
+     * is being sought, and {@code defc} as the class in which the
+     * member is actually defined.
+     * The value {@code lookc} is defined as <em>not present</em>
+     * if the current lookup object does not have
+     * <a href="MethodHandles.Lookup.html#privacc">private access</a>.
+     * The calls are made according to the following rules:
+     * <ul>
+     * <li><b>Step 1:</b>
+     *     If {@code lookc} is not present, or if its class loader is not
+     *     the same as or an ancestor of the class loader of {@code refc},
+     *     then {@link SecurityManager#checkPackageAccess
+     *     smgr.checkPackageAccess(refcPkg)} is called,
+     *     where {@code refcPkg} is the package of {@code refc}.
+     * <li><b>Step 2:</b>
+     *     If the retrieved member is not public and
+     *     {@code lookc} is not present, then
+     *     {@link SecurityManager#checkPermission smgr.checkPermission}
+     *     with {@code RuntimePermission("accessDeclaredMembers")} is called.
+     * <li><b>Step 3:</b>
+     *     If the retrieved member is not public,
+     *     and if {@code lookc} is not present,
+     *     and if {@code defc} and {@code refc} are different,
+     *     then {@link SecurityManager#checkPackageAccess
+     *     smgr.checkPackageAccess(defcPkg)} is called,
+     *     where {@code defcPkg} is the package of {@code defc}.
+     * </ul>
+     * Security checks are performed after other access checks have passed.
+     * Therefore, the above rules presuppose a member that is public,
+     * or else that is being accessed from a lookup class that has
+     * rights to access the member.
+     *
+     * <h1><a name="callsens"></a>Caller sensitive methods</h1>
+     * A small number of Java methods have a special property called caller sensitivity.
+     * A <em>caller-sensitive</em> method can behave differently depending on the
+     * identity of its immediate caller.
+     * <p>
+     * If a method handle for a caller-sensitive method is requested,
+     * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply,
+     * but they take account of the lookup class in a special way.
+     * The resulting method handle behaves as if it were called
+     * from an instruction contained in the lookup class,
+     * so that the caller-sensitive method detects the lookup class.
+     * (By contrast, the invoker of the method handle is disregarded.)
+     * Thus, in the case of caller-sensitive methods,
+     * different lookup classes may give rise to
+     * differently behaving method handles.
+     * <p>
+     * In cases where the lookup object is
+     * {@link MethodHandles#publicLookup() publicLookup()},
+     * or some other lookup object without
+     * <a href="MethodHandles.Lookup.html#privacc">private access</a>,
+     * the lookup class is disregarded.
+     * In such cases, no caller-sensitive method handle can be created,
+     * access is forbidden, and the lookup fails with an
+     * {@code IllegalAccessException}.
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * For example, the caller-sensitive method
+     * {@link java.lang.Class#forName(String) Class.forName(x)}
+     * can return varying classes or throw varying exceptions,
+     * depending on the class loader of the class that calls it.
+     * A public lookup of {@code Class.forName} will fail, because
+     * there is no reasonable way to determine its bytecode behavior.
+     * <p style="font-size:smaller;">
+     * If an application caches method handles for broad sharing,
+     * it should use {@code publicLookup()} to create them.
+     * If there is a lookup of {@code Class.forName}, it will fail,
+     * and the application must take appropriate action in that case.
+     * It may be that a later lookup, perhaps during the invocation of a
+     * bootstrap method, can incorporate the specific identity
+     * of the caller, making the method accessible.
+     * <p style="font-size:smaller;">
+     * The function {@code MethodHandles.lookup} is caller sensitive
+     * so that there can be a secure foundation for lookups.
+     * Nearly all other methods in the JSR 292 API rely on lookup
+     * objects to check access requests.
+     */
+    public static final
+    class Lookup {
+        /** The class on behalf of whom the lookup is being performed. */
+        /* @NonNull */ private final Class<?> lookupClass;
+
+        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
+        private final int allowedModes;
+
+        /** A single-bit mask representing {@code public} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x01}, happens to be the same as the value of the
+         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
+         */
+        public static final int PUBLIC = Modifier.PUBLIC;
+
+        /** A single-bit mask representing {@code private} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x02}, happens to be the same as the value of the
+         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
+         */
+        public static final int PRIVATE = Modifier.PRIVATE;
+
+        /** A single-bit mask representing {@code protected} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x04}, happens to be the same as the value of the
+         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
+         */
+        public static final int PROTECTED = Modifier.PROTECTED;
+
+        /** A single-bit mask representing {@code package} access (default access),
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value is {@code 0x08}, which does not correspond meaningfully to
+         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
+         */
+        public static final int PACKAGE = Modifier.STATIC;
+
+        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
+
+        // Android-note: Android has no notion of a trusted lookup. If required, such lookups
+        // are performed by the runtime. As a result, we always use lookupClass, which will always
+        // be non-null in our implementation.
+        //
+        // private static final int TRUSTED   = -1;
+
+        private static int fixmods(int mods) {
+            mods &= (ALL_MODES - PACKAGE);
+            return (mods != 0) ? mods : PACKAGE;
+        }
+
+        /** Tells which class is performing the lookup.  It is this class against
+         *  which checks are performed for visibility and access permissions.
+         *  <p>
+         *  The class implies a maximum level of access permission,
+         *  but the permissions may be additionally limited by the bitmask
+         *  {@link #lookupModes lookupModes}, which controls whether non-public members
+         *  can be accessed.
+         *  @return the lookup class, on behalf of which this lookup object finds members
+         */
+        public Class<?> lookupClass() {
+            return lookupClass;
+        }
+
+        /** Tells which access-protection classes of members this lookup object can produce.
+         *  The result is a bit-mask of the bits
+         *  {@linkplain #PUBLIC PUBLIC (0x01)},
+         *  {@linkplain #PRIVATE PRIVATE (0x02)},
+         *  {@linkplain #PROTECTED PROTECTED (0x04)},
+         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
+         *  <p>
+         *  A freshly-created lookup object
+         *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
+         *  has all possible bits set, since the caller class can access all its own members.
+         *  A lookup object on a new lookup class
+         *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
+         *  may have some mode bits set to zero.
+         *  The purpose of this is to restrict access via the new lookup object,
+         *  so that it can access only names which can be reached by the original
+         *  lookup object, and also by the new lookup class.
+         *  @return the lookup modes, which limit the kinds of access performed by this lookup object
+         */
+        public int lookupModes() {
+            return allowedModes & ALL_MODES;
+        }
+
+        /** Embody the current class (the lookupClass) as a lookup class
+         * for method handle creation.
+         * Must be called by from a method in this package,
+         * which in turn is called by a method not in this package.
+         */
+        Lookup(Class<?> lookupClass) {
+            this(lookupClass, ALL_MODES);
+            // make sure we haven't accidentally picked up a privileged class:
+            checkUnprivilegedlookupClass(lookupClass, ALL_MODES);
+        }
+
+        private Lookup(Class<?> lookupClass, int allowedModes) {
+            this.lookupClass = lookupClass;
+            this.allowedModes = allowedModes;
+        }
+
+        /**
+         * Creates a lookup on the specified new lookup class.
+         * The resulting object will report the specified
+         * class as its own {@link #lookupClass lookupClass}.
+         * <p>
+         * However, the resulting {@code Lookup} object is guaranteed
+         * to have no more access capabilities than the original.
+         * In particular, access capabilities can be lost as follows:<ul>
+         * <li>If the new lookup class differs from the old one,
+         * protected members will not be accessible by virtue of inheritance.
+         * (Protected members may continue to be accessible because of package sharing.)
+         * <li>If the new lookup class is in a different package
+         * than the old one, protected and default (package) members will not be accessible.
+         * <li>If the new lookup class is not within the same package member
+         * as the old one, private members will not be accessible.
+         * <li>If the new lookup class is not accessible to the old lookup class,
+         * then no members, not even public members, will be accessible.
+         * (In all other cases, public members will continue to be accessible.)
+         * </ul>
+         *
+         * @param requestedLookupClass the desired lookup class for the new lookup object
+         * @return a lookup object which reports the desired lookup class
+         * @throws NullPointerException if the argument is null
+         */
+        public Lookup in(Class<?> requestedLookupClass) {
+            requestedLookupClass.getClass();  // null check
+            // Android-changed: There's no notion of a trusted lookup.
+            // if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
+            //    return new Lookup(requestedLookupClass, ALL_MODES);
+
+            if (requestedLookupClass == this.lookupClass)
+                return this;  // keep same capabilities
+            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
+            if ((newModes & PACKAGE) != 0
+                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
+                newModes &= ~(PACKAGE|PRIVATE);
+            }
+            // Allow nestmate lookups to be created without special privilege:
+            if ((newModes & PRIVATE) != 0
+                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
+                newModes &= ~PRIVATE;
+            }
+            if ((newModes & PUBLIC) != 0
+                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
+                // The requested class it not accessible from the lookup class.
+                // No permissions.
+                newModes = 0;
+            }
+            checkUnprivilegedlookupClass(requestedLookupClass, newModes);
+            return new Lookup(requestedLookupClass, newModes);
+        }
+
+        // Make sure outer class is initialized first.
+        //
+        // Android-changed: Removed unnecessary reference to IMPL_NAMES.
+        // static { IMPL_NAMES.getClass(); }
+
+        /** Version of lookup which is trusted minimally.
+         *  It can only be used to create method handles to
+         *  publicly accessible members.
+         */
+        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
+
+        private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
+            String name = lookupClass.getName();
+            if (name.startsWith("java.lang.invoke."))
+                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
+
+            // For caller-sensitive MethodHandles.lookup()
+            // disallow lookup more restricted packages
+            //
+            // Android-changed: The bootstrap classloader isn't null.
+            if (allowedModes == ALL_MODES &&
+                    lookupClass.getClassLoader() == Object.class.getClassLoader()) {
+                if (name.startsWith("java.") ||
+                        (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
+                    throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
+                }
+            }
+        }
+
+        /**
+         * Displays the name of the class from which lookups are to be made.
+         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
+         * If there are restrictions on the access permitted to this lookup,
+         * this is indicated by adding a suffix to the class name, consisting
+         * of a slash and a keyword.  The keyword represents the strongest
+         * allowed access, and is chosen as follows:
+         * <ul>
+         * <li>If no access is allowed, the suffix is "/noaccess".
+         * <li>If only public access is allowed, the suffix is "/public".
+         * <li>If only public and package access are allowed, the suffix is "/package".
+         * <li>If only public, package, and private access are allowed, the suffix is "/private".
+         * </ul>
+         * If none of the above cases apply, it is the case that full
+         * access (public, package, private, and protected) is allowed.
+         * In this case, no suffix is added.
+         * This is true only of an object obtained originally from
+         * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+         * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
+         * always have restricted access, and will display a suffix.
+         * <p>
+         * (It may seem strange that protected access should be
+         * stronger than private access.  Viewed independently from
+         * package access, protected access is the first to be lost,
+         * because it requires a direct subclass relationship between
+         * caller and callee.)
+         * @see #in
+         */
+        @Override
+        public String toString() {
+            String cname = lookupClass.getName();
+            switch (allowedModes) {
+            case 0:  // no privileges
+                return cname + "/noaccess";
+            case PUBLIC:
+                return cname + "/public";
+            case PUBLIC|PACKAGE:
+                return cname + "/package";
+            case ALL_MODES & ~PROTECTED:
+                return cname + "/private";
+            case ALL_MODES:
+                return cname;
+            // Android-changed: No support for TRUSTED callers.
+            // case TRUSTED:
+            //    return "/trusted";  // internal only; not exported
+            default:  // Should not happen, but it's a bitfield...
+                cname = cname + "/" + Integer.toHexString(allowedModes);
+                assert(false) : cname;
+                return cname;
+            }
+        }
+
+        /**
+         * Produces a method handle for a static method.
+         * The type of the method handle will be that of the method.
+         * (Since static methods do not take receivers, there is no
+         * additional receiver argument inserted into the method handle type,
+         * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
+         * The method and all its argument types must be accessible to the lookup object.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * If the returned method handle is invoked, the method's class will
+         * be initialized, if it has not already been initialized.
+         * <p><b>Example:</b>
+         * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
+  "asList", methodType(List.class, Object[].class));
+assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
+         * }</pre></blockquote>
+         * @param refc the class from which the method is accessed
+         * @param name the name of the method
+         * @param type the type of the method
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails,
+         *                                or if the method is not {@code static},
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public
+        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            // TODO: Support varargs methods. The returned method handle must be a var-args
+            // collector in that case.
+            if (refc == MethodHandle.class) {
+                MethodHandle mh = findVirtualForMH(name, type);
+                if (mh != null) {
+                    return mh;
+                }
+            }
+
+            Method method = refc.getDeclaredMethod(name, type.ptypes());
+            final int modifiers = method.getModifiers();
+            if (!Modifier.isStatic(modifiers)) {
+                throw new IllegalAccessException("Method" + method + " is not static");
+            }
+
+            checkAccess(refc, method.getDeclaringClass(), modifiers, method.getName());
+            return new MethodHandleImpl(method.getArtMethod(), MethodHandle.INVOKE_STATIC, type);
+        }
+        private MethodHandle findVirtualForMH(String name, MethodType type) {
+            // these names require special lookups because of the implicit MethodType argument
+            if ("invoke".equals(name))
+                return invoker(type);
+            if ("invokeExact".equals(name))
+                return exactInvoker(type);
+            return null;
+        }
+
+        /**
+         * Produces a method handle for a virtual method.
+         * The type of the method handle will be that of the method,
+         * with the receiver type (usually {@code refc}) prepended.
+         * The method and all its argument types must be accessible to the lookup object.
+         * <p>
+         * When called, the handle will treat the first argument as a receiver
+         * and dispatch on the receiver's type to determine which method
+         * implementation to enter.
+         * (The dispatching action is identical with that performed by an
+         * {@code invokevirtual} or {@code invokeinterface} instruction.)
+         * <p>
+         * The first argument will be of type {@code refc} if the lookup
+         * class has full privileges to access the member.  Otherwise
+         * the member must be {@code protected} and the first argument
+         * will be restricted in type to the lookup class.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
+         * instructions and method handles produced by {@code findVirtual},
+         * if the class is {@code MethodHandle} and the name string is
+         * {@code invokeExact} or {@code invoke}, the resulting
+         * method handle is equivalent to one produced by
+         * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
+         * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
+         * with the same {@code type} argument.
+         *
+         * <b>Example:</b>
+         * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle MH_concat = publicLookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
+  "hashCode", methodType(int.class));
+MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
+  "hashCode", methodType(int.class));
+assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
+assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
+// interface method:
+MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
+  "subSequence", methodType(CharSequence.class, int.class, int.class));
+assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
+// constructor "internal method" must be accessed differently:
+MethodType MT_newString = methodType(void.class); //()V for new String()
+try { assertEquals("impossible", lookup()
+        .findVirtual(String.class, "<init>", MT_newString));
+ } catch (NoSuchMethodException ex) { } // OK
+MethodHandle MH_newString = publicLookup()
+  .findConstructor(String.class, MT_newString);
+assertEquals("", (String) MH_newString.invokeExact());
+         * }</pre></blockquote>
+         *
+         * @param refc the class or interface from which the method is accessed
+         * @param name the name of the method
+         * @param type the type of the method, with the receiver argument omitted
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails,
+         *                                or if the method is {@code static}
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            // TODO: Support varargs methods. The returned method handle must be a var-args
+            // collector in that case.
+
+            Method method = refc.getDeclaredMethod(name, type.ptypes());
+            final int modifiers = method.getModifiers();
+            if (Modifier.isStatic(modifiers)) {
+                throw new IllegalAccessException("Method" + method + " is static.");
+            }
+
+            checkAccess(refc, method.getDeclaringClass(), method.getModifiers(), method.getName());
+
+            // Insert the leading reference parameter.
+            MethodType handleType = type.insertParameterTypes(0, refc);
+            return new MethodHandleImpl(method.getArtMethod(), MethodHandle.INVOKE_VIRTUAL,
+                    handleType);
+        }
+
+        /**
+         * Produces a method handle which creates an object and initializes it, using
+         * the constructor of the specified type.
+         * The parameter types of the method handle will be those of the constructor,
+         * while the return type will be a reference to the constructor's class.
+         * The constructor and all its argument types must be accessible to the lookup object.
+         * <p>
+         * The requested type must have a return type of {@code void}.
+         * (This is consistent with the JVM's treatment of constructor type descriptors.)
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * If the returned method handle is invoked, the constructor's class will
+         * be initialized, if it has not already been initialized.
+         * <p><b>Example:</b>
+         * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle MH_newArrayList = publicLookup().findConstructor(
+  ArrayList.class, methodType(void.class, Collection.class));
+Collection orig = Arrays.asList("x", "y");
+Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
+assert(orig != copy);
+assertEquals(orig, copy);
+// a variable-arity constructor:
+MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
+  ProcessBuilder.class, methodType(void.class, String[].class));
+ProcessBuilder pb = (ProcessBuilder)
+  MH_newProcessBuilder.invoke("x", "y", "z");
+assertEquals("[x, y, z]", pb.command().toString());
+         * }</pre></blockquote>
+         * @param refc the class or interface from which the method is accessed
+         * @param type the type of the method, with the receiver argument omitted, and a void return type
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the constructor does not exist
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            // TODO: Support varargs methods. The returned method handle must be a var-args
+            // collector in that case.
+
+            if (type.returnType() != void.class) {
+                throw new NoSuchElementException("Unable to find constructor of type: " + type);
+            }
+
+            Constructor constructor = refc.getDeclaredConstructor(type.ptypes());
+            checkAccess(refc, constructor.getDeclaringClass(), constructor.getModifiers(),
+                    constructor.getName());
+
+            MethodType handleType = type.changeReturnType(refc);
+            return new MethodHandleImpl(constructor.getArtMethod(), MethodHandle.INVOKE_DIRECT, handleType);
+        }
+
+        /**
+         * Produces an early-bound method handle for a virtual method.
+         * It will bypass checks for overriding methods on the receiver,
+         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
+         * instruction from within the explicitly specified {@code specialCaller}.
+         * The type of the method handle will be that of the method,
+         * with a suitably restricted receiver type prepended.
+         * (The receiver type will be {@code specialCaller} or a subtype.)
+         * The method and all its argument types must be accessible
+         * to the lookup object.
+         * <p>
+         * Before method resolution,
+         * if the explicitly specified caller class is not identical with the
+         * lookup class, or if this lookup object does not have
+         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+         * privileges, the access fails.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p style="font-size:smaller;">
+         * <em>(Note:  JVM internal methods named {@code "<init>"} are not visible to this API,
+         * even though the {@code invokespecial} instruction can refer to them
+         * in special circumstances.  Use {@link #findConstructor findConstructor}
+         * to access instance initialization methods in a safe manner.)</em>
+         * <p><b>Example:</b>
+         * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+static class Listie extends ArrayList {
+  public String toString() { return "[wee Listie]"; }
+  static Lookup lookup() { return MethodHandles.lookup(); }
+}
+...
+// no access to constructor via invokeSpecial:
+MethodHandle MH_newListie = Listie.lookup()
+  .findConstructor(Listie.class, methodType(void.class));
+Listie l = (Listie) MH_newListie.invokeExact();
+try { assertEquals("impossible", Listie.lookup().findSpecial(
+        Listie.class, "<init>", methodType(void.class), Listie.class));
+ } catch (NoSuchMethodException ex) { } // OK
+// access to super and self methods via invokeSpecial:
+MethodHandle MH_super = Listie.lookup().findSpecial(
+  ArrayList.class, "toString" , methodType(String.class), Listie.class);
+MethodHandle MH_this = Listie.lookup().findSpecial(
+  Listie.class, "toString" , methodType(String.class), Listie.class);
+MethodHandle MH_duper = Listie.lookup().findSpecial(
+  Object.class, "toString" , methodType(String.class), Listie.class);
+assertEquals("[]", (String) MH_super.invokeExact(l));
+assertEquals(""+l, (String) MH_this.invokeExact(l));
+assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
+try { assertEquals("inaccessible", Listie.lookup().findSpecial(
+        String.class, "toString", methodType(String.class), Listie.class));
+ } catch (IllegalAccessException ex) { } // OK
+Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
+assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
+         * }</pre></blockquote>
+         *
+         * @param refc the class or interface from which the method is accessed
+         * @param name the name of the method (which must not be "&lt;init&gt;")
+         * @param type the type of the method, with the receiver argument omitted
+         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
+                                        Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.findSpecial is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving read access to a non-static field.
+         * The type of the method handle will have a return type of the field's
+         * value type.
+         * The method handle's single argument will be the instance containing
+         * the field.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can load values from the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.findGetter is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving write access to a non-static field.
+         * The type of the method handle will have a void return type.
+         * The method handle will take two arguments, the instance containing
+         * the field, and the value to be stored.
+         * The second argument will be of the field's value type.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can store values into the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.findSetter is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving read access to a static field.
+         * The type of the method handle will have a return type of the field's
+         * value type.
+         * The method handle will take no arguments.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * <p>
+         * If the returned method handle is invoked, the field's class will
+         * be initialized, if it has not already been initialized.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can load values from the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.findStaticGetter is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving write access to a static field.
+         * The type of the method handle will have a void return type.
+         * The method handle will take a single
+         * argument, of the field's value type, the value to be stored.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * <p>
+         * If the returned method handle is invoked, the field's class will
+         * be initialized, if it has not already been initialized.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can store values into the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.findStaticSetter is not implemented");
+        }
+
+        /**
+         * Produces an early-bound method handle for a non-static method.
+         * The receiver must have a supertype {@code defc} in which a method
+         * of the given name and type is accessible to the lookup class.
+         * The method and all its argument types must be accessible to the lookup object.
+         * The type of the method handle will be that of the method,
+         * without any insertion of an additional receiver parameter.
+         * The given receiver will be bound into the method handle,
+         * so that every call to the method handle will invoke the
+         * requested method on the given receiver.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set
+         * <em>and</em> the trailing array argument is not the only argument.
+         * (If the trailing array argument is the only argument,
+         * the given receiver value will be bound to it.)
+         * <p>
+         * This is equivalent to the following code:
+         * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle mh0 = lookup().findVirtual(defc, name, type);
+MethodHandle mh1 = mh0.bindTo(receiver);
+MethodType mt1 = mh1.type();
+if (mh0.isVarargsCollector())
+  mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
+return mh1;
+         * }</pre></blockquote>
+         * where {@code defc} is either {@code receiver.getClass()} or a super
+         * type of that class, in which the requested method is accessible
+         * to the lookup class.
+         * (Note that {@code bindTo} does not preserve variable arity.)
+         * @param receiver the object from which the method is accessed
+         * @param name the name of the method
+         * @param type the type of the method, with the receiver argument omitted
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         * @see MethodHandle#bindTo
+         * @see #findVirtual
+         */
+        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.bind is not implemented");
+        }
+
+        /**
+         * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
+         * to <i>m</i>, if the lookup class has permission.
+         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
+         * If <i>m</i> is virtual, overriding is respected on every call.
+         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
+         * The type of the method handle will be that of the method,
+         * with the receiver type prepended (but only if it is non-static).
+         * If the method's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * If <i>m</i> is static, and
+         * if the returned method handle is invoked, the method's class will
+         * be initialized, if it has not already been initialized.
+         * @param m the reflected method
+         * @return a method handle which can invoke the reflected method
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflect(Method m) throws IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.unreflect is not implemented");
+        }
+
+        /**
+         * Produces a method handle for a reflected method.
+         * It will bypass checks for overriding methods on the receiver,
+         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
+         * instruction from within the explicitly specified {@code specialCaller}.
+         * The type of the method handle will be that of the method,
+         * with a suitably restricted receiver type prepended.
+         * (The receiver type will be {@code specialCaller} or a subtype.)
+         * If the method's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class,
+         * as if {@code invokespecial} instruction were being linked.
+         * <p>
+         * Before method resolution,
+         * if the explicitly specified caller class is not identical with the
+         * lookup class, or if this lookup object does not have
+         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+         * privileges, the access fails.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param m the reflected method
+         * @param specialCaller the class nominally calling the method
+         * @return a method handle which can invoke the reflected method
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.unreflectSpecial is not implemented");
+        }
+
+        /**
+         * Produces a method handle for a reflected constructor.
+         * The type of the method handle will be that of the constructor,
+         * with the return type changed to the declaring class.
+         * The method handle will perform a {@code newInstance} operation,
+         * creating a new instance of the constructor's class on the
+         * arguments passed to the method handle.
+         * <p>
+         * If the constructor's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * If the returned method handle is invoked, the constructor's class will
+         * be initialized, if it has not already been initialized.
+         * @param c the reflected constructor
+         * @return a method handle which can invoke the reflected constructor
+         * @throws IllegalAccessException if access checking fails
+         *                                or if the method's variable arity modifier bit
+         *                                is set and {@code asVarargsCollector} fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.unreflectConstructor is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving read access to a reflected field.
+         * The type of the method handle will have a return type of the field's
+         * value type.
+         * If the field is static, the method handle will take no arguments.
+         * Otherwise, its single argument will be the instance containing
+         * the field.
+         * If the field's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * <p>
+         * If the field is static, and
+         * if the returned method handle is invoked, the field's class will
+         * be initialized, if it has not already been initialized.
+         * @param f the reflected field
+         * @return a method handle which can load values from the reflected field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.unreflectGetter is not implemented");
+        }
+
+        /**
+         * Produces a method handle giving write access to a reflected field.
+         * The type of the method handle will have a void return type.
+         * If the field is static, the method handle will take a single
+         * argument, of the field's value type, the value to be stored.
+         * Otherwise, the two arguments will be the instance containing
+         * the field, and the value to be stored.
+         * If the field's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * <p>
+         * If the field is static, and
+         * if the returned method handle is invoked, the field's class will
+         * be initialized, if it has not already been initialized.
+         * @param f the reflected field
+         * @return a method handle which can store values into the reflected field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
+            // TODO(narayan): Implement this method.
+            throw new UnsupportedOperationException("MethodHandles.Lookup.unreflectSetter is not implemented");
+        }
+
+        /**
+         * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
+         * created by this lookup object or a similar one.
+         * Security and access checks are performed to ensure that this lookup object
+         * is capable of reproducing the target method handle.
+         * This means that the cracking may fail if target is a direct method handle
+         * but was created by an unrelated lookup object.
+         * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>
+         * and was created by a lookup object for a different class.
+         * @param target a direct method handle to crack into symbolic reference components
+         * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
+         * @exception NullPointerException if the target is {@code null}
+         * @see MethodHandleInfo
+         * @since 1.8
+         */
+        public MethodHandleInfo revealDirect(MethodHandle target) {
+            // TODO(narayan): Implement this method.
+            //
+            // Notes: Only works for direct method handles. Must check access.
+            //
+            throw new UnsupportedOperationException("MethodHandles.Lookup.revealDirect is not implemented");
+        }
+
+        private boolean hasPrivateAccess() {
+            return (allowedModes & PRIVATE) != 0;
+        }
+
+        /** Check public/protected/private bits on the symbolic reference class and its member. */
+        void checkAccess(Class<?> refc, Class<?> defc, int mods, String methName)
+                throws IllegalAccessException {
+            int allowedModes = this.allowedModes;
+
+            if (Modifier.isProtected(mods) &&
+                    defc == Object.class &&
+                    "clone".equals(methName) &&
+                    refc.isArray()) {
+                // The JVM does this hack also.
+                // (See ClassVerifier::verify_invoke_instructions
+                // and LinkResolver::check_method_accessability.)
+                // Because the JVM does not allow separate methods on array types,
+                // there is no separate method for int[].clone.
+                // All arrays simply inherit Object.clone.
+                // But for access checking logic, we make Object.clone
+                // (normally protected) appear to be public.
+                // Later on, when the DirectMethodHandle is created,
+                // its leading argument will be restricted to the
+                // requested array type.
+                // N.B. The return type is not adjusted, because
+                // that is *not* the bytecode behavior.
+                mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
+            }
+
+            if (Modifier.isProtected(mods) && Modifier.isConstructor(mods)) {
+                // cannot "new" a protected ctor in a different package
+                mods ^= Modifier.PROTECTED;
+            }
+
+            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
+                return;  // common case
+            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
+            if ((requestedModes & allowedModes) != 0) {
+                if (VerifyAccess.isMemberAccessible(refc, defc, mods, lookupClass(), allowedModes))
+                    return;
+            } else {
+                // Protected members can also be checked as if they were package-private.
+                if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
+                        && VerifyAccess.isSamePackage(defc, lookupClass()))
+                    return;
+            }
+
+            throwMakeAccessException(accessFailedMessage(refc, defc, mods), this);
+        }
+
+        String accessFailedMessage(Class<?> refc, Class<?> defc, int mods) {
+            // check the class first:
+            boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
+                    (defc == refc ||
+                            Modifier.isPublic(refc.getModifiers())));
+            if (!classOK && (allowedModes & PACKAGE) != 0) {
+                classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) &&
+                        (defc == refc ||
+                                VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES)));
+            }
+            if (!classOK)
+                return "class is not public";
+            if (Modifier.isPublic(mods))
+                return "access to public member failed";  // (how?)
+            if (Modifier.isPrivate(mods))
+                return "member is private";
+            if (Modifier.isProtected(mods))
+                return "member is protected";
+            return "member is private to package";
+        }
+
+        private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+        private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
+            int allowedModes = this.allowedModes;
+            // Android-changed: No support for TRUSTED lookups.
+            // if (allowedModes == TRUSTED)  return;
+            if (!hasPrivateAccess()
+                    || (specialCaller != lookupClass()
+                    && !(ALLOW_NESTMATE_ACCESS &&
+                    VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
+                throwMakeAccessException("no private access for invokespecial", this);
+        }
+
+        public void throwMakeAccessException(String message, Object from) throws
+                IllegalAccessException{
+            message = message + ": "+ toString();
+            if (from != null)  message += ", from " + from;
+            throw new IllegalAccessException(message);
+        }
+    }
+
+    /**
+     * Produces a method handle giving read access to elements of an array.
+     * The type of the method handle will have a return type of the array's
+     * element type.  Its first argument will be the array type,
+     * and the second will be {@code int}.
+     * @param arrayClass an array type
+     * @return a method handle which can load values from the given array type
+     * @throws NullPointerException if the argument is null
+     * @throws  IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
+        // return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.arrayElementGetter is not implemented");
+    }
+
+    /**
+     * Produces a method handle giving write access to elements of an array.
+     * The type of the method handle will have a void return type.
+     * Its last argument will be the array's element type.
+     * The first and second arguments will be the array type and int.
+     * @param arrayClass the class of an array
+     * @return a method handle which can store values into the array type
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
+        // return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.arrayElementSetter is not implemented");
+    }
+
+    /// method handle invocation (reflective style)
+
+    /**
+     * Produces a method handle which will invoke any method handle of the
+     * given {@code type}, with a given number of trailing arguments replaced by
+     * a single trailing {@code Object[]} array.
+     * The resulting invoker will be a method handle with the following
+     * arguments:
+     * <ul>
+     * <li>a single {@code MethodHandle} target
+     * <li>zero or more leading values (counted by {@code leadingArgCount})
+     * <li>an {@code Object[]} array containing trailing arguments
+     * </ul>
+     * <p>
+     * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with
+     * the indicated {@code type}.
+     * That is, if the target is exactly of the given {@code type}, it will behave
+     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
+     * is used to convert the target to the required {@code type}.
+     * <p>
+     * The type of the returned invoker will not be the given {@code type}, but rather
+     * will have all parameters except the first {@code leadingArgCount}
+     * replaced by a single array of type {@code Object[]}, which will be
+     * the final parameter.
+     * <p>
+     * Before invoking its target, the invoker will spread the final array, apply
+     * reference casts as necessary, and unbox and widen primitive arguments.
+     * If, when the invoker is called, the supplied array argument does
+     * not have the correct number of elements, the invoker will throw
+     * an {@link IllegalArgumentException} instead of invoking the target.
+     * <p>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * <blockquote><pre>{@code
+MethodHandle invoker = MethodHandles.invoker(type);
+int spreadArgCount = type.parameterCount() - leadingArgCount;
+invoker = invoker.asSpreader(Object[].class, spreadArgCount);
+return invoker;
+     * }</pre></blockquote>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
+     * @return a method handle suitable for invoking any method handle of the given type
+     * @throws NullPointerException if {@code type} is null
+     * @throws IllegalArgumentException if {@code leadingArgCount} is not in
+     *                  the range from 0 to {@code type.parameterCount()} inclusive,
+     *                  or if the resulting method handle's type would have
+     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+     */
+    static public
+    MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
+        if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
+            throw newIllegalArgumentException("bad argument count", leadingArgCount);
+        type = type.asSpreaderType(Object[].class, type.parameterCount() - leadingArgCount);
+        // return type.invokers().spreadInvoker(leadingArgCount);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.spreadInvoker is not implemented");
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
+     * The resulting invoker will have a type which is
+     * exactly equal to the desired type, except that it will accept
+     * an additional leading argument of type {@code MethodHandle}.
+     * <p>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
+     *
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * Invoker method handles can be useful when working with variable method handles
+     * of unknown types.
+     * For example, to emulate an {@code invokeExact} call to a variable method
+     * handle {@code M}, extract its type {@code T},
+     * look up the invoker method {@code X} for {@code T},
+     * and call the invoker method, as {@code X.invoke(T, A...)}.
+     * (It would not work to call {@code X.invokeExact}, since the type {@code T}
+     * is unknown.)
+     * If spreading, collecting, or other argument transformations are required,
+     * they can be applied once to the invoker {@code X} and reused on many {@code M}
+     * method handle values, as long as they are compatible with the type of {@code X}.
+     * <p style="font-size:smaller;">
+     * <em>(Note:  The invoker method is not available via the Core Reflection API.
+     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
+     * on the declared {@code invokeExact} or {@code invoke} method will raise an
+     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
+     * <p>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @return a method handle suitable for invoking any method handle of the given type
+     * @throws IllegalArgumentException if the resulting method handle's type would have
+     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+     */
+    static public
+    MethodHandle exactInvoker(MethodType type) {
+        // return type.invokers().exactInvoker();
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.exactInvoker is not implemented");
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
+     * The resulting invoker will have a type which is
+     * exactly equal to the desired type, except that it will accept
+     * an additional leading argument of type {@code MethodHandle}.
+     * <p>
+     * Before invoking its target, if the target differs from the expected type,
+     * the invoker will apply reference casts as
+     * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
+     * Similarly, the return value will be converted as necessary.
+     * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
+     * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
+     * <p>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)}
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * A {@linkplain MethodType#genericMethodType general method type} is one which
+     * mentions only {@code Object} arguments and return values.
+     * An invoker for such a type is capable of calling any method handle
+     * of the same arity as the general type.
+     * <p style="font-size:smaller;">
+     * <em>(Note:  The invoker method is not available via the Core Reflection API.
+     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
+     * on the declared {@code invokeExact} or {@code invoke} method will raise an
+     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
+     * <p>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @return a method handle suitable for invoking any method handle convertible to the given type
+     * @throws IllegalArgumentException if the resulting method handle's type would have
+     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+     */
+    static public
+    MethodHandle invoker(MethodType type) {
+        // return type.invokers().genericInvoker();
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.invoker is not implemented");
+    }
+
+    // Android-changed: Basic invokers are not supported.
+    //
+    // static /*non-public*/
+    // MethodHandle basicInvoker(MethodType type) {
+    //     return type.invokers().basicInvoker();
+    // }
+
+     /// method handle modification (creation from other method handles)
+
+    /**
+     * Produces a method handle which adapts the type of the
+     * given method handle to a new type by pairwise argument and return type conversion.
+     * The original type and new type must have the same number of arguments.
+     * The resulting method handle is guaranteed to report a type
+     * which is equal to the desired new type.
+     * <p>
+     * If the original type and new type are equal, returns target.
+     * <p>
+     * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType},
+     * and some additional conversions are also applied if those conversions fail.
+     * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied
+     * if possible, before or instead of any conversions done by {@code asType}:
+     * <ul>
+     * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type,
+     *     then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast.
+     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
+     * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive,
+     *     the boolean is converted to a byte value, 1 for true, 0 for false.
+     *     (This treatment follows the usage of the bytecode verifier.)
+     * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive,
+     *     <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5),
+     *     and the low order bit of the result is tested, as if by {@code (x & 1) != 0}.
+     * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean,
+     *     then a Java casting conversion (JLS 5.5) is applied.
+     *     (Specifically, <em>T0</em> will convert to <em>T1</em> by
+     *     widening and/or narrowing.)
+     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
+     *     conversion will be applied at runtime, possibly followed
+     *     by a Java casting conversion (JLS 5.5) on the primitive value,
+     *     possibly followed by a conversion from byte to boolean by testing
+     *     the low-order bit.
+     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive,
+     *     and if the reference is null at runtime, a zero value is introduced.
+     * </ul>
+     * @param target the method handle to invoke after arguments are retyped
+     * @param newType the expected type of the new method handle
+     * @return a method handle which delegates to the target after performing
+     *           any necessary argument conversions, and arranges for any
+     *           necessary return value conversions
+     * @throws NullPointerException if either argument is null
+     * @throws WrongMethodTypeException if the conversion cannot be made
+     * @see MethodHandle#asType
+     */
+    public static
+    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+        explicitCastArgumentsChecks(target, newType);
+        // use the asTypeCache when possible:
+        MethodType oldType = target.type();
+        if (oldType == newType)  return target;
+        if (oldType.explicitCastEquivalentToAsType(newType)) {
+            return target.asFixedArity().asType(newType);
+        }
+
+        // return MethodHandleImpl.makePairwiseConvert(target, newType, false);
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.explicitCastArguments is not implemented");
+    }
+
+    private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) {
+        if (target.type().parameterCount() != newType.parameterCount()) {
+            throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType);
+        }
+    }
+
+    /**
+     * Produces a method handle which adapts the calling sequence of the
+     * given method handle to a new type, by reordering the arguments.
+     * The resulting method handle is guaranteed to report a type
+     * which is equal to the desired new type.
+     * <p>
+     * The given array controls the reordering.
+     * Call {@code #I} the number of incoming parameters (the value
+     * {@code newType.parameterCount()}, and call {@code #O} the number
+     * of outgoing parameters (the value {@code target.type().parameterCount()}).
+     * Then the length of the reordering array must be {@code #O},
+     * and each element must be a non-negative number less than {@code #I}.
+     * For every {@code N} less than {@code #O}, the {@code N}-th
+     * outgoing argument will be taken from the {@code I}-th incoming
+     * argument, where {@code I} is {@code reorder[N]}.
+     * <p>
+     * No argument or return value conversions are applied.
+     * The type of each incoming argument, as determined by {@code newType},
+     * must be identical to the type of the corresponding outgoing parameter
+     * or parameters in the target method handle.
+     * The return type of {@code newType} must be identical to the return
+     * type of the original target.
+     * <p>
+     * The reordering array need not specify an actual permutation.
+     * An incoming argument will be duplicated if its index appears
+     * more than once in the array, and an incoming argument will be dropped
+     * if its index does not appear in the array.
+     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
+     * incoming arguments which are not mentioned in the reordering array
+     * are may be any type, as determined only by {@code newType}.
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodType intfn1 = methodType(int.class, int.class);
+MethodType intfn2 = methodType(int.class, int.class, int.class);
+MethodHandle sub = ... (int x, int y) -> (x-y) ...;
+assert(sub.type().equals(intfn2));
+MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
+MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
+assert((int)rsub.invokeExact(1, 100) == 99);
+MethodHandle add = ... (int x, int y) -> (x+y) ...;
+assert(add.type().equals(intfn2));
+MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
+assert(twice.type().equals(intfn1));
+assert((int)twice.invokeExact(21) == 42);
+     * }</pre></blockquote>
+     * @param target the method handle to invoke after arguments are reordered
+     * @param newType the expected type of the new method handle
+     * @param reorder an index array which controls the reordering
+     * @return a method handle which delegates to the target after it
+     *           drops unused arguments and moves and/or duplicates the other arguments
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if the index array length is not equal to
+     *                  the arity of the target, or if any index array element
+     *                  not a valid index for a parameter of {@code newType},
+     *                  or if two corresponding parameter types in
+     *                  {@code target.type()} and {@code newType} are not identical,
+     */
+    public static
+    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
+        reorder = reorder.clone();  // get a private copy
+        MethodType oldType = target.type();
+        permuteArgumentChecks(reorder, newType, oldType);
+
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.permuteArguments is not implemented");
+    }
+
+    // Android-changed: findFirstDupOrDrop is unused and removed.
+    // private static int findFirstDupOrDrop(int[] reorder, int newArity);
+
+    private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) {
+        if (newType.returnType() != oldType.returnType())
+            throw newIllegalArgumentException("return types do not match",
+                    oldType, newType);
+        if (reorder.length == oldType.parameterCount()) {
+            int limit = newType.parameterCount();
+            boolean bad = false;
+            for (int j = 0; j < reorder.length; j++) {
+                int i = reorder[j];
+                if (i < 0 || i >= limit) {
+                    bad = true; break;
+                }
+                Class<?> src = newType.parameterType(i);
+                Class<?> dst = oldType.parameterType(j);
+                if (src != dst)
+                    throw newIllegalArgumentException("parameter types do not match after reorder",
+                            oldType, newType);
+            }
+            if (!bad)  return true;
+        }
+        throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
+    }
+
+    /**
+     * Produces a method handle of the requested return type which returns the given
+     * constant value every time it is invoked.
+     * <p>
+     * Before the method handle is returned, the passed-in value is converted to the requested type.
+     * If the requested type is primitive, widening primitive conversions are attempted,
+     * else reference conversions are attempted.
+     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}.
+     * @param type the return type of the desired method handle
+     * @param value the value to return
+     * @return a method handle of the given return type and no arguments, which always returns the given value
+     * @throws NullPointerException if the {@code type} argument is null
+     * @throws ClassCastException if the value cannot be converted to the required return type
+     * @throws IllegalArgumentException if the given type is {@code void.class}
+     */
+    public static
+    MethodHandle constant(Class<?> type, Object value) {
+        if (type.isPrimitive()) {
+            if (type == void.class)
+                throw newIllegalArgumentException("void type");
+            Wrapper w = Wrapper.forPrimitiveType(type);
+            value = w.convert(value, type);
+            if (w.zero().equals(value))
+                return zero(w, type);
+            return insertArguments(identity(type), 0, value);
+        } else {
+            if (value == null)
+                return zero(Wrapper.OBJECT, type);
+            return identity(type).bindTo(value);
+        }
+    }
+
+    /**
+     * Produces a method handle which returns its sole argument when invoked.
+     * @param type the type of the sole parameter and return value of the desired method handle
+     * @return a unary method handle which accepts and returns the given type
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if the given type is {@code void.class}
+     */
+    public static
+    MethodHandle identity(Class<?> type) {
+        Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT);
+        int pos = btw.ordinal();
+        MethodHandle ident = IDENTITY_MHS[pos];
+        if (ident == null) {
+            ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType()));
+        }
+        if (ident.type().returnType() == type)
+            return ident;
+        // something like identity(Foo.class); do not bother to intern these
+        assert(btw == Wrapper.OBJECT);
+        return makeIdentity(type);
+    }
+    private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
+    private static MethodHandle makeIdentity(Class<?> ptype) {
+        // MethodType mtype = MethodType.methodType(ptype, ptype);
+        // LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
+        // return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.makeIdentity is not implemented");
+    }
+
+    private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
+        int pos = btw.ordinal();
+        MethodHandle zero = ZERO_MHS[pos];
+        if (zero == null) {
+            zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
+        }
+        if (zero.type().returnType() == rtype)
+            return zero;
+        assert(btw == Wrapper.OBJECT);
+        return makeZero(rtype);
+    }
+    private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
+    private static MethodHandle makeZero(Class<?> rtype) {
+        // MethodType mtype = MethodType.methodType(rtype);
+        // LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
+        // return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.makeZero is not implemented");
+    }
+
+    synchronized private static MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = cache[pos];
+        if (prev != null) return prev;
+        return cache[pos] = value;
+    }
+
+    /**
+     * Provides a target method handle with one or more <em>bound arguments</em>
+     * in advance of the method handle's invocation.
+     * The formal parameters to the target corresponding to the bound
+     * arguments are called <em>bound parameters</em>.
+     * Returns a new method handle which saves away the bound arguments.
+     * When it is invoked, it receives arguments for any non-bound parameters,
+     * binds the saved arguments to their corresponding parameters,
+     * and calls the original target.
+     * <p>
+     * The type of the new method handle will drop the types for the bound
+     * parameters from the original target type, since the new method handle
+     * will no longer require those arguments to be supplied by its callers.
+     * <p>
+     * Each given argument object must match the corresponding bound parameter type.
+     * If a bound parameter type is a primitive, the argument object
+     * must be a wrapper, and will be unboxed to produce the primitive value.
+     * <p>
+     * The {@code pos} argument selects which parameters are to be bound.
+     * It may range between zero and <i>N-L</i> (inclusively),
+     * where <i>N</i> is the arity of the target method handle
+     * and <i>L</i> is the length of the values array.
+     * @param target the method handle to invoke after the argument is inserted
+     * @param pos where to insert the argument (zero for the first)
+     * @param values the series of arguments to insert
+     * @return a method handle which inserts an additional argument,
+     *         before calling the original method handle
+     * @throws NullPointerException if the target or the {@code values} array is null
+     * @see MethodHandle#bindTo
+     */
+    public static
+    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
+        int insCount = values.length;
+        Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos);
+        if (insCount == 0)  return target;
+
+        // BoundMethodHandle result = target.rebind();
+        // for (int i = 0; i < insCount; i++) {
+        //     Object value = values[i];
+        //     Class<?> ptype = ptypes[pos+i];
+        //     if (ptype.isPrimitive()) {
+        //         result = insertArgumentPrimitive(result, pos, ptype, value);
+        //     } else {
+        //         value = ptype.cast(value);  // throw CCE if needed
+        //         result = result.bindArgumentL(pos, value);
+        //     }
+        // }
+        // return result;
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.insertArguments is not implemented");
+    }
+
+    // Android-changed: insertArgumentPrimitive is unused.
+    //
+    // private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos,
+    //                                                          Class<?> ptype, Object value) {
+    //     Wrapper w = Wrapper.forPrimitiveType(ptype);
+    //     // perform unboxing and/or primitive conversion
+    //     value = w.convert(value, ptype);
+    //     switch (w) {
+    //     case INT:     return result.bindArgumentI(pos, (int)value);
+    //     case LONG:    return result.bindArgumentJ(pos, (long)value);
+    //     case FLOAT:   return result.bindArgumentF(pos, (float)value);
+    //     case DOUBLE:  return result.bindArgumentD(pos, (double)value);
+    //     default:      return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
+    //     }
+    // }
+
+    private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
+        MethodType oldType = target.type();
+        int outargs = oldType.parameterCount();
+        int inargs  = outargs - insCount;
+        if (inargs < 0)
+            throw newIllegalArgumentException("too many values to insert");
+        if (pos < 0 || pos > inargs)
+            throw newIllegalArgumentException("no argument type to append");
+        return oldType.ptypes();
+    }
+
+    /**
+     * Produces a method handle which will discard some dummy arguments
+     * before calling some other specified <i>target</i> method handle.
+     * The type of the new method handle will be the same as the target's type,
+     * except it will also include the dummy argument types,
+     * at some given position.
+     * <p>
+     * The {@code pos} argument may range between zero and <i>N</i>,
+     * where <i>N</i> is the arity of the target.
+     * If {@code pos} is zero, the dummy arguments will precede
+     * the target's real arguments; if {@code pos} is <i>N</i>
+     * they will come after.
+     * <p>
+     * <b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+     * }</pre></blockquote>
+     * <p>
+     * This method is also equivalent to the following code:
+     * <blockquote><pre>
+     * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))}
+     * </pre></blockquote>
+     * @param target the method handle to invoke after the arguments are dropped
+     * @param valueTypes the type(s) of the argument(s) to drop
+     * @param pos position of first argument to drop (zero for the leftmost)
+     * @return a method handle which drops arguments of the given types,
+     *         before calling the original method handle
+     * @throws NullPointerException if the target is null,
+     *                              or if the {@code valueTypes} list or any of its elements is null
+     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
+     *                  or if {@code pos} is negative or greater than the arity of the target,
+     *                  or if the new method handle's type would have too many parameters
+     */
+    public static
+    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
+        MethodType oldType = target.type();  // get NPE
+        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
+
+        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
+        // if (dropped == 0)  return target;
+        // BoundMethodHandle result = target.rebind();
+        // LambdaForm lform = result.form;
+        // int insertFormArg = 1 + pos;
+        // for (Class<?> ptype : valueTypes) {
+        //     lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype));
+        // }
+        // result = result.copyWith(newType, lform);
+        // return result;
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.dropArguments is not implemented");
+    }
+
+    private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
+        int dropped = valueTypes.size();
+        MethodType.checkSlotCount(dropped);
+        int outargs = oldType.parameterCount();
+        int inargs  = outargs + dropped;
+        if (pos < 0 || pos > outargs)
+            throw newIllegalArgumentException("no argument type to remove"
+                    + Arrays.asList(oldType, pos, valueTypes, inargs, outargs)
+                    );
+        return dropped;
+    }
+
+    /**
+     * Produces a method handle which will discard some dummy arguments
+     * before calling some other specified <i>target</i> method handle.
+     * The type of the new method handle will be the same as the target's type,
+     * except it will also include the dummy argument types,
+     * at some given position.
+     * <p>
+     * The {@code pos} argument may range between zero and <i>N</i>,
+     * where <i>N</i> is the arity of the target.
+     * If {@code pos} is zero, the dummy arguments will precede
+     * the target's real arguments; if {@code pos} is <i>N</i>
+     * they will come after.
+     * <p>
+     * <b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+     * }</pre></blockquote>
+     * <p>
+     * This method is also equivalent to the following code:
+     * <blockquote><pre>
+     * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
+     * </pre></blockquote>
+     * @param target the method handle to invoke after the arguments are dropped
+     * @param valueTypes the type(s) of the argument(s) to drop
+     * @param pos position of first argument to drop (zero for the leftmost)
+     * @return a method handle which drops arguments of the given types,
+     *         before calling the original method handle
+     * @throws NullPointerException if the target is null,
+     *                              or if the {@code valueTypes} array or any of its elements is null
+     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
+     *                  or if {@code pos} is negative or greater than the arity of the target,
+     *                  or if the new method handle's type would have
+     *                  <a href="MethodHandle.html#maxarity">too many parameters</a>
+     */
+    public static
+    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+        return dropArguments(target, pos, Arrays.asList(valueTypes));
+    }
+
+    /**
+     * Adapts a target method handle by pre-processing
+     * one or more of its arguments, each with its own unary filter function,
+     * and then calling the target with each pre-processed argument
+     * replaced by the result of its corresponding filter function.
+     * <p>
+     * The pre-processing is performed by one or more method handles,
+     * specified in the elements of the {@code filters} array.
+     * The first element of the filter array corresponds to the {@code pos}
+     * argument of the target, and so on in sequence.
+     * <p>
+     * Null arguments in the array are treated as identity functions,
+     * and the corresponding arguments left unchanged.
+     * (If there are no non-null elements in the array, the original target is returned.)
+     * Each filter is applied to the corresponding argument of the adapter.
+     * <p>
+     * If a filter {@code F} applies to the {@code N}th argument of
+     * the target, then {@code F} must be a method handle which
+     * takes exactly one argument.  The type of {@code F}'s sole argument
+     * replaces the corresponding argument type of the target
+     * in the resulting adapted method handle.
+     * The return type of {@code F} must be identical to the corresponding
+     * parameter type of the target.
+     * <p>
+     * It is an error if there are elements of {@code filters}
+     * (null or not)
+     * which do not correspond to argument positions in the target.
+     * <p><b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+  "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+     * }</pre></blockquote>
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * V target(P... p, A[i]... a[i], B... b);
+     * A[i] filter[i](V[i]);
+     * T adapter(P... p, V[i]... v[i], B... b) {
+     *   return target(p..., f[i](v[i])..., b...);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param target the method handle to invoke after arguments are filtered
+     * @param pos the position of the first argument to filter
+     * @param filters method handles to call initially on filtered arguments
+     * @return method handle which incorporates the specified argument filtering logic
+     * @throws NullPointerException if the target is null
+     *                              or if the {@code filters} array is null
+     * @throws IllegalArgumentException if a non-null element of {@code filters}
+     *          does not match a corresponding argument type of target as described above,
+     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
+     *          or if the resulting method handle's type would have
+     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+     */
+    public static
+    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
+        filterArgumentsCheckArity(target, pos, filters);
+        MethodHandle adapter = target;
+        int curPos = pos-1;  // pre-incremented
+        for (MethodHandle filter : filters) {
+            curPos += 1;
+            if (filter == null)  continue;  // ignore null elements of filters
+            adapter = filterArgument(adapter, curPos, filter);
+        }
+        return adapter;
+    }
+
+    /*non-public*/ static
+    MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
+        filterArgumentChecks(target, pos, filter);
+        // MethodType targetType = target.type();
+        // MethodType filterType = filter.type();
+        // BoundMethodHandle result = target.rebind();
+        // Class<?> newParamType = filterType.parameterType(0);
+        // LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
+        // MethodType newType = targetType.changeParameterType(pos, newParamType);
+        // result = result.copyWithExtendL(newType, lform, filter);
+        // return result;
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.filterArgument is not implemented");
+    }
+
+    private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
+        MethodType targetType = target.type();
+        int maxPos = targetType.parameterCount();
+        if (pos + filters.length > maxPos)
+            throw newIllegalArgumentException("too many filters");
+    }
+
+    private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
+        MethodType targetType = target.type();
+        MethodType filterType = filter.type();
+        if (filterType.parameterCount() != 1
+            || filterType.returnType() != targetType.parameterType(pos))
+            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
+    }
+
+    /**
+     * Adapts a target method handle by pre-processing
+     * a sub-sequence of its arguments with a filter (another method handle).
+     * The pre-processed arguments are replaced by the result (if any) of the
+     * filter function.
+     * The target is then called on the modified (usually shortened) argument list.
+     * <p>
+     * If the filter returns a value, the target must accept that value as
+     * its argument in position {@code pos}, preceded and/or followed by
+     * any arguments not passed to the filter.
+     * If the filter returns void, the target must accept all arguments
+     * not passed to the filter.
+     * No arguments are reordered, and a result returned from the filter
+     * replaces (in order) the whole subsequence of arguments originally
+     * passed to the adapter.
+     * <p>
+     * The argument types (if any) of the filter
+     * replace zero or one argument types of the target, at position {@code pos},
+     * in the resulting adapted method handle.
+     * The return type of the filter (if any) must be identical to the
+     * argument type of the target at position {@code pos}, and that target argument
+     * is supplied by the return value of the filter.
+     * <p>
+     * In all cases, {@code pos} must be greater than or equal to zero, and
+     * {@code pos} must also be less than or equal to the target's arity.
+     * <p><b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle deepToString = publicLookup()
+  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
+
+MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
+assertEquals("[strange]", (String) ts1.invokeExact("strange"));
+
+MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
+assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
+
+MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
+MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
+assertEquals("[top, [up, down], strange]",
+             (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
+
+MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
+assertEquals("[top, [up, down], [strange]]",
+             (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
+
+MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
+assertEquals("[top, [[up, down, strange], charm], bottom]",
+             (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
+     * }</pre></blockquote>
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * T target(A...,V,C...);
+     * V filter(B...);
+     * T adapter(A... a,B... b,C... c) {
+     *   V v = filter(b...);
+     *   return target(a...,v,c...);
+     * }
+     * // and if the filter has no arguments:
+     * T target2(A...,V,C...);
+     * V filter2();
+     * T adapter2(A... a,C... c) {
+     *   V v = filter2();
+     *   return target2(a...,v,c...);
+     * }
+     * // and if the filter has a void return:
+     * T target3(A...,C...);
+     * void filter3(B...);
+     * void adapter3(A... a,B... b,C... c) {
+     *   filter3(b...);
+     *   return target3(a...,c...);
+     * }
+     * }</pre></blockquote>
+     * <p>
+     * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
+     * one which first "folds" the affected arguments, and then drops them, in separate
+     * steps as follows:
+     * <blockquote><pre>{@code
+     * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
+     * mh = MethodHandles.foldArguments(mh, coll); //step 1
+     * }</pre></blockquote>
+     * If the target method handle consumes no arguments besides than the result
+     * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
+     * is equivalent to {@code filterReturnValue(coll, mh)}.
+     * If the filter method handle {@code coll} consumes one argument and produces
+     * a non-void result, then {@code collectArguments(mh, N, coll)}
+     * is equivalent to {@code filterArguments(mh, N, coll)}.
+     * Other equivalences are possible but would require argument permutation.
+     *
+     * @param target the method handle to invoke after filtering the subsequence of arguments
+     * @param pos the position of the first adapter argument to pass to the filter,
+     *            and/or the target argument which receives the result of the filter
+     * @param filter method handle to call on the subsequence of arguments
+     * @return method handle which incorporates the specified argument subsequence filtering logic
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if the return type of {@code filter}
+     *          is non-void and is not the same as the {@code pos} argument of the target,
+     *          or if {@code pos} is not between 0 and the target's arity, inclusive,
+     *          or if the resulting method handle's type would have
+     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+     * @see MethodHandles#foldArguments
+     * @see MethodHandles#filterArguments
+     * @see MethodHandles#filterReturnValue
+     */
+    public static
+    MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
+        MethodType newType = collectArgumentsChecks(target, pos, filter);
+        MethodType collectorType = filter.type();
+
+        // BoundMethodHandle result = target.rebind();
+        // LambdaForm lform;
+        // if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) {
+        //     lform = result.editor().collectArgumentArrayForm(1 + pos, filter);
+        //     if (lform != null) {
+        //         return result.copyWith(newType, lform);
+        //     }
+        // }
+        // lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType());
+        // return result.copyWithExtendL(newType, lform, filter);
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.collectArguments is not implemented");
+    }
+
+    private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
+        MethodType targetType = target.type();
+        MethodType filterType = filter.type();
+        Class<?> rtype = filterType.returnType();
+        List<Class<?>> filterArgs = filterType.parameterList();
+        if (rtype == void.class) {
+            return targetType.insertParameterTypes(pos, filterArgs);
+        }
+        if (rtype != targetType.parameterType(pos)) {
+            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
+        }
+        return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs);
+    }
+
+    /**
+     * Adapts a target method handle by post-processing
+     * its return value (if any) with a filter (another method handle).
+     * The result of the filter is returned from the adapter.
+     * <p>
+     * If the target returns a value, the filter must accept that value as
+     * its only argument.
+     * If the target returns void, the filter must accept no arguments.
+     * <p>
+     * The return type of the filter
+     * replaces the return type of the target
+     * in the resulting adapted method handle.
+     * The argument type of the filter (if any) must be identical to the
+     * return type of the target.
+     * <p><b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle length = lookup().findVirtual(String.class,
+  "length", methodType(int.class));
+System.out.println((String) cat.invokeExact("x", "y")); // xy
+MethodHandle f0 = filterReturnValue(cat, length);
+System.out.println((int) f0.invokeExact("x", "y")); // 2
+     * }</pre></blockquote>
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * V target(A...);
+     * T filter(V);
+     * T adapter(A... a) {
+     *   V v = target(a...);
+     *   return filter(v);
+     * }
+     * // and if the target has a void return:
+     * void target2(A...);
+     * T filter2();
+     * T adapter2(A... a) {
+     *   target2(a...);
+     *   return filter2();
+     * }
+     * // and if the filter has a void return:
+     * V target3(A...);
+     * void filter3(V);
+     * void adapter3(A... a) {
+     *   V v = target3(a...);
+     *   filter3(v);
+     * }
+     * }</pre></blockquote>
+     * @param target the method handle to invoke before filtering the return value
+     * @param filter method handle to call on the return value
+     * @return method handle which incorporates the specified return value filtering logic
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if the argument list of {@code filter}
+     *          does not match the return type of target as described above
+     */
+    public static
+    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
+        MethodType targetType = target.type();
+        MethodType filterType = filter.type();
+        filterReturnValueChecks(targetType, filterType);
+
+        // BoundMethodHandle result = target.rebind();
+        // BasicType rtype = BasicType.basicType(filterType.returnType());
+        // LambdaForm lform = result.editor().filterReturnForm(rtype, false);
+        // MethodType newType = targetType.changeReturnType(filterType.returnType());
+        // result = result.copyWithExtendL(newType, lform, filter);
+        // return result;
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.filterReturnValue is not implemented");
+    }
+
+    private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException {
+        Class<?> rtype = targetType.returnType();
+        int filterValues = filterType.parameterCount();
+        if (filterValues == 0
+                ? (rtype != void.class)
+                : (rtype != filterType.parameterType(0)))
+            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
+    }
+
+    /**
+     * Adapts a target method handle by pre-processing
+     * some of its arguments, and then calling the target with
+     * the result of the pre-processing, inserted into the original
+     * sequence of arguments.
+     * <p>
+     * The pre-processing is performed by {@code combiner}, a second method handle.
+     * Of the arguments passed to the adapter, the first {@code N} arguments
+     * are copied to the combiner, which is then called.
+     * (Here, {@code N} is defined as the parameter count of the combiner.)
+     * After this, control passes to the target, with any result
+     * from the combiner inserted before the original {@code N} incoming
+     * arguments.
+     * <p>
+     * If the combiner returns a value, the first parameter type of the target
+     * must be identical with the return type of the combiner, and the next
+     * {@code N} parameter types of the target must exactly match the parameters
+     * of the combiner.
+     * <p>
+     * If the combiner has a void return, no result will be inserted,
+     * and the first {@code N} parameter types of the target
+     * must exactly match the parameters of the combiner.
+     * <p>
+     * The resulting adapter is the same type as the target, except that the
+     * first parameter type is dropped,
+     * if it corresponds to the result of the combiner.
+     * <p>
+     * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
+     * that either the combiner or the target does not wish to receive.
+     * If some of the incoming arguments are destined only for the combiner,
+     * consider using {@link MethodHandle#asCollector asCollector} instead, since those
+     * arguments will not need to be live on the stack on entry to the
+     * target.)
+     * <p><b>Example:</b>
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+  "println", methodType(void.class, String.class))
+    .bindTo(System.out);
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+MethodHandle catTrace = foldArguments(cat, trace);
+// also prints "boo":
+assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+     * }</pre></blockquote>
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * // there are N arguments in A...
+     * T target(V, A[N]..., B...);
+     * V combiner(A...);
+     * T adapter(A... a, B... b) {
+     *   V v = combiner(a...);
+     *   return target(v, a..., b...);
+     * }
+     * // and if the combiner has a void return:
+     * T target2(A[N]..., B...);
+     * void combiner2(A...);
+     * T adapter2(A... a, B... b) {
+     *   combiner2(a...);
+     *   return target2(a..., b...);
+     * }
+     * }</pre></blockquote>
+     * @param target the method handle to invoke after arguments are combined
+     * @param combiner method handle to call initially on the incoming arguments
+     * @return method handle which incorporates the specified argument folding logic
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if {@code combiner}'s return type
+     *          is non-void and not the same as the first argument type of
+     *          the target, or if the initial {@code N} argument types
+     *          of the target
+     *          (skipping one matching the {@code combiner}'s return type)
+     *          are not identical with the argument types of {@code combiner}
+     */
+    public static
+    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
+        int foldPos = 0;
+        MethodType targetType = target.type();
+        MethodType combinerType = combiner.type();
+        Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
+
+        // BoundMethodHandle result = target.rebind();
+        // boolean dropResult = (rtype == void.class);
+        // // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
+        // LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType());
+        // MethodType newType = targetType;
+        // if (!dropResult)
+        //     newType = newType.dropParameterTypes(foldPos, foldPos + 1);
+        // result = result.copyWithExtendL(newType, lform, combiner);
+        // return result;
+
+        // TODO(narayan): Implement this method.
+        throw new UnsupportedOperationException("MethodHandles.foldArguments is not implemented");
+    }
+
+    private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
+        int foldArgs   = combinerType.parameterCount();
+        Class<?> rtype = combinerType.returnType();
+        int foldVals = rtype == void.class ? 0 : 1;
+        int afterInsertPos = foldPos + foldVals;
+        boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
+        if (ok && !(combinerType.parameterList()
+                    .equals(targetType.parameterList().subList(afterInsertPos,
+                                                               afterInsertPos + foldArgs))))
+            ok = false;
+        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
+            ok = false;
+        if (!ok)
+            throw misMatchedTypes("target and combiner types", targetType, combinerType);
+        return rtype;
+    }
+
+    /**
+     * Makes a method handle which adapts a target method handle,
+     * by guarding it with a test, a boolean-valued method handle.
+     * If the guard fails, a fallback handle is called instead.
+     * All three method handles must have the same corresponding
+     * argument and return types, except that the return type
+     * of the test must be boolean, and the test is allowed
+     * to have fewer arguments than the other two method handles.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * boolean test(A...);
+     * T target(A...,B...);
+     * T fallback(A...,B...);
+     * T adapter(A... a,B... b) {
+     *   if (test(a...))
+     *     return target(a..., b...);
+     *   else
+     *     return fallback(a..., b...);
+     * }
+     * }</pre></blockquote>
+     * Note that the test arguments ({@code a...} in the pseudocode) cannot
+     * be modified by execution of the test, and so are passed unchanged
+     * from the caller to the target or fallback as appropriate.
+     * @param test method handle used for test, must return boolean
+     * @param target method handle to call if test passes
+     * @param fallback method handle to call if test fails
+     * @return method handle which incorporates the specified if/then/else logic
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code test} does not return boolean,
+     *          or if all three method types do not match (with the return
+     *          type of {@code test} changed to match that of the target).
+     */
+    public static
+    MethodHandle guardWithTest(MethodHandle test,
+                               MethodHandle target,
+                               MethodHandle fallback) {
+        MethodType gtype = test.type();
+        MethodType ttype = target.type();
+        MethodType ftype = fallback.type();
+        if (!ttype.equals(ftype))
+            throw misMatchedTypes("target and fallback types", ttype, ftype);
+        if (gtype.returnType() != boolean.class)
+            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
+        List<Class<?>> targs = ttype.parameterList();
+        List<Class<?>> gargs = gtype.parameterList();
+        if (!targs.equals(gargs)) {
+            int gpc = gargs.size(), tpc = targs.size();
+            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
+                throw misMatchedTypes("target and test types", ttype, gtype);
+            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
+            gtype = test.type();
+        }
+
+        // TODO(narayan): Implement this method.
+        // return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
+        throw new UnsupportedOperationException("MethodHandles.guardWithTest is not implemented");
+    }
+
+    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
+        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
+    }
+
+    /**
+     * Makes a method handle which adapts a target method handle,
+     * by running it inside an exception handler.
+     * If the target returns normally, the adapter returns that value.
+     * If an exception matching the specified type is thrown, the fallback
+     * handle is called instead on the exception, plus the original arguments.
+     * <p>
+     * The target and handler must have the same corresponding
+     * argument and return types, except that handler may omit trailing arguments
+     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
+     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>{@code
+     * T target(A..., B...);
+     * T handler(ExType, A...);
+     * T adapter(A... a, B... b) {
+     *   try {
+     *     return target(a..., b...);
+     *   } catch (ExType ex) {
+     *     return handler(ex, a...);
+     *   }
+     * }
+     * }</pre></blockquote>
+     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
+     * be modified by execution of the target, and so are passed unchanged
+     * from the caller to the handler, if the handler is invoked.
+     * <p>
+     * The target and handler must return the same type, even if the handler
+     * always throws.  (This might happen, for instance, because the handler
+     * is simulating a {@code finally} clause).
+     * To create such a throwing handler, compose the handler creation logic
+     * with {@link #throwException throwException},
+     * in order to create a method handle of the correct return type.
+     * @param target method handle to call
+     * @param exType the type of exception which the handler will catch
+     * @param handler method handle to call if a matching exception is thrown
+     * @return method handle which incorporates the specified try/catch logic
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code handler} does not accept
+     *          the given exception type, or if the method handle types do
+     *          not match in their return types and their
+     *          corresponding parameters
+     */
+    public static
+    MethodHandle catchException(MethodHandle target,
+                                Class<? extends Throwable> exType,
+                                MethodHandle handler) {
+        MethodType ttype = target.type();
+        MethodType htype = handler.type();
+        if (htype.parameterCount() < 1 ||
+            !htype.parameterType(0).isAssignableFrom(exType))
+            throw newIllegalArgumentException("handler does not accept exception type "+exType);
+        if (htype.returnType() != ttype.returnType())
+            throw misMatchedTypes("target and handler return types", ttype, htype);
+        List<Class<?>> targs = ttype.parameterList();
+        List<Class<?>> hargs = htype.parameterList();
+        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
+        if (!targs.equals(hargs)) {
+            int hpc = hargs.size(), tpc = targs.size();
+            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
+                throw misMatchedTypes("target and handler types", ttype, htype);
+            handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc));
+            htype = handler.type();
+        }
+
+        // TODO(narayan): Implement this method.
+        // return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
+        throw new UnsupportedOperationException("MethodHandles.catchException is not implemented");
+    }
+
+    /**
+     * Produces a method handle which will throw exceptions of the given {@code exType}.
+     * The method handle will accept a single argument of {@code exType},
+     * and immediately throw it as an exception.
+     * The method type will nominally specify a return of {@code returnType}.
+     * The return type may be anything convenient:  It doesn't matter to the
+     * method handle's behavior, since it will never return normally.
+     * @param returnType the return type of the desired method handle
+     * @param exType the parameter type of the desired method handle
+     * @return method handle which can throw the given exceptions
+     * @throws NullPointerException if either argument is null
+     */
+    public static
+    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
+        if (!Throwable.class.isAssignableFrom(exType))
+            throw new ClassCastException(exType.getName());
+
+        // TODO(narayan): Implement this method.
+        // return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
+        throw new UnsupportedOperationException("MethodHandles.throwException is not implemented");
+    }
+}
diff --git a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
index ddfbc1d..a88d6c1 100644
--- a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -344,7 +344,7 @@
      * @throws NullPointerException if the given annotation class is null
      * @since 1.8
      */
-    default <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
+    default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
         // Loop over all directly-present annotations looking for a matching one
         for (Annotation annotation : getDeclaredAnnotations()) {
diff --git a/ojluni/src/main/java/java/lang/reflect/Constructor.java b/ojluni/src/main/java/java/lang/reflect/Constructor.java
index 3e26cbb..7e3a71d 100644
--- a/ojluni/src/main/java/java/lang/reflect/Constructor.java
+++ b/ojluni/src/main/java/java/lang/reflect/Constructor.java
@@ -26,10 +26,8 @@
 
 package java.lang.reflect;
 
-import java.util.Comparator;
-import libcore.reflect.Types;
-
 import java.lang.annotation.Annotation;
+import java.util.Comparator;
 
 /**
  * {@code Constructor} provides information about, and access to, a single
@@ -51,7 +49,7 @@
  * @author      Kenneth Russell
  * @author      Nakul Saraiya
  */
-public final class Constructor<T> extends AbstractMethod {
+public final class Constructor<T> extends Executable {
     private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method.
 
     private final Class<?> serializationClass;
@@ -74,14 +72,20 @@
         return new Constructor<T>(ctor, cl);
     }
 
+    @Override
+    boolean hasGenericInformation() {
+        // Android-changed: Signature retrieval is handled in Executable.
+        return super.hasGenericInformationInternal();
+    }
+
     /**
      * {@inheritDoc}
      */
     @Override
     @SuppressWarnings({"rawtypes", "unchecked"})
     public Class<T> getDeclaringClass() {
-        // Android-changed: This is handled by AbstractMethod.
-        return (Class<T>) super.getDeclaringClass();
+        // Android-changed: This is handled by Executable.
+        return (Class<T>) super.getDeclaringClassInternal();
     }
 
     /**
@@ -98,8 +102,8 @@
      */
     @Override
     public int getModifiers() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getModifiers();
+        // Android-changed: This is handled by Executable.
+        return super.getModifiersInternal();
     }
 
     /**
@@ -110,7 +114,7 @@
     @Override
     @SuppressWarnings({"rawtypes", "unchecked"})
     public TypeVariable<Constructor<T>>[] getTypeParameters() {
-        // Android-changed: This is mostly handled by AbstractMethod.
+        // Android-changed: This is mostly handled by Executable.
         GenericInfo info = getMethodOrConstructorGenericInfoInternal();
         return (TypeVariable<Constructor<T>>[]) info.formalTypeParameters.clone();
     }
@@ -121,16 +125,16 @@
      */
     @Override
     public Class<?>[] getParameterTypes() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterTypes();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterTypesInternal();
     }
 
     /**
      * {@inheritDoc}
      */
     public int getParameterCount() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterCount();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterCountInternal();
     }
 
     /**
@@ -371,7 +375,7 @@
      */
     @Override
     public Annotation[][] getParameterAnnotations() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterAnnotations();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterAnnotationsInternal();
     }
 }
diff --git a/ojluni/src/main/java/java/lang/reflect/Executable.java b/ojluni/src/main/java/java/lang/reflect/Executable.java
index 1840566..539716f 100644
--- a/ojluni/src/main/java/java/lang/reflect/Executable.java
+++ b/ojluni/src/main/java/java/lang/reflect/Executable.java
@@ -25,8 +25,15 @@
 
 package java.lang.reflect;
 
+import com.android.dex.Dex;
+
 import java.lang.annotation.Annotation;
+import java.util.Objects;
 import libcore.reflect.AnnotatedElements;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
+import libcore.util.EmptyArray;
 
 /**
  * A shared superclass for the common functionality of {@link Method}
@@ -41,6 +48,11 @@
      */
     Executable() {}
 
+    /**
+     * Does the Executable have generic information.
+     */
+    abstract boolean hasGenericInformation();
+
     boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
         /* Avoid unnecessary cloning */
         if (params1.length == params2.length) {
@@ -108,7 +120,6 @@
      */
     abstract void specificToStringHeader(StringBuilder sb);
 
-
     String sharedToGenericString(int modifierMask, boolean isDefault) {
         try {
             StringBuilder sb = new StringBuilder();
@@ -250,12 +261,168 @@
      *     type that cannot be instantiated for any reason
      */
     public Type[] getGenericParameterTypes() {
-        // Android-changed: Implemented in AbstractMethod instead.
-        throw new UnsupportedOperationException(
-                "Executable.getGenericParameterTypes() not implemented");
+        // Android-changed: Changed to use Types / getMethodOrConstructorGenericInfoInternal()
+        return Types.getTypeArray(
+                getMethodOrConstructorGenericInfoInternal().genericParameterTypes, false);
     }
 
     /**
+     * Behaves like {@code getGenericParameterTypes}, but returns type
+     * information for all parameters, including synthetic parameters.
+     */
+    Type[] getAllGenericParameterTypes() {
+        final boolean genericInfo = hasGenericInformation();
+
+        // Easy case: we don't have generic parameter information.  In
+        // this case, we just return the result of
+        // getParameterTypes().
+        if (!genericInfo) {
+            return getParameterTypes();
+        } else {
+            final boolean realParamData = hasRealParameterData();
+            final Type[] genericParamTypes = getGenericParameterTypes();
+            final Type[] nonGenericParamTypes = getParameterTypes();
+            final Type[] out = new Type[nonGenericParamTypes.length];
+            final Parameter[] params = getParameters();
+            int fromidx = 0;
+            // If we have real parameter data, then we use the
+            // synthetic and mandate flags to our advantage.
+            if (realParamData) {
+                for (int i = 0; i < out.length; i++) {
+                    final Parameter param = params[i];
+                    if (param.isSynthetic() || param.isImplicit()) {
+                        // If we hit a synthetic or mandated parameter,
+                        // use the non generic parameter info.
+                        out[i] = nonGenericParamTypes[i];
+                    } else {
+                        // Otherwise, use the generic parameter info.
+                        out[i] = genericParamTypes[fromidx];
+                        fromidx++;
+                    }
+                }
+            } else {
+                // Otherwise, use the non-generic parameter data.
+                // Without method parameter reflection data, we have
+                // no way to figure out which parameters are
+                // synthetic/mandated, thus, no way to match up the
+                // indexes.
+                return genericParamTypes.length == nonGenericParamTypes.length ?
+                    genericParamTypes : nonGenericParamTypes;
+            }
+            return out;
+        }
+    }
+
+    /**
+     * Returns an array of {@code Parameter} objects that represent
+     * all the parameters to the underlying executable represented by
+     * this object.  Returns an array of length 0 if the executable
+     * has no parameters.
+     *
+     * <p>The parameters of the underlying executable do not necessarily
+     * have unique names, or names that are legal identifiers in the
+     * Java programming language (JLS 3.8).
+     *
+     * @since 1.8
+     * @throws MalformedParametersException if the class file contains
+     * a MethodParameters attribute that is improperly formatted.
+     * @return an array of {@code Parameter} objects representing all
+     * the parameters to the executable this object represents.
+     */
+    public Parameter[] getParameters() {
+        // TODO: This may eventually need to be guarded by security
+        // mechanisms similar to those in Field, Method, etc.
+        //
+        // Need to copy the cached array to prevent users from messing
+        // with it.  Since parameters are immutable, we can
+        // shallow-copy.
+        return privateGetParameters().clone();
+    }
+
+    private Parameter[] synthesizeAllParams() {
+        final int realparams = getParameterCount();
+        final Parameter[] out = new Parameter[realparams];
+        for (int i = 0; i < realparams; i++)
+            // TODO: is there a way to synthetically derive the
+            // modifiers?  Probably not in the general case, since
+            // we'd have no way of knowing about them, but there
+            // may be specific cases.
+            out[i] = new Parameter("arg" + i, 0, this, i);
+        return out;
+    }
+
+    private void verifyParameters(final Parameter[] parameters) {
+        final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED;
+
+        if (getParameterTypes().length != parameters.length)
+            throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute");
+
+        for (Parameter parameter : parameters) {
+            final String name = parameter.getRealName();
+            final int mods = parameter.getModifiers();
+
+            if (name != null) {
+                if (name.isEmpty() || name.indexOf('.') != -1 ||
+                    name.indexOf(';') != -1 || name.indexOf('[') != -1 ||
+                    name.indexOf('/') != -1) {
+                    throw new MalformedParametersException("Invalid parameter name \"" + name + "\"");
+                }
+            }
+
+            if (mods != (mods & mask)) {
+                throw new MalformedParametersException("Invalid parameter modifiers");
+            }
+        }
+    }
+
+    private Parameter[] privateGetParameters() {
+        // Use tmp to avoid multiple writes to a volatile.
+        Parameter[] tmp = parameters;
+
+        if (tmp == null) {
+            // Otherwise, go to the JVM to get them
+            try {
+                tmp = getParameters0();
+            } catch(IllegalArgumentException e) {
+                // Rethrow ClassFormatErrors
+                // Android-changed: Exception changed to be more descriptive.
+                MalformedParametersException e2 =
+                        new MalformedParametersException(
+                                "Invalid parameter metadata in class file");
+                e2.initCause(e);
+                throw e2;
+            }
+
+            // If we get back nothing, then synthesize parameters
+            if (tmp == null) {
+                hasRealParameterData = false;
+                tmp = synthesizeAllParams();
+            } else {
+                hasRealParameterData = true;
+                verifyParameters(tmp);
+            }
+
+            parameters = tmp;
+        }
+
+        return tmp;
+    }
+
+    boolean hasRealParameterData() {
+        // If this somehow gets called before parameters gets
+        // initialized, force it into existence.
+        if (parameters == null) {
+            privateGetParameters();
+        }
+        return hasRealParameterData;
+    }
+
+    private transient volatile boolean hasRealParameterData;
+    private transient volatile Parameter[] parameters;
+
+    private native Parameter[] getParameters0();
+
+    /**
      * Returns an array of {@code Class} objects that represent the
      * types of exceptions declared to be thrown by the underlying
      * executable represented by this object.  Returns an array of
@@ -289,9 +456,9 @@
      *     parameterized type that cannot be instantiated for any reason
      */
     public Type[] getGenericExceptionTypes() {
-        // Android-changed: Implemented in AbstractMethod instead.
-        throw new UnsupportedOperationException(
-                "Executable.getGenericExceptionTypes() not implemented");
+        // Android-changed: Changed to use Types / getMethodOrConstructorGenericInfoInternal()
+        return Types.getTypeArray(
+                getMethodOrConstructorGenericInfoInternal().genericExceptionTypes, false);
     }
 
     /**
@@ -310,7 +477,8 @@
      * to take a variable number of arguments.
      */
     public boolean isVarArgs()  {
-        return (getModifiers() & Modifier.VARARGS) != 0;
+        // Android-changed: Slightly more efficient.
+        return (accessFlags & Modifier.VARARGS) != 0;
     }
 
     /**
@@ -323,7 +491,8 @@
      * @jls 13.1 The Form of a Binary
      */
     public boolean isSynthetic() {
-        return Modifier.isSynthetic(getModifiers());
+        // Android-changed: Slightly more efficient.
+        return (accessFlags & Modifier.SYNTHETIC) != 0;
     }
 
     /**
@@ -345,8 +514,11 @@
      * A compiler may add extra parameters that are implicitly
      * declared in source ("mandated"), as well as parameters that
      * are neither implicitly nor explicitly declared in source
-     * ("synthetic") to the parameter list for a method.
+     * ("synthetic") to the parameter list for a method.  See {@link
+     * java.lang.reflect.Parameter} for more information.
      *
+     * @see java.lang.reflect.Parameter
+     * @see java.lang.reflect.Parameter#getAnnotations
      * @return an array of arrays that represent the annotations on
      *    the formal and implicit parameters, in declaration order, of
      *    the executable represented by this object
@@ -358,9 +530,11 @@
      * @throws NullPointerException  {@inheritDoc}
      */
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        // Android-changed: Implemented in AbstractMethod instead.
-        throw new UnsupportedOperationException("Executable.getAnnotation(Class) not implemented");
+        Objects.requireNonNull(annotationClass);
+        // Android-changed: Implemented natively.
+        return getAnnotationNative(annotationClass);
     }
+    private native <T extends Annotation> T getAnnotationNative(Class<T> annotationClass);
 
     /**
      * {@inheritDoc}
@@ -377,8 +551,233 @@
      * {@inheritDoc}
      */
     public Annotation[] getDeclaredAnnotations()  {
-        // Android-changed: Implemented in AbstractMethod instead.
-        throw new UnsupportedOperationException(
-                "Executable.getDeclaredAnnotations() not implemented");
+        // Android-changed: Implemented natively.
+        return getDeclaredAnnotationsNative();
+    }
+    private native Annotation[] getDeclaredAnnotationsNative();
+
+    // Android-changed: Additional ART-related fields and logic below that is shared between
+    // Method and Constructor.
+
+    /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
+    @SuppressWarnings("unused") // set by runtime
+    private int accessFlags;
+
+    /**
+     * The ArtMethod associated with this Executable, required for dispatching due to entrypoints
+     * Classloader is held live by the declaring class.
+     */
+    @SuppressWarnings("unused") // set by runtime
+    private long artMethod;
+
+    /** Executable's declaring class */
+    @SuppressWarnings("unused") // set by runtime
+    private Class<?> declaringClass;
+
+    /**
+     * Overriden method's declaring class (same as declaringClass unless declaringClass is a proxy
+     * class).
+     */
+    @SuppressWarnings("unused") // set by runtime
+    private Class<?> declaringClassOfOverriddenMethod;
+
+    /** The method index of this method within its defining dex file */
+    @SuppressWarnings("unused") // set by runtime
+    private int dexMethodIndex;
+
+    /**
+     * We insert native method stubs for abstract methods so we don't have to
+     * check the access flags at the time of the method call.  This results in
+     * "native abstract" methods, which can't exist.  If we see the "abstract"
+     * flag set, clear the "native" flag.
+     *
+     * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
+     * position, because the callers of this function are trying to convey
+     * the "traditional" meaning of the flags to their callers.
+     */
+    private static int fixMethodFlags(int flags) {
+        if ((flags & Modifier.ABSTRACT) != 0) {
+            flags &= ~Modifier.NATIVE;
+        }
+        flags &= ~Modifier.SYNCHRONIZED;
+        int ACC_DECLARED_SYNCHRONIZED = 0x00020000;
+        if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
+            flags |= Modifier.SYNCHRONIZED;
+        }
+        return flags & 0xffff;  // mask out bits not used by Java
+    }
+
+    final int getModifiersInternal() {
+        return fixMethodFlags(accessFlags);
+    }
+
+    final Class<?> getDeclaringClassInternal() {
+        return declaringClass;
+    }
+
+    /**
+     * Returns an array of {@code Class} objects associated with the parameter types of this
+     * Executable. If the Executable was declared with no parameters, an empty array will be
+     * returned.
+     *
+     * @return the parameter types
+     */
+    final Class<?>[] getParameterTypesInternal() {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
+        if (types.length == 0) {
+            return EmptyArray.CLASS;
+        }
+        Class<?>[] parametersArray = new Class[types.length];
+        for (int i = 0; i < types.length; i++) {
+            // Note, in the case of a Proxy the dex cache types are equal.
+            parametersArray[i] = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
+        }
+        return parametersArray;
+    }
+
+    final int getParameterCountInternal() {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
+        return types.length;
+    }
+
+    // Android provides a more efficient implementation of this method for Executable than the one
+    // implemented in AnnotatedElement.
+    @Override
+    public final boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+        Objects.requireNonNull(annotationType);
+        return isAnnotationPresentNative(annotationType);
+    }
+    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
+
+    final Annotation[][] getParameterAnnotationsInternal() {
+        Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+        if (parameterAnnotations == null) {
+            parameterAnnotations = new Annotation[getParameterTypes().length][0];
+        }
+        return parameterAnnotations;
+    }
+    private native Annotation[][] getParameterAnnotationsNative();
+
+    /**
+     * @hide - exposed for use by {@link Class}.
+     */
+    public final int getAccessFlags() {
+        return accessFlags;
+    }
+
+    /**
+     * @hide - exposed for use by {@code java.lang.invoke.*}.
+     */
+    public final long getArtMethod() {
+        return artMethod;
+    }
+
+    static final class GenericInfo {
+        final ListOfTypes genericExceptionTypes;
+        final ListOfTypes genericParameterTypes;
+        final Type genericReturnType;
+        final TypeVariable<?>[] formalTypeParameters;
+
+        GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret,
+                TypeVariable<?>[] formal) {
+            genericExceptionTypes = exceptions;
+            genericParameterTypes = parameters;
+            genericReturnType = ret;
+            formalTypeParameters = formal;
+        }
+    }
+
+    final boolean hasGenericInformationInternal() {
+        return getSignatureAnnotation() != null;
+    }
+
+    /**
+     * Returns generic information associated with this method/constructor member.
+     */
+    final GenericInfo getMethodOrConstructorGenericInfoInternal() {
+        String signatureAttribute = getSignatureAttribute();
+        Class<?>[] exceptionTypes = this.getExceptionTypes();
+        GenericSignatureParser parser =
+                new GenericSignatureParser(this.getDeclaringClass().getClassLoader());
+        if (this instanceof Method) {
+            parser.parseForMethod(this, signatureAttribute, exceptionTypes);
+        } else {
+            parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
+        }
+        return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
+                parser.returnType, parser.formalTypeParameters);
+    }
+
+    private String getSignatureAttribute() {
+        String[] annotation = getSignatureAnnotation();
+        if (annotation == null) {
+            return null;
+        }
+        StringBuilder result = new StringBuilder();
+        for (String s : annotation) {
+            result.append(s);
+        }
+        return result.toString();
+    }
+    private native String[] getSignatureAnnotation();
+
+    final boolean equalNameAndParametersInternal(Method m) {
+        return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes());
+    }
+
+    private boolean equalMethodParameters(Class<?>[] params) {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
+        if (types.length != params.length) {
+            return false;
+        }
+        for (int i = 0; i < types.length; i++) {
+            if (declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]) != params[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    final int compareMethodParametersInternal(Class<?>[] params) {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
+        int length = Math.min(types.length, params.length);
+        for (int i = 0; i < length; i++) {
+            Class<?> aType = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
+            Class<?> bType = params[i];
+            if (aType != bType) {
+                int comparison = aType.getName().compareTo(bType.getName());
+                if (comparison != 0) {
+                    return comparison;
+                }
+            }
+        }
+        return types.length - params.length;
+    }
+
+    final String getMethodNameInternal() {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex);
+        return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex);
+    }
+
+    final Class<?> getMethodReturnTypeInternal() {
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex);
+        // Note, in the case of a Proxy the dex cache types are equal.
+        return declaringClassOfOverriddenMethod.getDexCacheType(dex, returnTypeIndex);
+    }
+
+    /** A cheap implementation for {@link Method#isDefault()}. */
+    final boolean isDefaultMethodInternal() {
+        return (accessFlags & Modifier.DEFAULT) != 0;
+    }
+
+    /** A cheap implementation for {@link Method#isBridge()}. */
+    final boolean isBridgeMethodInternal() {
+        return (accessFlags & Modifier.BRIDGE) != 0;
     }
 }
diff --git a/ojluni/src/main/java/java/lang/reflect/MalformedParametersException.java b/ojluni/src/main/java/java/lang/reflect/MalformedParametersException.java
new file mode 100644
index 0000000..6b14b15
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/reflect/MalformedParametersException.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * Thrown when {@link java.lang.reflect.Executable#getParameters the
+ * java.lang.reflect package} attempts to read method parameters from
+ * a class file and determines that one or more parameters are
+ * malformed.
+ *
+ * <p>The following is a list of conditions under which this exception
+ * can be thrown:
+ * <ul>
+ * <li> The number of parameters (parameter_count) is wrong for the method
+ * <li> A constant pool index is out of bounds.
+ * <li> A constant pool index does not refer to a UTF-8 entry
+ * <li> A parameter's name is "", or contains an illegal character
+ * <li> The flags field contains an illegal flag (something other than
+ *     FINAL, SYNTHETIC, or MANDATED)
+ * </ul>
+ *
+ * See {@link java.lang.reflect.Executable#getParameters} for more
+ * information.
+ *
+ * @see java.lang.reflect.Executable#getParameters
+ * @since 1.8
+ * @hide Hidden pending tests
+ */
+public class MalformedParametersException extends RuntimeException {
+
+    /**
+     * Version for serialization.
+     */
+    private static final long serialVersionUID = 20130919L;
+
+    /**
+     * Create a {@code MalformedParametersException} with an empty
+     * reason.
+     */
+    public MalformedParametersException() {}
+
+    /**
+     * Create a {@code MalformedParametersException}.
+     *
+     * @param reason The reason for the exception.
+     */
+    public MalformedParametersException(String reason) {
+        super(reason);
+    }
+}
diff --git a/ojluni/src/main/java/java/lang/reflect/Method.java b/ojluni/src/main/java/java/lang/reflect/Method.java
index a9f2eb7..e3fa1c9 100644
--- a/ojluni/src/main/java/java/lang/reflect/Method.java
+++ b/ojluni/src/main/java/java/lang/reflect/Method.java
@@ -50,7 +50,7 @@
  * @author Kenneth Russell
  * @author Nakul Saraiya
  */
-public final class Method extends AbstractMethod  {
+public final class Method extends Executable  {
     /**
      * Orders methods by their name, parameters and return type.
      *
@@ -82,13 +82,19 @@
     private Method() {
     }
 
+    @Override
+    boolean hasGenericInformation() {
+        // Android-changed: Signature retrieval is handled in Executable.
+        return super.hasGenericInformationInternal();
+    }
+
     /**
      * {@inheritDoc}
-      */
+     */
     @Override
     public Class<?> getDeclaringClass() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getDeclaringClass();
+        // Android-changed: This is handled by Executable.
+        return super.getDeclaringClassInternal();
     }
 
     /**
@@ -97,7 +103,7 @@
      */
     @Override
     public String getName() {
-        // Android-changed: This is handled by AbstractMethod.
+        // Android-changed: This is handled by Executable.
         return getMethodNameInternal();
     }
 
@@ -106,8 +112,8 @@
      */
     @Override
     public int getModifiers() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getModifiers();
+        // Android-changed: This is handled by Executable.
+        return super.getModifiersInternal();
     }
 
     /**
@@ -118,7 +124,7 @@
     @Override
     @SuppressWarnings({"rawtypes", "unchecked"})
     public TypeVariable<Method>[] getTypeParameters() {
-        // Android-changed: This is mostly handled by AbstractMethod.
+        // Android-changed: This is mostly handled by Executable.
         GenericInfo info = getMethodOrConstructorGenericInfoInternal();
         return (TypeVariable<Method>[]) info.formalTypeParameters.clone();
     }
@@ -130,7 +136,7 @@
      * @return the return type for the method this object represents
      */
     public Class<?> getReturnType() {
-        // Android-changed: This is handled by AbstractMethod.
+        // Android-changed: This is handled by Executable.
         return getMethodReturnTypeInternal();
     }
 
@@ -159,6 +165,7 @@
      * @since 1.5
      */
     public Type getGenericReturnType() {
+        // Android-changed: Modified implementation to use Executable.
       return Types.getType(getMethodOrConstructorGenericInfoInternal().genericReturnType);
     }
 
@@ -167,16 +174,16 @@
      */
     @Override
     public Class<?>[] getParameterTypes() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterTypes();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterTypesInternal();
     }
 
     /**
      * {@inheritDoc}
      */
     public int getParameterCount() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterCount();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterCountInternal();
     }
 
     /**
@@ -238,7 +245,6 @@
         return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
     }
 
-
     /**
      * Returns a string describing this {@code Method}.  The string is
      * formatted as the method access modifiers, if any, followed by
@@ -332,7 +338,6 @@
         sb.append(getName());
     }
 
-
     /**
      * Invokes the underlying method represented by this {@code Method}
      * object, on the specified object with the specified parameters.
@@ -402,7 +407,7 @@
      * @since 1.5
      */
     public boolean isBridge() {
-        // Android-changed: This is handled by AbstractMethod.
+        // Android-changed: This is handled by Executable.
         return super.isBridgeMethodInternal();
     }
 
@@ -425,7 +430,6 @@
         return super.isSynthetic();
     }
 
-
     /**
      * Returns {@code true} if this method is a default
      * method; returns {@code false} otherwise.
@@ -439,7 +443,7 @@
      * @since 1.8
      */
     public boolean isDefault() {
-        // Android-changed: This is handled by AbstractMethod.
+        // Android-changed: This is handled by Executable.
         return super.isDefaultMethodInternal();
     }
 
@@ -482,8 +486,8 @@
      */
     @Override
     public Annotation[][] getParameterAnnotations() {
-        // Android-changed: This is handled by AbstractMethod.
-        return super.getParameterAnnotations();
+        // Android-changed: This is handled by Executable.
+        return super.getParameterAnnotationsInternal();
     }
 
     /**
diff --git a/ojluni/src/main/java/java/lang/reflect/Parameter.java b/ojluni/src/main/java/java/lang/reflect/Parameter.java
new file mode 100644
index 0000000..2d96307
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/reflect/Parameter.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.reflect;
+
+import java.lang.annotation.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import libcore.reflect.AnnotatedElements;
+
+/**
+ * Information about method parameters.
+ *
+ * A {@code Parameter} provides information about method parameters,
+ * including its name and modifiers.  It also provides an alternate
+ * means of obtaining attributes for the parameter.
+ *
+ * @since 1.8
+ */
+public final class Parameter implements AnnotatedElement {
+
+    private final String name;
+    private final int modifiers;
+    private final Executable executable;
+    private final int index;
+
+    /**
+     * Package-private constructor for {@code Parameter}.
+     *
+     * If method parameter data is present in the classfile, then the
+     * JVM creates {@code Parameter} objects directly.  If it is
+     * absent, however, then {@code Executable} uses this constructor
+     * to synthesize them.
+     *
+     * @param name The name of the parameter.
+     * @param modifiers The modifier flags for the parameter.
+     * @param executable The executable which defines this parameter.
+     * @param index The index of the parameter.
+     */
+    Parameter(String name,
+              int modifiers,
+              Executable executable,
+              int index) {
+        this.name = name;
+        this.modifiers = modifiers;
+        this.executable = executable;
+        this.index = index;
+    }
+
+    /**
+     * Compares based on the executable and the index.
+     *
+     * @param obj The object to compare.
+     * @return Whether or not this is equal to the argument.
+     */
+    public boolean equals(Object obj) {
+        if(obj instanceof Parameter) {
+            Parameter other = (Parameter)obj;
+            return (other.executable.equals(executable) &&
+                    other.index == index);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code based on the executable's hash code and the
+     * index.
+     *
+     * @return A hash code based on the executable's hash code.
+     */
+    public int hashCode() {
+        return executable.hashCode() ^ index;
+    }
+
+    // Android-changed: Removed references to the class file format.
+    /**
+     * Returns true if the parameter has a name; returns false otherwise.
+     * Whether a parameter has a name is determined by compiler options
+     * and whether the parameter is synthesized.
+     *
+     * @return true if and only if the parameter has a name
+     */
+    public boolean isNamePresent() {
+        return executable.hasRealParameterData() && name != null;
+    }
+
+    /**
+     * Returns a string describing this parameter.  The format is the
+     * modifiers for the parameter, if any, in canonical order as
+     * recommended by <cite>The Java&trade; Language
+     * Specification</cite>, followed by the fully- qualified type of
+     * the parameter (excluding the last [] if the parameter is
+     * variable arity), followed by "..." if the parameter is variable
+     * arity, followed by a space, followed by the name of the
+     * parameter.
+     *
+     * @return A string representation of the parameter and associated
+     * information.
+     */
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        final Type type = getParameterizedType();
+        final String typename = type.getTypeName();
+
+        sb.append(Modifier.toString(getModifiers()));
+
+        if(0 != modifiers)
+            sb.append(' ');
+
+        if(isVarArgs())
+            sb.append(typename.replaceFirst("\\[\\]$", "..."));
+        else
+            sb.append(typename);
+
+        sb.append(' ');
+        sb.append(getName());
+
+        return sb.toString();
+    }
+
+    /**
+     * Return the {@code Executable} which declares this parameter.
+     *
+     * @return The {@code Executable} declaring this parameter.
+     */
+    public Executable getDeclaringExecutable() {
+        return executable;
+    }
+
+    /**
+     * Get the modifier flags for this the parameter represented by
+     * this {@code Parameter} object.
+     *
+     * @return The modifier flags for this parameter.
+     */
+    public int getModifiers() {
+        return modifiers;
+    }
+
+    /**
+     * Returns the name of the parameter.  If the parameter's name is
+     * {@linkplain #isNamePresent() present}, then this method returns
+     * the name provided by the class file. Otherwise, this method
+     * synthesizes a name of the form argN, where N is the index of
+     * the parameter in the descriptor of the method which declares
+     * the parameter.
+     *
+     * @return The name of the parameter, either provided by the class
+     *         file or synthesized if the class file does not provide
+     *         a name.
+     */
+    public String getName() {
+        // Note: empty strings as paramete names are now outlawed.
+        // The .equals("") is for compatibility with current JVM
+        // behavior.  It may be removed at some point.
+        if(name == null || name.equals(""))
+            return "arg" + index;
+        else
+            return name;
+    }
+
+    // Package-private accessor to the real name field.
+    String getRealName() {
+        return name;
+    }
+
+    /**
+     * Returns a {@code Type} object that identifies the parameterized
+     * type for the parameter represented by this {@code Parameter}
+     * object.
+     *
+     * @return a {@code Type} object identifying the parameterized
+     * type of the parameter represented by this object
+     */
+    public Type getParameterizedType() {
+        Type tmp = parameterTypeCache;
+        if (null == tmp) {
+            tmp = executable.getAllGenericParameterTypes()[index];
+            parameterTypeCache = tmp;
+        }
+
+        return tmp;
+    }
+
+    private transient volatile Type parameterTypeCache = null;
+
+    /**
+     * Returns a {@code Class} object that identifies the
+     * declared type for the parameter represented by this
+     * {@code Parameter} object.
+     *
+     * @return a {@code Class} object identifying the declared
+     * type of the parameter represented by this object
+     */
+    public Class<?> getType() {
+        Class<?> tmp = parameterClassCache;
+        if (null == tmp) {
+            tmp = executable.getParameterTypes()[index];
+            parameterClassCache = tmp;
+        }
+        return tmp;
+    }
+
+    private transient volatile Class<?> parameterClassCache = null;
+
+    /**
+     * Returns {@code true} if this parameter is implicitly declared
+     * in source code; returns {@code false} otherwise.
+     *
+     * @return true if and only if this parameter is implicitly
+     * declared as defined by <cite>The Java&trade; Language
+     * Specification</cite>.
+     */
+    public boolean isImplicit() {
+        return Modifier.isMandated(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter is neither implicitly
+     * nor explicitly declared in source code; returns {@code false}
+     * otherwise.
+     *
+     * @jls 13.1 The Form of a Binary
+     * @return true if and only if this parameter is a synthetic
+     * construct as defined by
+     * <cite>The Java&trade; Language Specification</cite>.
+     */
+    public boolean isSynthetic() {
+        return Modifier.isSynthetic(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter represents a variable
+     * argument list; returns {@code false} otherwise.
+     *
+     * @return {@code true} if an only if this parameter represents a
+     * variable argument list.
+     */
+    public boolean isVarArgs() {
+        return executable.isVarArgs() &&
+            index == executable.getParameterCount() - 1;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        // Android-changed: Uses native code to obtain annotation information.
+        return getAnnotationNative(executable, index, annotationClass);
+    }
+    private static native <A extends Annotation> A getAnnotationNative(
+            Executable executable, int parameterIndex, Class<A> annotationType);
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+        // Android-changed: Uses AnnotatedElements instead.
+        return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getDeclaredAnnotations() {
+        return executable.getParameterAnnotations()[index];
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotation is the same as
+        // getAnnotation.
+        return getAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotations is the same as
+        // getAnnotations.
+        return getAnnotationsByType(annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getAnnotations() {
+        return getDeclaredAnnotations();
+    }
+}
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index 6f2c95c..f9dbaff 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -152,46 +152,44 @@
         if (!isBound())
           bind(new InetSocketAddress(0));
 
-        // ----- BEGIN android -----
-        connectedAddress = address;
-        connectedPort = port;
-        // ----- END android -----
-
-        // old impls do not support connect/disconnect
-        if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
-             ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
-            connectState = ST_CONNECTED_NO_IMPL;
-        } else {
-          /* ----- BEGIN android -----
-          try {
-              getImpl().connect(address, port);
-
-              // socket is now connected by the impl
-              connectState = ST_CONNECTED;
-          } catch (SocketException se) {
-                // connection will be emulated by DatagramSocket
+        // Android-changed: This section now throws any SocketException generated by connect()
+        // to enable it to be recorded as the pendingConnectException. It has been enclosed in a
+        // try-finally to ensure connectedAddress and connectedPort are set when the exception
+        // is thrown.
+        try {
+            // old impls do not support connect/disconnect
+            // Android-changed: Added special handling for AbstractPlainDatagramSocketImpl in
+            // the condition below.
+            if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
+                    ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
                 connectState = ST_CONNECTED_NO_IMPL;
-          }*/
-          getImpl().connect(address, port);
+            } else {
+                try {
+                    getImpl().connect(address, port);
 
-          // socket is now connected by the impl
-          connectState = ST_CONNECTED;
-          // Do we need to filter some packets?
-          int avail = getImpl().dataAvailable();
-          if (avail == -1) {
-              throw new SocketException();
-          }
-          explicitFilter = avail > 0;
-          if (explicitFilter) {
-              bytesLeftToFilter = getReceiveBufferSize();
-          }
-          // ----- END android -----
+                    // socket is now connected by the impl
+                    connectState = ST_CONNECTED;
+
+                    // Do we need to filter some packets?
+                    int avail = getImpl().dataAvailable();
+                    if (avail == -1) {
+                        throw new SocketException();
+                    }
+                    explicitFilter = avail > 0;
+                    if (explicitFilter) {
+                        bytesLeftToFilter = getReceiveBufferSize();
+                    }
+                } catch (SocketException se) {
+                    // connection will be emulated by DatagramSocket
+                    connectState = ST_CONNECTED_NO_IMPL;
+                    // Android-changed: Propagate the SocketException so connect() can store it.
+                    throw se;
+                }
+           }
+        } finally {
+            connectedAddress = address;
+            connectedPort = port;
         }
-
-        /* ----- BEGIN android -----
-        connectedAddress = address;
-        connectedPort = port;
-        ----- END android ----- */
     }
 
 
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/security/DigestOutputStream.java b/ojluni/src/main/java/java/security/DigestOutputStream.java
index 1307bdf..d7f777b 100644
--- a/ojluni/src/main/java/java/security/DigestOutputStream.java
+++ b/ojluni/src/main/java/java/security/DigestOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1999, 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
@@ -37,13 +37,13 @@
  * the bits going through the stream.
  *
  * <p>To complete the message digest computation, call one of the
- * <code>digest</code> methods on the associated message
- * digest after your calls to one of this digest ouput stream's
+ * {@code digest} methods on the associated message
+ * digest after your calls to one of this digest output stream's
  * {@link #write(int) write} methods.
  *
  * <p>It is possible to turn this stream on or off (see
  * {@link #on(boolean) on}). When it is on, a call to one of the
- * <code>write</code> methods results in
+ * {@code write} methods results in
  * an update on the message digest.  But when it is off, the message
  * digest is not updated. The default is for the stream to be on.
  *
@@ -99,8 +99,8 @@
      * the specified byte, and in any case writes the byte
      * to the output stream. That is, if the digest function is on
      * (see {@link #on(boolean) on}), this method calls
-     * <code>update</code> on the message digest associated with this
-     * stream, passing it the byte <code>b</code>. This method then
+     * {@code update} on the message digest associated with this
+     * stream, passing it the byte {@code b}. This method then
      * writes the byte to the output stream, blocking until the byte
      * is actually written.
      *
@@ -112,17 +112,17 @@
      * @see MessageDigest#update(byte)
      */
     public void write(int b) throws IOException {
+        out.write(b);
         if (on) {
             digest.update((byte)b);
         }
-        out.write(b);
     }
 
     /**
      * Updates the message digest (if the digest function is on) using
      * the specified subarray, and in any case writes the subarray to
      * the output stream. That is, if the digest function is on (see
-     * {@link #on(boolean) on}), this method calls <code>update</code>
+     * {@link #on(boolean) on}), this method calls {@code update}
      * on the message digest associated with this stream, passing it
      * the subarray specifications. This method then writes the subarray
      * bytes to the output stream, blocking until the bytes are actually
@@ -131,26 +131,35 @@
      * @param b the array containing the subarray to be used for updating
      * and writing to the output stream.
      *
-     * @param off the offset into <code>b</code> of the first byte to
+     * @param off the offset into {@code b} of the first byte to
      * be updated and written.
      *
      * @param len the number of bytes of data to be updated and written
-     * from <code>b</code>, starting at offset <code>off</code>.
+     * from {@code b}, starting at offset {@code off}.
      *
      * @exception IOException if an I/O error occurs.
      *
      * @see MessageDigest#update(byte[], int, int)
      */
     public void write(byte[] b, int off, int len) throws IOException {
+        // BEGIN ANDROID-ADDED: perform checks for parameters first.
+        // See org.apache.harmony.security.tests.j.s.DigestOutputStreamTest#test_write$BII_6
+        if (b == null || off + len > b.length) {
+            throw new IllegalArgumentException("wrong parameters for write");
+        }
+        if (off < 0 || len < 0) {
+            throw new IndexOutOfBoundsException("wrong index for write");
+        }
+        // END ANDROID-ADDED
+        out.write(b, off, len);
         if (on) {
             digest.update(b, off, len);
         }
-        out.write(b, off, len);
     }
 
     /**
      * Turns the digest function on or off. The default is on.  When
-     * it is on, a call to one of the <code>write</code> methods results in an
+     * it is on, a call to one of the {@code write} methods results in an
      * update on the message digest.  But when it is off, the message
      * digest is not updated.
      *
diff --git a/ojluni/src/main/java/java/security/Signature.java b/ojluni/src/main/java/java/security/Signature.java
index 8923ecd..a8a42a1 100644
--- a/ojluni/src/main/java/java/security/Signature.java
+++ b/ojluni/src/main/java/java/security/Signature.java
@@ -1,6 +1,6 @@
 /*
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright (C) 2014 The Android Open Source Project
- * 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
@@ -42,8 +42,9 @@
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.BadPaddingException;
 import javax.crypto.NoSuchPaddingException;
-
+/* BEGIN ANDROID-REMOVED: this debugging mechanism is not available in Android.
 import sun.security.util.Debug;
+ * END ANDROID-REMOVED */
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
 
@@ -54,10 +55,10 @@
  *
  * <p> The signature algorithm can be, among others, the NIST standard
  * DSA, using DSA and SHA-1. The DSA algorithm using the
- * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>.
+ * SHA-1 message digest algorithm can be specified as {@code SHA1withDSA}.
  * In the case of RSA, there are multiple choices for the message digest
  * algorithm, so the signing algorithm could be specified as, for example,
- * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>.
+ * {@code MD2withRSA}, {@code MD5withRSA}, or {@code SHA1withRSA}.
  * The algorithm name must be specified, as there is no default.
  *
  * <p> A Signature object can be used to generate and verify digital
@@ -78,13 +79,13 @@
  *     (see {@link #initSign(PrivateKey)}
  *     and {@link #initSign(PrivateKey, SecureRandom)}).
  *
- *     </ul><p>
+ *     </ul>
  *
- * <li>Updating<p>
+ * <li>Updating
  *
  * <p>Depending on the type of initialization, this will update the
  * bytes to be signed or verified. See the
- * {@link #update(byte) update} methods.<p>
+ * {@link #update(byte) update} methods.
  *
  * <li>Signing or Verifying a signature on all updated bytes. See the
  * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
@@ -93,13 +94,13 @@
  * </ol>
  *
  * <p>Note that this class is abstract and extends from
- * <code>SignatureSpi</code> for historical reasons.
+ * {@code SignatureSpi} for historical reasons.
  * Application developers should only take notice of the methods defined in
- * this <code>Signature</code> class; all the methods in
+ * this {@code Signature} class; all the methods in
  * the superclass are intended for cryptographic service providers who wish to
  * supply their own implementations of digital signature algorithms.
  *
- * <p> Android provides the following <code>Signature</code> algorithms:
+ * <p> Android provides the following {@code Signature} algorithms:
  * <table>
  *     <thead>
  *         <tr>
@@ -214,9 +215,16 @@
 
 public abstract class Signature extends SignatureSpi {
 
+    /* BEGIN ANDROID-REMOVED: this debugging mechanism not available in Android
     private static final Debug debug =
                         Debug.getInstance("jca", "Signature");
 
+    private static final Debug pdebug =
+                        Debug.getInstance("provider", "Provider");
+    private static final boolean skipDebug =
+        Debug.isOn("engine=") && !Debug.isOn("signature");
+     * END ANDROID-REMOVED */
+
     /*
      * The algorithm for this signature object.
      * This value is used to map an OID to the particular algorithm.
@@ -344,6 +352,7 @@
         Signature sig;
         if (instance.impl instanceof Signature) {
             sig = (Signature)instance.impl;
+            sig.algorithm = algorithm;
         } else {
             SignatureSpi spi = (SignatureSpi)instance.impl;
             sig = new Delegate(spi, algorithm);
@@ -385,11 +394,13 @@
                 // instance of SignatureSpi but not Signature
                 boolean r = (instance instanceof SignatureSpi)
                                 && (instance instanceof Signature == false);
+                /* BEGIN ANDROID-REMOVED: this mechanism not available in Android
                 if ((debug != null) && (r == false)) {
                     debug.println("Not a SignatureSpi " + className);
                     debug.println("Delayed provider selection may not be "
                         + "available for algorithm " + s.getAlgorithm());
                 }
+                 * END ANDROID-REMOVED */
                 result = Boolean.valueOf(r);
                 signatureInfo.put(className, result);
             } catch (Exception e) {
@@ -546,6 +557,13 @@
             throws InvalidKeyException {
         engineInitVerify(publicKey);
         state = VERIFY;
+
+        /* BEGIN ANDROID-REMOVED: this debugging mechanism not supported in Android.
+        if (!skipDebug && pdebug != null) {
+            pdebug.println("Signature." + algorithm +
+                " verification algorithm from: " + this.provider.getName());
+        }
+         * END ANDROID-REMOVED */
     }
 
     /**
@@ -556,7 +574,7 @@
      * extension field implies that the public key in
      * the certificate and its corresponding private key are not
      * supposed to be used for digital signatures, an
-     * <code>InvalidKeyException</code> is thrown.
+     * {@code InvalidKeyException} is thrown.
      *
      * @param certificate the certificate of the identity whose signature is
      * going to be verified.
@@ -590,6 +608,13 @@
         PublicKey publicKey = certificate.getPublicKey();
         engineInitVerify(publicKey);
         state = VERIFY;
+
+        /* BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+        if (!skipDebug && pdebug != null) {
+            pdebug.println("Signature." + algorithm +
+                " verification algorithm from: " + this.provider.getName());
+        }
+         * END ANDROID-REMOVED */
     }
 
     /**
@@ -606,6 +631,13 @@
             throws InvalidKeyException {
         engineInitSign(privateKey);
         state = SIGN;
+
+        /* BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+        if (!skipDebug && pdebug != null) {
+            pdebug.println("Signature." + algorithm +
+                " signing algorithm from: " + this.provider.getName());
+        }
+         * END ANDROID-REMOVED */
     }
 
     /**
@@ -624,6 +656,13 @@
             throws InvalidKeyException {
         engineInitSign(privateKey, random);
         state = SIGN;
+
+        /* BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+        if (!skipDebug && pdebug != null) {
+            pdebug.println("Signature." + algorithm +
+                " signing algorithm from: " + this.provider.getName());
+        }
+         * END ANDROID-REMOVED */
     }
 
     /**
@@ -633,10 +672,10 @@
      *
      * <p>A call to this method resets this signature object to the state
      * it was in when previously initialized for signing via a
-     * call to <code>initSign(PrivateKey)</code>. That is, the object is
+     * call to {@code initSign(PrivateKey)}. That is, the object is
      * reset and available to generate another signature from the same
-     * signer, if desired, via new calls to <code>update</code> and
-     * <code>sign</code>.
+     * signer, if desired, via new calls to {@code update} and
+     * {@code sign}.
      *
      * @return the signature bytes of the signing operation's result.
      *
@@ -654,28 +693,28 @@
 
     /**
      * Finishes the signature operation and stores the resulting signature
-     * bytes in the provided buffer <code>outbuf</code>, starting at
-     * <code>offset</code>.
+     * bytes in the provided buffer {@code outbuf}, starting at
+     * {@code offset}.
      * The format of the signature depends on the underlying
      * signature scheme.
      *
      * <p>This signature object is reset to its initial state (the state it
-     * was in after a call to one of the <code>initSign</code> methods) and
+     * was in after a call to one of the {@code initSign} methods) and
      * can be reused to generate further signatures with the same private key.
      *
      * @param outbuf buffer for the signature result.
      *
-     * @param offset offset into <code>outbuf</code> where the signature is
+     * @param offset offset into {@code outbuf} where the signature is
      * stored.
      *
-     * @param len number of bytes within <code>outbuf</code> allotted for the
+     * @param len number of bytes within {@code outbuf} allotted for the
      * signature.
      *
-     * @return the number of bytes placed into <code>outbuf</code>.
+     * @return the number of bytes placed into {@code outbuf}.
      *
      * @exception SignatureException if this signature object is not
      * initialized properly, if this signature algorithm is unable to
-     * process the input data provided, or if <code>len</code> is less
+     * process the input data provided, or if {@code len} is less
      * than the actual signature length.
      *
      * @since 1.2
@@ -685,6 +724,9 @@
         if (outbuf == null) {
             throw new IllegalArgumentException("No output buffer given");
         }
+        if (offset < 0 || len < 0) {
+            throw new IllegalArgumentException("offset or len is less than 0");
+        }
         if (outbuf.length - offset < len) {
             throw new IllegalArgumentException
                 ("Output buffer too small for specified offset and length");
@@ -701,9 +743,9 @@
      *
      * <p>A call to this method resets this signature object to the state
      * it was in when previously initialized for verification via a
-     * call to <code>initVerify(PublicKey)</code>. That is, the object is
+     * call to {@code initVerify(PublicKey)}. That is, the object is
      * reset and available to verify another signature from the identity
-     * whose public key was specified in the call to <code>initVerify</code>.
+     * whose public key was specified in the call to {@code initVerify}.
      *
      * @param signature the signature bytes to be verified.
      *
@@ -728,9 +770,9 @@
      *
      * <p>A call to this method resets this signature object to the state
      * it was in when previously initialized for verification via a
-     * call to <code>initVerify(PublicKey)</code>. That is, the object is
+     * call to {@code initVerify(PublicKey)}. That is, the object is
      * reset and available to verify another signature from the identity
-     * whose public key was specified in the call to <code>initVerify</code>.
+     * whose public key was specified in the call to {@code initVerify}.
      *
      *
      * @param signature the signature bytes to be verified.
@@ -743,19 +785,26 @@
      * initialized properly, the passed-in signature is improperly
      * encoded or of the wrong type, if this signature algorithm is unable to
      * process the input data provided, etc.
-     * @exception IllegalArgumentException if the <code>signature</code>
-     * byte array is null, or the <code>offset</code> or <code>length</code>
-     * is less than 0, or the sum of the <code>offset</code> and
-     * <code>length</code> is greater than the length of the
-     * <code>signature</code> byte array.
+     * @exception IllegalArgumentException if the {@code signature}
+     * byte array is null, or the {@code offset} or {@code length}
+     * is less than 0, or the sum of the {@code offset} and
+     * {@code length} is greater than the length of the
+     * {@code signature} byte array.
      * @since 1.4
      */
     public final boolean verify(byte[] signature, int offset, int length)
         throws SignatureException {
         if (state == VERIFY) {
-            if ((signature == null) || (offset < 0) || (length < 0) ||
-                (length > signature.length - offset)) {
-                throw new IllegalArgumentException("Bad arguments");
+            if (signature == null) {
+                throw new IllegalArgumentException("signature is null");
+            }
+            if (offset < 0 || length < 0) {
+                throw new IllegalArgumentException
+                    ("offset or length is less than 0");
+            }
+            if (signature.length - offset < length) {
+                throw new IllegalArgumentException
+                    ("signature too small for specified offset and length");
             }
 
             return engineVerify(signature, offset, length);
@@ -807,17 +856,17 @@
      */
     public final void update(byte[] data, int off, int len)
             throws SignatureException {
-        // Android-changed: Check data, off & len early and throw an exception
-        // as soon as possible.
-        if (data == null) {
-            throw new IllegalArgumentException("data == null");
-        }
-
-        if (off < 0 || len < 0 || off + len > data.length) {
-            throw new IllegalArgumentException();
-        }
-
         if (state == SIGN || state == VERIFY) {
+            if (data == null) {
+                throw new IllegalArgumentException("data is null");
+            }
+            if (off < 0 || len < 0) {
+                throw new IllegalArgumentException("off or len is less than 0");
+            }
+            if (data.length - off < len) {
+                throw new IllegalArgumentException
+                    ("data too small for specified offset and length");
+            }
             engineUpdate(data, off, len);
         } else {
             throw new SignatureException("object not initialized for "
@@ -827,8 +876,8 @@
 
     /**
      * Updates the data to be signed or verified using the specified
-     * ByteBuffer. Processes the <code>data.remaining()</code> bytes
-     * starting at at <code>data.position()</code>.
+     * ByteBuffer. Processes the {@code data.remaining()} bytes
+     * starting at at {@code data.position()}.
      * Upon return, the buffer's position will be equal to its limit;
      * its limit will not have changed.
      *
@@ -895,7 +944,7 @@
      * @param param the string identifier of the parameter.
      * @param value the parameter value.
      *
-     * @exception InvalidParameterException if <code>param</code> is an
+     * @exception InvalidParameterException if {@code param} is an
      * invalid parameter for this signature algorithm engine,
      * the parameter is already set
      * and cannot be set again, a security exception occurs, and so on.
@@ -961,7 +1010,7 @@
      * @return the object that represents the parameter value, or null if
      * there is none.
      *
-     * @exception InvalidParameterException if <code>param</code> is an invalid
+     * @exception InvalidParameterException if {@code param} is an invalid
      * parameter for this engine, or another exception occurs while
      * trying to get this parameter.
      *
@@ -982,7 +1031,7 @@
      * @return a clone if the implementation is cloneable.
      *
      * @exception CloneNotSupportedException if this is called
-     * on an implementation that does not support <code>Cloneable</code>.
+     * on an implementation that does not support {@code Cloneable}.
      */
     public Object clone() throws CloneNotSupportedException {
         if (this instanceof Cloneable) {
@@ -1015,6 +1064,7 @@
      * and its original parent (Object).
      */
 
+    @SuppressWarnings("deprecation")
     private static class Delegate extends Signature {
 
         // The provider implementation (delegate)
@@ -1043,7 +1093,7 @@
          * @return a clone if the delegate is cloneable.
          *
          * @exception CloneNotSupportedException if this is called on a
-         * delegate that does not support <code>Cloneable</code>.
+         * delegate that does not support {@code Cloneable}.
          */
         public Object clone() throws CloneNotSupportedException {
             chooseFirstProvider();
@@ -1097,6 +1147,7 @@
                 if (sigSpi != null) {
                     return;
                 }
+                /* BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
                 if (debug != null) {
                     int w = --warnCount;
                     if (w >= 0) {
@@ -1109,6 +1160,7 @@
                         new Exception("Call trace").printStackTrace();
                     }
                 }
+                 * END ANDROID-REMOVED */
                 Exception lastException = null;
                 List<Service> list;
                 if (((Signature)this).algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
@@ -1313,6 +1365,7 @@
     }
 
     // adapter for RSA/ECB/PKCS1Padding ciphers
+    @SuppressWarnings("deprecation")
     private static class CipherAdapter extends SignatureSpi {
 
         private final Cipher cipher;
@@ -1378,7 +1431,7 @@
                 byte[] out = cipher.doFinal(sigBytes);
                 byte[] dataBytes = data.toByteArray();
                 data.reset();
-                return Arrays.equals(out, dataBytes);
+                return MessageDigest.isEqual(out, dataBytes);
             } catch (BadPaddingException e) {
                 // e.g. wrong public key used
                 // return false rather than throwing exception
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index c1301b3..de2a93e 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -39,25 +39,35 @@
 
 package java.text;
 
+import android.icu.text.TimeZoneFormat;
+import android.icu.text.TimeZoneNames;
+import android.icu.util.ULocale;
+
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
+import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.GregorianCalendar;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import libcore.icu.LocaleData;
-import libcore.icu.TimeZoneNames;
 
 import sun.util.calendar.CalendarUtils;
 
 import static java.text.DateFormatSymbols.*;
 
+// Android-changed: Added supported API level, removed unnecessary <br>
 /**
  * <code>SimpleDateFormat</code> is a concrete class for formatting and
  * parsing dates in a locale-sensitive manner. It allows for formatting
@@ -100,116 +110,139 @@
  *         <th align=left>Date or Time Component
  *         <th align=left>Presentation
  *         <th align=left>Examples
+ *         <th align=left>Supported (API Levels)
  *     <tr>
  *         <td><code>G</code>
  *         <td>Era designator
  *         <td><a href="#text">Text</a>
  *         <td><code>AD</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>y</code>
  *         <td>Year
  *         <td><a href="#year">Year</a>
  *         <td><code>1996</code>; <code>96</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>Y</code>
  *         <td>Week year
  *         <td><a href="#year">Year</a>
  *         <td><code>2009</code>; <code>09</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>M</code>
  *         <td>Month in year (context sensitive)
  *         <td><a href="#month">Month</a>
  *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>w</code>
  *         <td>Week in year
  *         <td><a href="#number">Number</a>
  *         <td><code>27</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>W</code>
  *         <td>Week in month
  *         <td><a href="#number">Number</a>
  *         <td><code>2</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>D</code>
  *         <td>Day in year
  *         <td><a href="#number">Number</a>
  *         <td><code>189</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>d</code>
  *         <td>Day in month
  *         <td><a href="#number">Number</a>
  *         <td><code>10</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>F</code>
  *         <td>Day of week in month
  *         <td><a href="#number">Number</a>
  *         <td><code>2</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>E</code>
  *         <td>Day name in week
  *         <td><a href="#text">Text</a>
  *         <td><code>Tuesday</code>; <code>Tue</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>u</code>
  *         <td>Day number of week (1 = Monday, ..., 7 = Sunday)
  *         <td><a href="#number">Number</a>
  *         <td><code>1</code>
+ *         <td>24+</td>
  *     <tr>
  *         <td><code>a</code>
  *         <td>Am/pm marker
  *         <td><a href="#text">Text</a>
  *         <td><code>PM</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>H</code>
  *         <td>Hour in day (0-23)
  *         <td><a href="#number">Number</a>
  *         <td><code>0</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>k</code>
  *         <td>Hour in day (1-24)
  *         <td><a href="#number">Number</a>
  *         <td><code>24</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>K</code>
  *         <td>Hour in am/pm (0-11)
  *         <td><a href="#number">Number</a>
  *         <td><code>0</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>h</code>
  *         <td>Hour in am/pm (1-12)
  *         <td><a href="#number">Number</a>
  *         <td><code>12</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>m</code>
  *         <td>Minute in hour
  *         <td><a href="#number">Number</a>
  *         <td><code>30</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>s</code>
  *         <td>Second in minute
  *         <td><a href="#number">Number</a>
  *         <td><code>55</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>S</code>
  *         <td>Millisecond
  *         <td><a href="#number">Number</a>
  *         <td><code>978</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>z</code>
  *         <td>Time zone
  *         <td><a href="#timezone">General time zone</a>
  *         <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
+ *         <td>1+</td>
  *     <tr style="background-color: rgb(238, 238, 255);">
  *         <td><code>Z</code>
  *         <td>Time zone
  *         <td><a href="#rfc822timezone">RFC 822 time zone</a>
  *         <td><code>-0800</code>
+ *         <td>1+</td>
  *     <tr>
  *         <td><code>X</code>
  *         <td>Time zone
  *         <td><a href="#iso8601timezone">ISO 8601 time zone</a>
  *         <td><code>-08</code>; <code>-0800</code>;  <code>-08:00</code>
+ *         <td>1+</td>
  * </table>
  * </blockquote>
  * Pattern letters are usually repeated, as their number determines the
@@ -220,15 +253,15 @@
  *     the full form is used; otherwise a short or abbreviated form
  *     is used if available.
  *     For parsing, both forms are accepted, independent of the number
- *     of pattern letters.<br><br></li>
+ *     of pattern letters.</li>
  * <li><strong><a name="number">Number:</a></strong>
  *     For formatting, the number of pattern letters is the minimum
  *     number of digits, and shorter numbers are zero-padded to this amount.
  *     For parsing, the number of pattern letters is ignored unless
- *     it's needed to separate two adjacent fields.<br><br></li>
+ *     it's needed to separate two adjacent fields.</li>
  * <li><strong><a name="year">Year:</a></strong>
  *     If the formatter's {@link #getCalendar() Calendar} is the Gregorian
- *     calendar, the following rules are applied.<br>
+ *     calendar, the following rules are applied.
  *     <ul>
  *     <li>For formatting, if the number of pattern letters is 2, the year
  *         is truncated to 2 digits; otherwise it is interpreted as a
@@ -257,7 +290,7 @@
  *     letters is 4 or more, a calendar specific {@linkplain
  *     Calendar#LONG long form} is used. Otherwise, a calendar
  *     specific {@linkplain Calendar#SHORT short or abbreviated form}
- *     is used.<br>
+ *     is used.
  *     <br>
  *     If week year {@code 'Y'} is specified and the {@linkplain
  *     #getCalendar() calendar} doesn't support any <a
@@ -266,11 +299,11 @@
  *     support of week years can be tested with a call to {@link
  *     DateFormat#getCalendar() getCalendar()}.{@link
  *     java.util.Calendar#isWeekDateSupported()
- *     isWeekDateSupported()}.<br><br></li>
+ *     isWeekDateSupported()}.</li>
  * <li><strong><a name="month">Month:</a></strong>
  *     If the number of pattern letters is 3 or more, the month is
  *     interpreted as <a href="#text">text</a>; otherwise,
- *     it is interpreted as a <a href="#number">number</a>.<br><br></li>
+ *     it is interpreted as a <a href="#number">number</a>.</li>
  * <li><strong><a name="timezone">General time zone:</a></strong>
  *     Time zones are interpreted as <a href="#text">text</a> if they have
  *     names. For time zones representing a GMT offset value, the
@@ -291,7 +324,7 @@
  *     00 and 59. The format is locale independent and digits must be taken
  *     from the Basic Latin block of the Unicode standard.
  *     <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
- *     accepted.<br><br></li>
+ *     accepted.</li>
  * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
  *     For formatting, the RFC 822 4-digit time zone format is used:
  *
@@ -501,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
@@ -533,6 +560,11 @@
     transient boolean useDateFormatSymbols;
 
     /**
+     * ICU TimeZoneNames used to format and parse time zone names.
+     */
+    private transient TimeZoneNames timeZoneNames;
+
+    /**
      * Constructs a <code>SimpleDateFormat</code> using the default pattern and
      * date format symbols for the default
      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
@@ -624,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");
@@ -1116,6 +1135,16 @@
         Field.DAY_OF_WEEK
     };
 
+    private static final String UTC = "UTC";
+
+    /**
+     * The list of time zone ids formatted as "UTC".
+     * This mirrors isUtc in libcore_icu_TimeZoneNames.cpp
+     */
+    private static final Set<String> UTC_ZONE_IDS = Collections.unmodifiableSet(new HashSet<>(
+            Arrays.asList("Etc/UCT", "Etc/UTC", "Etc/Universal", "Etc/Zulu", "UCT", "UTC",
+                    "Universal", "Zulu")));
+
     /**
      * Private member function that does the real date/time formatting.
      */
@@ -1241,13 +1270,32 @@
             if (current == null) {
                 TimeZone tz = calendar.getTimeZone();
                 boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
-                int tzstyle = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
                 String zoneString;
                 if (formatData.isZoneStringsSet) {
-                    zoneString = TimeZoneNames.getDisplayName(
+                    // DateFormatSymbols.setZoneStrings() has be used, use those values instead of
+                    // ICU code.
+                    int tzstyle = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
+                    zoneString = libcore.icu.TimeZoneNames.getDisplayName(
                             formatData.getZoneStringsWrapper(), tz.getID(), daylight, tzstyle);
                 } else {
-                    zoneString = tz.getDisplayName(daylight, tzstyle, formatData.locale);
+                    if (UTC_ZONE_IDS.contains(tz.getID())) {
+                        // ICU doesn't have name strings for UTC, explicitly print it as "UTC".
+                        zoneString = UTC;
+                    } else {
+                        TimeZoneNames.NameType nameType;
+                        if (count < 4) {
+                            nameType = daylight
+                                    ? TimeZoneNames.NameType.SHORT_DAYLIGHT
+                                    : TimeZoneNames.NameType.SHORT_STANDARD;
+                        } else {
+                            nameType = daylight
+                                    ? TimeZoneNames.NameType.LONG_DAYLIGHT
+                                    : TimeZoneNames.NameType.LONG_STANDARD;
+                        }
+                        String canonicalID = android.icu.util.TimeZone.getCanonicalID(tz.getID());
+                        zoneString = getTimeZoneNames()
+                                .getDisplayName(canonicalID, nameType, calendar.getTimeInMillis());
+                    }
                 }
                 if (zoneString != null) {
                     buffer.append(zoneString);
@@ -1694,22 +1742,127 @@
         return -1;
     }
 
-    private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex,
-                                   String[][] zoneStrings) {
-        int index = standardIndex + 2;
-        String zoneName  = zoneStrings[zoneIndex][index];
-        if (text.regionMatches(true, start,
-                               zoneName, 0, zoneName.length())) {
-            return true;
+    /**
+     * Parses the string in {@code text} (starting at {@code start}), interpreting it as a time zone
+     * name. If a time zone is found, the internal calendar is set to that timezone and the index of
+     * the first character after the time zone name is returned. Otherwise, returns {@code 0}.
+     * @return the index of the next character to parse or {@code 0} on error.
+     */
+    private int subParseZoneString(String text, int start, CalendarBuilder calb) {
+        if (formatData.isZoneStringsSet) {
+            // DateFormatSymbols.setZoneStrings() has be used, use those values instead of ICU code.
+            return subParseZoneStringFromSymbols(text, start, calb);
+        } else {
+            return subParseZoneStringFromICU(text, start, calb);
         }
-        return false;
+    }
+
+    private TimeZoneNames getTimeZoneNames() {
+        if (timeZoneNames == null) {
+            timeZoneNames = TimeZoneNames.getInstance(locale);
+        }
+        return timeZoneNames;
     }
 
     /**
-     * find time zone 'text' matched zoneStrings and set to internal
-     * calendar.
+     * The set of name types accepted when parsing time zone names.
      */
-    private int subParseZoneString(String text, int start, CalendarBuilder calb) {
+    private static final EnumSet<TimeZoneNames.NameType> NAME_TYPES =
+            EnumSet.of(TimeZoneNames.NameType.LONG_GENERIC, TimeZoneNames.NameType.LONG_STANDARD,
+                    TimeZoneNames.NameType.LONG_DAYLIGHT, TimeZoneNames.NameType.SHORT_GENERIC,
+                    TimeZoneNames.NameType.SHORT_STANDARD, TimeZoneNames.NameType.SHORT_DAYLIGHT);
+
+    /**
+     * Time zone name types that indicate daylight saving time.
+     */
+    private static final Set<TimeZoneNames.NameType> DST_NAME_TYPES =
+            Collections.unmodifiableSet(EnumSet.of(
+                    TimeZoneNames.NameType.LONG_DAYLIGHT, TimeZoneNames.NameType.SHORT_DAYLIGHT));
+
+    /**
+     * Parses the time zone string using the ICU4J class {@link TimeZoneNames}.
+     */
+    private int subParseZoneStringFromICU(String text, int start, CalendarBuilder calb) {
+        String currentTimeZoneID = android.icu.util.TimeZone.getCanonicalID(getTimeZone().getID());
+
+        TimeZoneNames tzNames = getTimeZoneNames();
+        TimeZoneNames.MatchInfo bestMatch = null;
+        // The MetaZones associated with the current time zone are needed in two places, both of
+        // which are avoided in some cases, so they are computed lazily.
+        Set<String> currentTzMetaZoneIds = null;
+
+        // ICU doesn't parse the string "UTC", so manually check for it.
+        if (start + UTC.length() <= text.length() &&
+                text.regionMatches(true /* ignoreCase */, start, UTC, 0, UTC.length())) {
+            bestMatch = new TimeZoneNames.MatchInfo(
+                    TimeZoneNames.NameType.SHORT_GENERIC, UTC, null, UTC.length());
+        } else {
+            Collection<TimeZoneNames.MatchInfo> matches = tzNames.find(text, start, NAME_TYPES);
+            for (TimeZoneNames.MatchInfo match : matches) {
+                if (bestMatch == null || bestMatch.matchLength() < match.matchLength()) {
+                    bestMatch = match;
+                } else if (bestMatch.matchLength() == match.matchLength()) {
+                    if (currentTimeZoneID.equals(match.tzID())) {
+                        // Prefer the currently set timezone over other matches, even if they are
+                        // the same length.
+                        bestMatch = match;
+                        break;
+                    } else if (match.mzID() != null) {
+                        if (currentTzMetaZoneIds == null) {
+                            currentTzMetaZoneIds =
+                                    tzNames.getAvailableMetaZoneIDs(currentTimeZoneID);
+                        }
+                        if (currentTzMetaZoneIds.contains(match.mzID())) {
+                            bestMatch = match;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (bestMatch == null) {
+                // No match found, return error.
+                return 0;
+            }
+        }
+
+        String tzId = bestMatch.tzID();
+        if (tzId == null) {
+            if (currentTzMetaZoneIds == null) {
+                currentTzMetaZoneIds = tzNames.getAvailableMetaZoneIDs(currentTimeZoneID);
+            }
+            if (currentTzMetaZoneIds.contains(bestMatch.mzID())) {
+                tzId = currentTimeZoneID;
+            } else {
+                // Match was for a meta-zone, find the matching reference zone.
+                ULocale uLocale = ULocale.forLocale(locale);
+                String region = uLocale.getCountry();
+                if (region.length() == 0) {
+                    uLocale = ULocale.addLikelySubtags(uLocale);
+                    region = uLocale.getCountry();
+                }
+                tzId = tzNames.getReferenceZoneID(bestMatch.mzID(), region);
+            }
+        }
+
+        TimeZone newTimeZone = TimeZone.getTimeZone(tzId);
+        if (!currentTimeZoneID.equals(tzId)) {
+            setTimeZone(newTimeZone);
+        }
+
+        // Same logic as in subParseZoneStringFromSymbols, see below for details.
+        boolean isDst = DST_NAME_TYPES.contains(bestMatch.nameType());
+        int dstAmount = isDst ? newTimeZone.getDSTSavings() : 0;
+        if (!isDst || dstAmount != 0) {
+            calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount);
+        }
+
+        return bestMatch.matchLength() + start;
+    }
+
+    /**
+     * Parses the time zone string using the information in {@link #formatData}.
+     */
+    private int subParseZoneStringFromSymbols(String text, int start, CalendarBuilder calb) {
         boolean useSameName = false; // true if standard and daylight time use the same abbreviation.
         TimeZone currentTimeZone = getTimeZone();
 
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/java/util/Currency.java b/ojluni/src/main/java/java/util/Currency.java
index da6df1b..9856f50 100644
--- a/ojluni/src/main/java/java/util/Currency.java
+++ b/ojluni/src/main/java/java/util/Currency.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,49 +27,45 @@
 package java.util;
 
 import java.io.Serializable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import libcore.icu.ICU;
 
 /**
  * Represents a currency. Currencies are identified by their ISO 4217 currency
- * codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html">
- * ISO web site</a> for more information, including a table of
- * currency codes.
+ * codes. Visit the <a href="http://www.iso.org/iso/home/standards/currency_codes.htm">
+ * ISO web site</a> for more information.
  * <p>
  * The class is designed so that there's never more than one
  * <code>Currency</code> instance for any given currency. Therefore, there's
  * no public constructor. You obtain a <code>Currency</code> instance using
  * the <code>getInstance</code> methods.
- * <p>
- * Users can supersede the Java runtime currency data by creating a properties
- * file named <code>&lt;JAVA_HOME&gt;/lib/currency.properties</code>.  The contents
- * of the properties file are key/value pairs of the ISO 3166 country codes
- * and the ISO 4217 currency data respectively.  The value part consists of
- * three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric
- * code, and a minor unit.  Those three ISO 4217 values are separated by commas.
- * The lines which start with '#'s are considered comment lines.  For example,
- * <p>
- * <code>
- * #Sample currency properties<br>
- * JP=JPZ,999,0
- * </code>
- * <p>
- * will supersede the currency data for Japan.
  *
  * @since 1.4
  */
+// Android-changed: Superseding runtime currency data via a properties file is not
+// supported on Android.
 public final class Currency implements Serializable {
 
     private static final long serialVersionUID = -158308464356906721L;
 
-    private static HashMap<String, Currency> instances = new HashMap<>();
+    /**
+     * ISO 4217 currency code for this currency.
+     *
+     * @serial
+     */
+    private final String currencyCode;
 
+    // class data: instance map
+
+    private static ConcurrentMap<String, Currency> instances = new ConcurrentHashMap<>(7);
     private static HashSet<Currency> available;
 
+    // Android-changed: Implement Currency on top of ICU throughout.
+    // We do not keep track of defaultFractionDigits and numericCode separately here.
     private transient final android.icu.util.Currency icuCurrency;
 
-    private final String currencyCode;
-
     /**
      * Constructs a <code>Currency</code> instance. The constructor is private
      * so that we can insure that there's never more than one instance for a
@@ -90,19 +86,20 @@
      * a supported ISO 4217 code.
      */
     public static Currency getInstance(String currencyCode) {
-        synchronized (instances) {
-            Currency instance = instances.get(currencyCode);
-            if (instance == null) {
-                android.icu.util.Currency icuInstance =
-                        android.icu.util.Currency.getInstance(currencyCode);
-                if (icuInstance == null) {
-                    return null;
-                }
-                instance = new Currency(icuInstance);
-                instances.put(currencyCode, instance);
-            }
+        // Android-changed BEGIN: use ICU
+        Currency instance = instances.get(currencyCode);
+        if (instance != null) {
             return instance;
         }
+        android.icu.util.Currency icuInstance =
+                  android.icu.util.Currency.getInstance(currencyCode);
+        if (icuInstance == null) {
+            return null;
+        }
+        Currency currencyVal = new Currency(icuInstance);
+        // ANDROID-changed END
+        instance = instances.putIfAbsent(currencyCode, currencyVal);
+        return (instance != null ? instance : currencyVal);
     }
 
     /**
@@ -120,13 +117,14 @@
      * @param locale the locale for whose country a <code>Currency</code>
      * instance is needed
      * @return the <code>Currency</code> instance for the country of the given
-     * locale, or null
+     * locale, or {@code null}
      * @exception NullPointerException if <code>locale</code> or its country
-     * code is null
-     * @exception IllegalArgumentException if the country of the given locale
+     * code is {@code null}
+     * @exception IllegalArgumentException if the country of the given {@code locale}
      * is not a supported ISO 3166 country code.
      */
     public static Currency getInstance(Locale locale) {
+        // Android-changed BEGIN: use ICU
         android.icu.util.Currency icuInstance =
                 android.icu.util.Currency.getInstance(locale);
         String variant = locale.getVariant();
@@ -143,6 +141,7 @@
             return null;
         }
         return getInstance(currencyCode);
+        // Android-changed END
     }
 
     /**
@@ -156,8 +155,9 @@
      * @since 1.7
      */
     public static Set<Currency> getAvailableCurrencies() {
-        synchronized (Currency.class) {
+        synchronized(Currency.class) {
             if (available == null) {
+                // Android-changed BEGIN: use ICU
                 Set<android.icu.util.Currency> icuAvailableCurrencies
                         = android.icu.util.Currency.getAvailableCurrencies();
                 available = new HashSet<>();
@@ -169,9 +169,13 @@
                     }
                     available.add(currency);
                 }
+                // Android-changed END
             }
-            return (Set<Currency>) available.clone();
         }
+
+        @SuppressWarnings("unchecked")
+        Set<Currency> result = (Set<Currency>) available.clone();
+        return result;
     }
 
     /**
@@ -184,15 +188,21 @@
     }
 
     /**
-     * Gets the symbol of this currency for the default locale.
+     * Gets the symbol of this currency for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale.
      * For example, for the US Dollar, the symbol is "$" if the default
      * locale is the US, while for other locales it may be "US$". If no
      * symbol can be determined, the ISO 4217 currency code is returned.
+     * <p>
+     * This is equivalent to calling
+     * {@link #getSymbol(Locale)
+     *     getSymbol(Locale.getDefault(Locale.Category.DISPLAY))}.
      *
-     * @return the symbol of this currency for the default locale
+     * @return the symbol of this currency for the default
+     *     {@link Locale.Category#DISPLAY DISPLAY} locale
      */
     public String getSymbol() {
-        return icuCurrency.getSymbol();
+        return getSymbol(Locale.getDefault(Locale.Category.DISPLAY));
     }
 
     /**
@@ -207,10 +217,12 @@
      * @exception NullPointerException if <code>locale</code> is null
      */
     public String getSymbol(Locale locale) {
+        // Android-changed BEGIN: use ICU
         if (locale == null) {
             throw new NullPointerException("locale == null");
         }
         return icuCurrency.getSymbol(locale);
+        // Android-changed END
     }
 
     /**
@@ -223,10 +235,12 @@
      * @return the default number of fraction digits used with this currency
      */
     public int getDefaultFractionDigits() {
+        // Android-changed BEGIN: use ICU
         if (icuCurrency.getCurrencyCode().equals("XXX")) {
             return -1;
         }
         return icuCurrency.getDefaultFractionDigits();
+        // Android-changed END
     }
 
     /**
@@ -236,19 +250,27 @@
      * @since 1.7
      */
     public int getNumericCode() {
+        // Android-changed: use ICU
+        // was: return numericCode;
         return icuCurrency.getNumericCode();
     }
 
     /**
      * Gets the name that is suitable for displaying this currency for
-     * the default locale.  If there is no suitable display name found
+     * the default {@link Locale.Category#DISPLAY DISPLAY} locale.
+     * If there is no suitable display name found
      * for the default locale, the ISO 4217 currency code is returned.
+     * <p>
+     * This is equivalent to calling
+     * {@link #getDisplayName(Locale)
+     *     getDisplayName(Locale.getDefault(Locale.Category.DISPLAY))}.
      *
-     * @return the display name of this currency for the default locale
+     * @return the display name of this currency for the default
+     *     {@link Locale.Category#DISPLAY DISPLAY} locale
      * @since 1.7
      */
     public String getDisplayName() {
-        return icuCurrency.getDisplayName();
+        return getDisplayName(Locale.getDefault(Locale.Category.DISPLAY));
     }
 
     /**
@@ -263,7 +285,8 @@
      * @since 1.7
      */
     public String getDisplayName(Locale locale) {
-        return icuCurrency.getDisplayName(locale);
+        // Android-changed: use ICU
+        return icuCurrency.getDisplayName(Objects.requireNonNull(locale));
     }
 
     /**
@@ -271,7 +294,9 @@
      *
      * @return the ISO 4217 currency code of this currency
      */
+    @Override
     public String toString() {
+        // Android-changed: use ICU
         return icuCurrency.toString();
     }
 
diff --git a/ojluni/src/main/java/java/util/Formattable.java b/ojluni/src/main/java/java/util/Formattable.java
index 28b788c..f7e1e50 100644
--- a/ojluni/src/main/java/java/util/Formattable.java
+++ b/ojluni/src/main/java/java/util/Formattable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
  * For example, the following class prints out different representations of a
  * stock's name depending on the flags and length constraints:
  *
- * <blockquote><pre>
+ * {@code
  *   import java.nio.CharBuffer;
  *   import java.util.Formatter;
  *   import java.util.Formattable;
@@ -89,12 +89,12 @@
  *           return String.format("%s - %s", symbol, companyName);
  *       }
  *   }
- * </pre></blockquote>
+ * }
  *
  * <p> When used in conjunction with the {@link java.util.Formatter}, the above
  * class produces the following output for various format strings.
  *
- * <blockquote><pre>
+ * {@code
  *   Formatter fmt = new Formatter();
  *   StockName sn = new StockName("HUGE", "Huge Fruit, Inc.",
  *                                "Fruit Titanesque, Inc.");
@@ -104,7 +104,7 @@
  *   fmt.format("%-10.8s", sn);              //   -> "HUGE      "
  *   fmt.format("%.12s", sn);                //   -> "Huge Fruit,*"
  *   fmt.format(Locale.FRANCE, "%25s", sn);  //   -> "   Fruit Titanesque, Inc."
- * </pre></blockquote>
+ * }
  *
  * <p> Formattables are not necessarily safe for multithreaded access.  Thread
  * safety is optional and may be enforced by classes that extend and implement
diff --git a/ojluni/src/main/java/java/util/IllegalFormatConversionException.java b/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
index 9bdbfc4..a9b006f 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -40,7 +40,7 @@
     private static final long serialVersionUID = 17000126L;
 
     private char c;
-    private Class arg;
+    private Class<?> arg;
 
     /**
      * Constructs an instance of this class with the mismatched conversion and
diff --git a/ojluni/src/main/java/java/util/InvalidPropertiesFormatException.java b/ojluni/src/main/java/java/util/InvalidPropertiesFormatException.java
index 64dde4d..bacab3d 100644
--- a/ojluni/src/main/java/java/util/InvalidPropertiesFormatException.java
+++ b/ojluni/src/main/java/java/util/InvalidPropertiesFormatException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -44,6 +44,9 @@
  */
 
 public class InvalidPropertiesFormatException extends IOException {
+
+    private static final long serialVersionUID = 7763056076009360219L;
+
     /**
      * Constructs an InvalidPropertiesFormatException with the specified
      * cause.
diff --git a/ojluni/src/main/java/java/util/ListResourceBundle.java b/ojluni/src/main/java/java/util/ListResourceBundle.java
index 736016f..99090ca 100644
--- a/ojluni/src/main/java/java/util/ListResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ListResourceBundle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, 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
@@ -89,7 +89,7 @@
  *
  * public class MyResources_fr extends ListResourceBundle {
  *     protected Object[][] getContents() {
- *         return new Object[][] = {
+ *         return new Object[][] {
  *         // LOCALIZE THIS
  *             {"s1", "Le disque \"{1}\" {0}."},          // MessageFormat pattern
  *             {"s2", "1"},                               // location of {0} in pattern
@@ -105,6 +105,12 @@
  * }
  * </pre>
  * </blockquote>
+ *
+ * <p>
+ * The implementation of a {@code ListResourceBundle} subclass must be thread-safe
+ * if it's simultaneously used by multiple threads. The default implementations
+ * of the methods in this class are thread-safe.
+ *
  * @see ResourceBundle
  * @see PropertyResourceBundle
  * @since JDK1.1
@@ -200,5 +206,8 @@
         lookup = temp;
     }
 
-    private Map<String,Object> lookup = null;
+    // Android-changed: Fix unsafe publication http://b/31467561
+    // Fixed in OpenJDK 9: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/29ecac30ecae
+    // was: private Map<String,Object> lookup = null;
+    private volatile Map<String,Object> lookup = null;
 }
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 5d1a775..fa29e1d 100644
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.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, 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
@@ -82,7 +82,7 @@
  * described below.
  *
  * <dl>
- *   <dt><a name="def_language"></a><b>language</b></dt>
+ *   <dt><a name="def_language"><b>language</b></a></dt>
  *
  *   <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
  *   language subtags up to 8 alpha letters (for future enhancements).
@@ -90,51 +90,51 @@
  *   alpha-2 code must be used.  You can find a full list of valid
  *   language codes in the IANA Language Subtag Registry (search for
  *   "Type: language").  The language field is case insensitive, but
- *   <code>Locale</code> always canonicalizes to lower case.</dd><br>
+ *   <code>Locale</code> always canonicalizes to lower case.</dd>
  *
  *   <dd>Well-formed language values have the form
  *   <code>[a-zA-Z]{2,8}</code>.  Note that this is not the the full
  *   BCP47 language production, since it excludes extlang.  They are
  *   not needed since modern three-letter language codes replace
- *   them.</dd><br>
+ *   them.</dd>
  *
- *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
+ *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd>
  *
- *   <dt><a name="def_script"/></a><b>script</b></dt>
+ *   <dt><a name="def_script"><b>script</b></a></dt>
  *
  *   <dd>ISO 15924 alpha-4 script code.  You can find a full list of
  *   valid script codes in the IANA Language Subtag Registry (search
  *   for "Type: script").  The script field is case insensitive, but
  *   <code>Locale</code> always canonicalizes to title case (the first
  *   letter is upper case and the rest of the letters are lower
- *   case).</dd><br>
+ *   case).</dd>
  *
  *   <dd>Well-formed script values have the form
- *   <code>[a-zA-Z]{4}</code></dd><br>
+ *   <code>[a-zA-Z]{4}</code></dd>
  *
- *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
+ *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd>
  *
- *   <dt><a name="def_region"></a><b>country (region)</b></dt>
+ *   <dt><a name="def_region"><b>country (region)</b></a></dt>
  *
  *   <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
  *   You can find a full list of valid country and region codes in the
  *   IANA Language Subtag Registry (search for "Type: region").  The
  *   country (region) field is case insensitive, but
- *   <code>Locale</code> always canonicalizes to upper case.</dd><br>
+ *   <code>Locale</code> always canonicalizes to upper case.</dd>
  *
  *   <dd>Well-formed country/region values have
- *   the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
+ *   the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd>
  *
  *   <dd>Example: "US" (United States), "FR" (France), "029"
- *   (Caribbean)</dd><br>
+ *   (Caribbean)</dd>
  *
- *   <dt><a name="def_variant"></a><b>variant</b></dt>
+ *   <dt><a name="def_variant"><b>variant</b></a></dt>
  *
  *   <dd>Any arbitrary value used to indicate a variation of a
  *   <code>Locale</code>.  Where there are two or more variant values
  *   each indicating its own semantics, these values should be ordered
  *   by importance, with most important first, separated by
- *   underscore('_').  The variant field is case sensitive.</dd><br>
+ *   underscore('_').  The variant field is case sensitive.</dd>
  *
  *   <dd>Note: IETF BCP 47 places syntactic restrictions on variant
  *   subtags.  Also BCP 47 subtags are strictly used to indicate
@@ -150,16 +150,16 @@
  *   cultural behaviors such as calendar type or number script.  In
  *   BCP 47 this kind of information, which does not identify the
  *   language, is supported by extension subtags or private use
- *   subtags.</dd><br>
+ *   subtags.</dd>
  *
  *   <dd>Well-formed variant values have the form <code>SUBTAG
  *   (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
  *   [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
- *   uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
+ *   uses hyphen ('-') as a delimiter, this is more lenient).</dd>
  *
- *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
+ *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd>
  *
- *   <dt><a name="def_extensions"></a><b>extensions</b></dt>
+ *   <dt><a name="def_extensions"><b>extensions</b></a></dt>
  *
  *   <dd>A map from single character keys to string values, indicating
  *   extensions apart from language identification.  The extensions in
@@ -167,14 +167,14 @@
  *   extension subtags and private use subtags. The extensions are
  *   case insensitive, but <code>Locale</code> canonicalizes all
  *   extension keys and values to lower case. Note that extensions
- *   cannot have empty values.</dd><br>
+ *   cannot have empty values.</dd>
  *
  *   <dd>Well-formed keys are single characters from the set
  *   <code>[0-9a-zA-Z]</code>.  Well-formed values have the form
  *   <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
  *   <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
  *   <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
- *   single-character subtags).</dd><br>
+ *   single-character subtags).</dd>
  *
  *   <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
  *   key="x"/value="java-1-7"</dd>
@@ -187,7 +187,7 @@
  * requirement (is well-formed), but does not validate the value
  * itself.  See {@link Builder} for details.
  *
- * <h4><a name="def_locale_extension"></a>Unicode locale/language extension</h4>
+ * <h3><a name="def_locale_extension">Unicode locale/language extension</a></h3>
  *
  * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
  * attributes and keywords to override or refine the default behavior
@@ -278,7 +278,8 @@
  * you can use <code>getDisplayLanguage</code> to get the name of
  * the language suitable for displaying to the user. Interestingly,
  * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
- * and have two versions: one that uses the default locale and one
+ * and have two versions: one that uses the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale and one
  * that uses the locale specified as an argument.
  *
  * <p>The Java Platform provides a number of classes that perform locale-sensitive
@@ -296,7 +297,8 @@
  * </pre>
  * </blockquote>
  * Each of these methods has two variants; one with an explicit locale
- * and one without; the latter uses the default locale:
+ * and one without; the latter uses the default
+ * {@link Locale.Category#FORMAT FORMAT} locale:
  * <blockquote>
  * <pre>
  *     NumberFormat.getInstance(myLocale)
@@ -334,7 +336,7 @@
  * Clients desiring a string representation of the complete locale can
  * then always rely on <code>toLanguageTag</code> for this purpose.
  *
- * <h5><a name="special_cases_constructor"></a>Special cases</h5>
+ * <h5><a name="special_cases_constructor">Special cases</a></h5>
  *
  * <p>For compatibility reasons, two
  * non-conforming locales are treated as special cases.  These are
@@ -816,10 +818,6 @@
      */
     public static Locale getDefault() {
         // do not synchronize this method - see 4071298
-        // it's OK if more than one default locale happens to be created
-        if (defaultLocale == null) {
-            defaultLocale = initDefault();
-        }
         return defaultLocale;
     }
 
@@ -841,16 +839,23 @@
      */
     public static Locale getDefault(Locale.Category category) {
         // do not synchronize this method - see 4071298
-        // it's OK if more than one default locale happens to be created
         switch (category) {
         case DISPLAY:
             if (defaultDisplayLocale == null) {
-                defaultDisplayLocale = initDefault(category);
+                synchronized(Locale.class) {
+                    if (defaultDisplayLocale == null) {
+                        defaultDisplayLocale = initDefault(category);
+                    }
+                }
             }
             return defaultDisplayLocale;
         case FORMAT:
             if (defaultFormatLocale == null) {
-                defaultFormatLocale = initDefault(category);
+                synchronized(Locale.class) {
+                    if (defaultFormatLocale == null) {
+                        defaultFormatLocale = initDefault(category);
+                    }
+                }
             }
             return defaultFormatLocale;
         default:
@@ -859,6 +864,10 @@
         return getDefault();
     }
 
+    // Android-changed BEGIN:
+    //  1.) In initDefault(), user.locale gets priority
+    //  2.) In both initDefault methods, use System.getProperty() instead
+    //      of legacy AccessController / GetPropertyAction security code.
     /**
      * @hide visible for testing.
      */
@@ -890,13 +899,11 @@
             country = System.getProperty("user.country", "");
             variant = System.getProperty("user.variant", "");
         }
+
         return getInstance(language, script, country, variant, null);
     }
 
     private static Locale initDefault(Locale.Category category) {
-        // make sure defaultLocale is initialized
-        final Locale defaultLocale = getDefault();
-
         return getInstance(
             System.getProperty(category.languageKey, defaultLocale.getLanguage()),
             System.getProperty(category.scriptKey, defaultLocale.getScript()),
@@ -904,6 +911,7 @@
             System.getProperty(category.variantKey, defaultLocale.getVariant()),
             null);
     }
+    // Android-changed END
 
     /**
      * Sets the default locale for this instance of the Java Virtual Machine.
@@ -937,6 +945,7 @@
         setDefault(Category.DISPLAY, newLocale);
         setDefault(Category.FORMAT, newLocale);
         defaultLocale = newLocale;
+        // Android-added
         ICU.setDefaultLocale(newLocale.toLanguageTag());
     }
 
@@ -1012,6 +1021,8 @@
      * country (region), such as 3-letter numeric UN M.49 area codes.
      * Therefore, the list returned by this method does not contain ALL valid
      * codes that can be used to create Locales.
+     *
+     * @return An array of ISO 3166 two-letter country codes.
      */
     public static String[] getISOCountries() {
         // Android-changed: Use ICU.
@@ -1031,6 +1042,8 @@
      * 8 characters in length.  Therefore, the list returned by this method does
      * not contain ALL valid codes that can be used to create Locales.
      * </ul>
+     *
+     * @return Am array of ISO 639 two-letter language codes.
      */
     public static String[] getISOLanguages() {
         // Android-changed: Use ICU.
@@ -1097,6 +1110,30 @@
     }
 
     /**
+     * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions">
+     * extensions</a>.
+     *
+     * @return {@code true} if this {@code Locale} has any extensions
+     * @since 1.8
+     */
+    public boolean hasExtensions() {
+        return localeExtensions != null;
+    }
+
+    /**
+     * Returns a copy of this {@code Locale} with no <a href="#def_extensions">
+     * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale}
+     * is returned.
+     *
+     * @return a copy of this {@code Locale} with no extensions, or {@code this}
+     *         if {@code this} has no extensions
+     * @since 1.8
+     */
+    public Locale stripExtensions() {
+        return hasExtensions() ? Locale.getInstance(baseLocale, null) : this;
+    }
+
+    /**
      * Returns the extension (or private use) value associated with
      * the specified key, or null if there is no extension
      * associated with the key. To be well-formed, the key must be one
@@ -1115,7 +1152,7 @@
         if (!LocaleExtensions.isValidKey(key)) {
             throw new IllegalArgumentException("Ill-formed extension key: " + key);
         }
-        return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
+        return hasExtensions() ? localeExtensions.getExtensionValue(key) : null;
     }
 
     /**
@@ -1128,7 +1165,7 @@
      * @since 1.7
      */
     public Set<Character> getExtensionKeys() {
-        if (localeExtensions == null) {
+        if (!hasExtensions()) {
             return Collections.emptySet();
         }
         return localeExtensions.getKeys();
@@ -1143,7 +1180,7 @@
      * @since 1.7
      */
     public Set<String> getUnicodeLocaleAttributes() {
-        if (localeExtensions == null) {
+        if (!hasExtensions()) {
             return Collections.emptySet();
         }
         return localeExtensions.getUnicodeLocaleAttributes();
@@ -1164,10 +1201,10 @@
      * @since 1.7
      */
     public String getUnicodeLocaleType(String key) {
-        if (!UnicodeLocaleExtension.isKey(key)) {
+        if (!isUnicodeExtensionKey(key)) {
             throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
         }
-        return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
+        return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null;
     }
 
     /**
@@ -1208,7 +1245,7 @@
      * Returns a string representation of this <code>Locale</code>
      * object, consisting of language, country, variant, script,
      * and extensions as below:
-     * <p><blockquote>
+     * <blockquote>
      * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
      * </blockquote>
      *
@@ -1232,15 +1269,15 @@
      * fields only.  To represent a Locale as a String for interchange purposes, use
      * {@link #toLanguageTag}.
      *
-     * <p>Examples: <ul><tt>
-     * <li>en
-     * <li>de_DE
-     * <li>_GB
-     * <li>en_US_WIN
-     * <li>de__POSIX
-     * <li>zh_CN_#Hans
-     * <li>zh_TW_#Hant-x-java
-     * <li>th_TH_TH_#u-nu-thai</tt></ul>
+     * <p>Examples: <ul>
+     * <li><tt>en</tt></li>
+     * <li><tt>de_DE</tt></li>
+     * <li><tt>_GB</tt></li>
+     * <li><tt>en_US_WIN</tt></li>
+     * <li><tt>de__POSIX</tt></li>
+     * <li><tt>zh_CN_#Hans</tt></li>
+     * <li><tt>zh_TW_#Hant-x-java</tt></li>
+     * <li><tt>th_TH_TH_#u-nu-thai</tt></li></ul>
      *
      * @return A string representation of the Locale, for debugging.
      * @see #getDisplayName
@@ -1348,6 +1385,10 @@
      * @since 1.7
      */
     public String toLanguageTag() {
+        if (languageTag != null) {
+            return languageTag;
+        }
+
         LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
         StringBuilder buf = new StringBuilder();
 
@@ -1391,7 +1432,13 @@
             buf.append(subtag);
         }
 
-        return buf.toString();
+        String langTag = buf.toString();
+        synchronized (this) {
+            if (languageTag == null) {
+                languageTag = langTag;
+            }
+        }
+        return languageTag;
     }
 
     /**
@@ -1449,7 +1496,7 @@
      *    // returns "ja-JP-u-ca-japanese-x-lvariant-JP"
      *    Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag();
      *    // returns "th-TH-u-nu-thai-x-lvariant-TH"
-     * <pre></ul>
+     * </pre></ul>
      *
      * <p>This implements the 'Language-Tag' production of BCP47, and
      * so supports grandfathered (regular and irregular) as well as
@@ -1460,7 +1507,7 @@
      *
      * <p>Grandfathered tags with canonical replacements are as follows:
      *
-     * <table>
+     * <table summary="Grandfathered tags with canonical replacements">
      * <tbody align="center">
      * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>modern replacement</th></tr>
      * <tr><td>art-lojban</td><td>&nbsp;</td><td>jbo</td></tr>
@@ -1489,7 +1536,7 @@
      * <p>Grandfathered tags with no modern replacement will be
      * converted as follows:
      *
-     * <table>
+     * <table summary="Grandfathered tags with no modern replacement">
      * <tbody align="center">
      * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>converts to</th></tr>
      * <tr><td>cel-gaulish</td><td>&nbsp;</td><td>xtg-x-cel-gaulish</td></tr>
@@ -1542,21 +1589,26 @@
      * three-letter language abbreviation is not available for this locale.
      */
     public String getISO3Language() throws MissingResourceException {
-        // Android-changed: Use ICU.getIso3Language. Also return "" for empty languages
-        // for the sake of backwards compatibility.
         String lang = baseLocale.getLanguage();
         if (lang.length() == 3) {
             return lang;
-        } else if (lang.isEmpty()) {
+        }
+        // Android-added BEGIN
+        // return "" for empty languages for the sake of backwards compatibility.
+        else if (lang.isEmpty()) {
             return "";
         }
+        // Android-added END
 
+        // Android-changed BEGIN: Use ICU.
+        // String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
+        // if (language3 == null) {
         String language3 = ICU.getISO3Language(lang);
         if (!lang.isEmpty() && language3.isEmpty()) {
+        // Android-changed END
             throw new MissingResourceException("Couldn't find 3-letter language code for "
                     + lang, "FormatData_" + toString(), "ShortLanguage");
         }
-
         return language3;
     }
 
@@ -1574,7 +1626,7 @@
      * three-letter country abbreviation is not available for this locale.
      */
     public String getISO3Country() throws MissingResourceException {
-        // Android changed: Use.getIso3Country. Also return "" for missing regions.
+        // Android-changed BEGIN: Use ICU. Also return "" for missing regions.
         final String region = baseLocale.getRegion();
         // Note that this will return an UN.M49 region code
         if (region.length() == 3) {
@@ -1589,25 +1641,34 @@
             throw new MissingResourceException("Couldn't find 3-letter country code for "
                     + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
         }
+        // Android-changed END
         return country3;
     }
 
     /**
      * Returns a name for the locale's language that is appropriate for display to the
      * user.
-     * If possible, the name returned will be localized for the default locale.
-     * For example, if the locale is fr_FR and the default locale
+     * If possible, the name returned will be localized for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale.
+     * For example, if the locale is fr_FR and the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale
      * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
-     * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
-     * If the name returned cannot be localized for the default locale,
+     * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
+     * getDisplayLanguage() will return "anglais".
+     * If the name returned cannot be localized for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale,
      * (say, we don't have a Japanese name for Croatian),
      * this function falls back on the English name, and uses the ISO code as a last-resort
      * value.  If the locale doesn't specify a language, this function returns the empty string.
+     *
+     * @return The name of the display language.
      */
     public final String getDisplayLanguage() {
         return getDisplayLanguage(getDefault(Category.DISPLAY));
     }
 
+    // Android-changed BEGIN: Use ICU; documentation; backwards compatibility hacks;
+    // added private helper methods.
     /**
      * Returns the name of this locale's language, localized to {@code locale}.
      * If the language name is unknown, the language code is returned.
@@ -1672,6 +1733,7 @@
 
         return true;
     }
+    // Android-changed END
 
     /**
      * Returns a name for the the locale's script that is appropriate for display to
@@ -1693,6 +1755,7 @@
      * @since 1.7
      */
     public String getDisplayScript(Locale locale) {
+        // Android-changed BEGIN: Use ICU.
         String scriptCode = baseLocale.getScript();
         if (scriptCode.isEmpty()) {
             return "";
@@ -1704,24 +1767,32 @@
         }
 
         return result;
-
+        // Android-changed END
     }
 
     /**
      * Returns a name for the locale's country that is appropriate for display to the
      * user.
-     * If possible, the name returned will be localized for the default locale.
-     * For example, if the locale is fr_FR and the default locale
+     * If possible, the name returned will be localized for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale.
+     * For example, if the locale is fr_FR and the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale
      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
-     * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
-     * If the name returned cannot be localized for the default locale,
+     * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
+     * getDisplayCountry() will return "Etats-Unis".
+     * If the name returned cannot be localized for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale,
      * (say, we don't have a Japanese name for Croatia),
      * this function falls back on the English name, and uses the ISO code as a last-resort
      * value.  If the locale doesn't specify a country, this function returns the empty string.
+     *
+     * @return The name of the country appropriate to the locale.
      */
     public final String getDisplayCountry() {
         return getDisplayCountry(getDefault(Category.DISPLAY));
     }
+
+    // Android-changed BEGIN: Use ICU; documentation; added private helper methods.
     /**
      * Returns the name of this locale's country, localized to {@code locale}.
      * Returns the empty string if this locale does not correspond to a specific
@@ -1798,24 +1869,31 @@
 
         return true;
     }
+    // Android-changed END
 
     /**
      * Returns a name for the locale's variant code that is appropriate for display to the
-     * user.  If possible, the name will be localized for the default locale.  If the locale
+     * user.  If possible, the name will be localized for the default
+     * {@link Locale.Category#DISPLAY DISPLAY} locale.  If the locale
      * doesn't specify a variant code, this function returns the empty string.
+     *
+     * @return The name of the display variant code appropriate to the locale.
      */
     public final String getDisplayVariant() {
         return getDisplayVariant(getDefault(Category.DISPLAY));
     }
 
     /**
-     * Returns the full variant name in the specified {@code Locale} for the variant code
-     * of this {@code Locale}. If there is no matching variant name, the variant code is
-     * returned.
+     * Returns a name for the locale's variant code that is appropriate for display to the
+     * user.  If possible, the name will be localized for inLocale.  If the locale
+     * doesn't specify a variant code, this function returns the empty string.
      *
-     * @since 1.7
+     * @param inLocale The locale for which to retrieve the display variant code.
+     * @return The name of the display variant code appropriate to the given locale.
+     * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
      */
-    public String getDisplayVariant(Locale locale) {
+    // Android-changed BEGIN: Use ICU; added private helper methods.
+    public String getDisplayVariant(Locale inLocale) {
         String variantCode = baseLocale.getVariant();
         if (variantCode.isEmpty()) {
             return "";
@@ -1827,7 +1905,7 @@
             return variantCode;
         }
 
-        String result = ICU.getDisplayVariant(this, locale);
+        String result = ICU.getDisplayVariant(this, inLocale);
         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
             result = ICU.getDisplayVariant(this, Locale.getDefault());
         }
@@ -1878,6 +1956,7 @@
 
         return false;
     }
+    // Android-changed END
 
     /**
      * Returns a name for the locale that is appropriate for display to the
@@ -1893,13 +1972,16 @@
      * country<br>
      * </blockquote>
      * depending on which fields are specified in the locale.  If the
-     * language, sacript, country, and variant fields are all empty,
+     * language, script, country, and variant fields are all empty,
      * this function returns the empty string.
+     *
+     * @return The name of the locale appropriate to display.
      */
     public final String getDisplayName() {
         return getDisplayName(getDefault(Category.DISPLAY));
     }
 
+    // Android-changed BEGIN: Use ICU.
     /**
      * Returns this locale's language name, country name, and variant, localized
      * to {@code locale}. The exact output form depends on whether this locale
@@ -1961,17 +2043,19 @@
         }
         return buffer.toString();
     }
+    // Android-changed END
 
     /**
      * Overrides Cloneable.
      */
+    @Override
     public Object clone()
     {
         try {
             Locale that = (Locale)super.clone();
             return that;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
@@ -2028,9 +2112,11 @@
      */
     private transient volatile int hashCodeValue = 0;
 
-    private static Locale defaultLocale = null;
-    private static Locale defaultDisplayLocale = null;
-    private static Locale defaultFormatLocale = null;
+    private volatile static Locale defaultLocale = initDefault();
+    private volatile static Locale defaultDisplayLocale = null;
+    private volatile static Locale defaultFormatLocale = null;
+
+    private transient volatile String languageTag;
 
     /**
      * Format a list using given pattern strings.
@@ -2047,9 +2133,11 @@
         // If we have no list patterns, compose the list in a simple,
         // non-localized way.
         if (listPattern == null || listCompositionPattern == null) {
-            StringBuffer result = new StringBuffer();
-            for (int i=0; i<stringList.length; ++i) {
-                if (i>0) result.append(',');
+            StringBuilder result = new StringBuilder();
+            for (int i = 0; i < stringList.length; ++i) {
+                if (i > 0) {
+                    result.append(',');
+                }
                 result.append(stringList[i]);
             }
             return result.toString();
@@ -2096,6 +2184,13 @@
         return composeList(format, newList);
     }
 
+    // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
+    // avoid its class loading.
+    private static boolean isUnicodeExtensionKey(String s) {
+        // 2alphanum
+        return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
+    }
+
     /**
      * @serialField language    String
      *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
@@ -2157,6 +2252,8 @@
         String variant = (String)fields.get("variant", "");
         String extStr = (String)fields.get("extensions", "");
         baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
+        // Android-changed: Handle null for backwards compatible deserialization. http://b/26387905
+        // was: if (extStr.length() > 0) {
         if (extStr != null && extStr.length() > 0) {
             try {
                 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
@@ -2177,7 +2274,7 @@
      * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
      * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
      * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
-     * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
+     * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
      * for more information.
      *
      * @return an instance of <code>Locale</code> equivalent to
@@ -2230,9 +2327,9 @@
         return extensions;
     }
 
-    /**
-     * @hide for internal use only.
-     */
+    // Android-removed: Drop nested private class LocaleNameGetter.
+    // Android-added BEGIN: Add adjustLanguageCode(); for internal use only.
+    /** @hide for internal use only. */
     public static String adjustLanguageCode(String languageCode) {
         String adjusted = languageCode.toLowerCase(Locale.US);
         // Map new language codes to the obsolete language
@@ -2247,6 +2344,7 @@
 
         return adjusted;
     }
+    // Android-added END
 
     /**
      * Enum for locale categories.  These locale categories are used to get/set
@@ -2584,9 +2682,11 @@
          * @see #setExtension(char, String)
          */
         public Builder removeUnicodeLocaleAttribute(String attribute) {
+            // Android-added BEGIN
             if (attribute == null) {
                 throw new NullPointerException("attribute == null");
             }
+            // Android-added END
 
             try {
                 localeBuilder.removeUnicodeLocaleAttribute(attribute);
diff --git a/ojluni/src/main/java/java/util/MissingFormatWidthException.java b/ojluni/src/main/java/java/util/MissingFormatWidthException.java
index af76ac5..9650fe2 100644
--- a/ojluni/src/main/java/java/util/MissingFormatWidthException.java
+++ b/ojluni/src/main/java/java/util/MissingFormatWidthException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when the format width is required.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to anyg
+ * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/NoSuchElementException.java b/ojluni/src/main/java/java/util/NoSuchElementException.java
index 88ff2c0..15e1aad 100644
--- a/ojluni/src/main/java/java/util/NoSuchElementException.java
+++ b/ojluni/src/main/java/java/util/NoSuchElementException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,13 +26,12 @@
 package java.util;
 
 /**
- * Thrown by the <code>nextElement</code> method of an
- * <code>Enumeration</code> to indicate that there are no more
- * elements in the enumeration.
+ * Thrown by various accessor methods to indicate that the element being requested
+ * does not exist.
  *
  * @author  unascribed
- * @see     java.util.Enumeration
  * @see     java.util.Enumeration#nextElement()
+ * @see     java.util.Iterator#next()
  * @since   JDK1.0
  */
 public
diff --git a/ojluni/src/main/java/java/util/Properties.java b/ojluni/src/main/java/java/util/Properties.java
index 7c3f0bb..fe61f98 100644
--- a/ojluni/src/main/java/java/util/Properties.java
+++ b/ojluni/src/main/java/java/util/Properties.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,8 +37,8 @@
 import java.io.BufferedWriter;
 
 /**
- * The <code>Properties</code> class represents a persistent set of
- * properties. The <code>Properties</code> can be saved to a stream
+ * The {@code Properties} class represents a persistent set of
+ * properties. The {@code Properties} can be saved to a stream
  * or loaded from a stream. Each key and its corresponding value in
  * the property list is a string.
  * <p>
@@ -46,17 +46,17 @@
  * "defaults"; this second property list is searched if
  * the property key is not found in the original property list.
  * <p>
- * Because <code>Properties</code> inherits from <code>Hashtable</code>, the
- * <code>put</code> and <code>putAll</code> methods can be applied to a
- * <code>Properties</code> object.  Their use is strongly discouraged as they
+ * Because {@code Properties} inherits from {@code Hashtable}, the
+ * {@code put} and {@code putAll} methods can be applied to a
+ * {@code Properties} object.  Their use is strongly discouraged as they
  * allow the caller to insert entries whose keys or values are not
- * <code>Strings</code>.  The <code>setProperty</code> method should be used
- * instead.  If the <code>store</code> or <code>save</code> method is called
- * on a "compromised" <code>Properties</code> object that contains a
- * non-<code>String</code> key or value, the call will fail. Similarly,
- * the call to the <code>propertyNames</code> or <code>list</code> method
- * will fail if it is called on a "compromised" <code>Properties</code>
- * object that contains a non-<code>String</code> key.
+ * {@code Strings}.  The {@code setProperty} method should be used
+ * instead.  If the {@code store} or {@code save} method is called
+ * on a "compromised" {@code Properties} object that contains a
+ * non-{@code String} key or value, the call will fail. Similarly,
+ * the call to the {@code propertyNames} or {@code list} method
+ * will fail if it is called on a "compromised" {@code Properties}
+ * object that contains a non-{@code String} key.
  *
  * <p>
  * The {@link #load(java.io.Reader) load(Reader)} <tt>/</tt>
@@ -78,8 +78,9 @@
  * <p> The {@link #loadFromXML(InputStream)} and {@link
  * #storeToXML(OutputStream, String, String)} methods load and store properties
  * in a simple XML format.  By default the UTF-8 character encoding is used,
- * however a specific encoding may be specified if required.  An XML properties
- * document has the following DOCTYPE declaration:
+ * however a specific encoding may be specified if required. Implementations
+ * are required to support UTF-8 and UTF-16 and may support other encodings.
+ * An XML properties document has the following DOCTYPE declaration:
  *
  * <pre>
  * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
@@ -146,15 +147,15 @@
     }
 
     /**
-     * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for
+     * Calls the <tt>Hashtable</tt> method {@code put}. Provided for
      * parallelism with the <tt>getProperty</tt> method. Enforces use of
      * strings for property keys and values. The value returned is the
-     * result of the <tt>Hashtable</tt> call to <code>put</code>.
+     * result of the <tt>Hashtable</tt> call to {@code put}.
      *
      * @param key the key to be placed into this property list.
      * @param value the value corresponding to <tt>key</tt>.
      * @return     the previous value of the specified key in this property
-     *             list, or <code>null</code> if it did not have one.
+     *             list, or {@code null} if it did not have one.
      * @see #getProperty
      * @since    1.2
      */
@@ -171,13 +172,13 @@
      * kinds of line, <i>natural lines</i> and <i>logical lines</i>.
      * A natural line is defined as a line of
      * characters that is terminated either by a set of line terminator
-     * characters (<code>\n</code> or <code>\r</code> or <code>\r\n</code>)
+     * characters ({@code \n} or {@code \r} or {@code \r\n})
      * or by the end of the stream. A natural line may be either a blank line,
      * a comment line, or hold all or some of a key-element pair. A logical
      * line holds all the data of a key-element pair, which may be spread
      * out across several adjacent natural lines by escaping
      * the line terminator sequence with a backslash character
-     * <code>\</code>.  Note that a comment line cannot be extended
+     * {@code \}.  Note that a comment line cannot be extended
      * in this manner; every natural line that is a comment must have
      * its own comment indicator, as described below. Lines are read from
      * input until the end of the stream is reached.
@@ -185,13 +186,13 @@
      * <p>
      * A natural line that contains only white space characters is
      * considered blank and is ignored.  A comment line has an ASCII
-     * <code>'#'</code> or <code>'!'</code> as its first non-white
+     * {@code '#'} or {@code '!'} as its first non-white
      * space character; comment lines are also ignored and do not
      * encode key-element information.  In addition to line
      * terminators, this format considers the characters space
-     * (<code>' '</code>, <code>'&#92;u0020'</code>), tab
-     * (<code>'\t'</code>, <code>'&#92;u0009'</code>), and form feed
-     * (<code>'\f'</code>, <code>'&#92;u000C'</code>) to be white
+     * ({@code ' '}, {@code '\u005Cu0020'}), tab
+     * ({@code '\t'}, {@code '\u005Cu0009'}), and form feed
+     * ({@code '\f'}, {@code '\u005Cu000C'}) to be white
      * space.
      *
      * <p>
@@ -215,32 +216,31 @@
      * <p>
      * The key contains all of the characters in the line starting
      * with the first non-white space character and up to, but not
-     * including, the first unescaped <code>'='</code>,
-     * <code>':'</code>, or white space character other than a line
+     * including, the first unescaped {@code '='},
+     * {@code ':'}, or white space character other than a line
      * terminator. All of these key termination characters may be
      * included in the key by escaping them with a preceding backslash
      * character; for example,<p>
      *
-     * <code>\:\=</code><p>
+     * {@code \:\=}<p>
      *
-     * would be the two-character key <code>":="</code>.  Line
-     * terminator characters can be included using <code>\r</code> and
-     * <code>\n</code> escape sequences.  Any white space after the
+     * would be the two-character key {@code ":="}.  Line
+     * terminator characters can be included using {@code \r} and
+     * {@code \n} escape sequences.  Any white space after the
      * key is skipped; if the first non-white space character after
-     * the key is <code>'='</code> or <code>':'</code>, then it is
+     * the key is {@code '='} or {@code ':'}, then it is
      * ignored and any white space characters after it are also
      * skipped.  All remaining characters on the line become part of
      * the associated element string; if there are no remaining
      * characters, the element is the empty string
-     * <code>&quot;&quot;</code>.  Once the raw character sequences
+     * {@code ""}.  Once the raw character sequences
      * constituting the key and element are identified, escape
      * processing is performed as described above.
      *
      * <p>
      * As an example, each of the following three lines specifies the key
-     * <code>"Truth"</code> and the associated element value
-     * <code>"Beauty"</code>:
-     * <p>
+     * {@code "Truth"} and the associated element value
+     * {@code "Beauty"}:
      * <pre>
      * Truth = Beauty
      *  Truth:Beauty
@@ -248,29 +248,25 @@
      * </pre>
      * As another example, the following three lines specify a single
      * property:
-     * <p>
      * <pre>
      * fruits                           apple, banana, pear, \
      *                                  cantaloupe, watermelon, \
      *                                  kiwi, mango
      * </pre>
-     * The key is <code>"fruits"</code> and the associated element is:
-     * <p>
+     * The key is {@code "fruits"} and the associated element is:
      * <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre>
-     * Note that a space appears before each <code>\</code> so that a space
-     * will appear after each comma in the final result; the <code>\</code>,
+     * Note that a space appears before each {@code \} so that a space
+     * will appear after each comma in the final result; the {@code \},
      * line terminator, and leading white space on the continuation line are
      * merely discarded and are <i>not</i> replaced by one or more other
      * characters.
      * <p>
      * As a third example, the line:
-     * <p>
      * <pre>cheeses
      * </pre>
-     * specifies that the key is <code>"cheeses"</code> and the associated
-     * element is the empty string <code>""</code>.<p>
+     * specifies that the key is {@code "cheeses"} and the associated
+     * element is the empty string {@code ""}.
      * <p>
-     *
      * <a name="unicodeescapes"></a>
      * Characters in keys and elements can be represented in escape
      * sequences similar to those used for character and string literals
@@ -283,24 +279,24 @@
      * <ul>
      * <li> Octal escapes are not recognized.
      *
-     * <li> The character sequence <code>\b</code> does <i>not</i>
+     * <li> The character sequence {@code \b} does <i>not</i>
      * represent a backspace character.
      *
      * <li> The method does not treat a backslash character,
-     * <code>\</code>, before a non-valid escape character as an
+     * {@code \}, before a non-valid escape character as an
      * error; the backslash is silently dropped.  For example, in a
-     * Java string the sequence <code>"\z"</code> would cause a
+     * Java string the sequence {@code "\z"} would cause a
      * compile time error.  In contrast, this method silently drops
      * the backslash.  Therefore, this method treats the two character
-     * sequence <code>"\b"</code> as equivalent to the single
-     * character <code>'b'</code>.
+     * sequence {@code "\b"} as equivalent to the single
+     * character {@code 'b'}.
      *
      * <li> Escapes are not necessary for single and double quotes;
      * however, by the rule above, single and double quote characters
      * preceded by a backslash still yield single and double quote
      * characters, respectively.
      *
-     * <li> Only a single 'u' character is allowed in a Uniocde escape
+     * <li> Only a single 'u' character is allowed in a Unicode escape
      * sequence.
      *
      * </ul>
@@ -366,7 +362,9 @@
                     valueStart = keyLen + 1;
                     hasSep = true;
                     break;
-                } else if (Character.isWhitespace(c) && !precedingBackslash) {
+                }
+                // Android-changed: use of Character.isWhitespace(c) b/25998006
+                else if (Character.isWhitespace(c) && !precedingBackslash) {
                     valueStart = keyLen + 1;
                     break;
                 }
@@ -379,6 +377,7 @@
             }
             while (valueStart < limit) {
                 c = lr.lineBuf[valueStart];
+                // Android-changed: use of Character.isWhitespace(c) b/25998006
                 if (!Character.isWhitespace(c)) {
                     if (!hasSep && (c == '=' ||  c == ':')) {
                         hasSep = true;
@@ -439,6 +438,9 @@
                         if (len == 0 || isCommentLine) {
                             return -1;
                         }
+                        if (precedingBackslash) {
+                            len--;
+                        }
                         return len;
                     }
                 }
@@ -456,6 +458,7 @@
                     }
                 }
                 if (skipWhiteSpace) {
+                    // Android-changed: use of Character.isWhitespace(c) b/25998006
                     if (Character.isWhitespace(c)) {
                         continue;
                     }
@@ -506,6 +509,9 @@
                                   :inStream.read(inByteBuf);
                         inOff = 0;
                         if (inLimit <= 0) {
+                            if (precedingBackslash) {
+                                len--;
+                            }
                             return len;
                         }
                     }
@@ -689,20 +695,20 @@
     }
 
     /**
-     * Calls the <code>store(OutputStream out, String comments)</code> method
+     * Calls the {@code store(OutputStream out, String comments)} method
      * and suppresses IOExceptions that were thrown.
      *
      * @deprecated This method does not throw an IOException if an I/O error
      * occurs while saving the property list.  The preferred way to save a
-     * properties list is via the <code>store(OutputStream out,
-     * String comments)</code> method or the
-     * <code>storeToXML(OutputStream os, String comment)</code> method.
+     * properties list is via the {@code store(OutputStream out,
+     * String comments)} method or the
+     * {@code storeToXML(OutputStream os, String comment)} method.
      *
      * @param   out      an output stream.
      * @param   comments   a description of the property list.
-     * @exception  ClassCastException  if this <code>Properties</code> object
+     * @exception  ClassCastException  if this {@code Properties} object
      *             contains any keys or values that are not
-     *             <code>Strings</code>.
+     *             {@code Strings}.
      */
     @Deprecated
     public void save(OutputStream out, String comments)  {
@@ -714,37 +720,37 @@
 
     /**
      * Writes this property list (key and element pairs) in this
-     * <code>Properties</code> table to the output character stream in a
+     * {@code Properties} table to the output character stream in a
      * format suitable for using the {@link #load(java.io.Reader) load(Reader)}
      * method.
      * <p>
-     * Properties from the defaults table of this <code>Properties</code>
+     * Properties from the defaults table of this {@code Properties}
      * table (if any) are <i>not</i> written out by this method.
      * <p>
-     * If the comments argument is not null, then an ASCII <code>#</code>
+     * If the comments argument is not null, then an ASCII {@code #}
      * character, the comments string, and a line separator are first written
-     * to the output stream. Thus, the <code>comments</code> can serve as an
+     * to the output stream. Thus, the {@code comments} can serve as an
      * identifying comment. Any one of a line feed ('\n'), a carriage
      * return ('\r'), or a carriage return followed immediately by a line feed
-     * in comments is replaced by a line separator generated by the <code>Writer</code>
-     * and if the next character in comments is not character <code>#</code> or
-     * character <code>!</code> then an ASCII <code>#</code> is written out
+     * in comments is replaced by a line separator generated by the {@code Writer}
+     * and if the next character in comments is not character {@code #} or
+     * character {@code !} then an ASCII {@code #} is written out
      * after that line separator.
      * <p>
      * Next, a comment line is always written, consisting of an ASCII
-     * <code>#</code> character, the current date and time (as if produced
-     * by the <code>toString</code> method of <code>Date</code> for the
-     * current time), and a line separator as generated by the <code>Writer</code>.
+     * {@code #} character, the current date and time (as if produced
+     * by the {@code toString} method of {@code Date} for the
+     * current time), and a line separator as generated by the {@code Writer}.
      * <p>
-     * Then every entry in this <code>Properties</code> table is
+     * Then every entry in this {@code Properties} table is
      * written out, one per line. For each entry the key string is
-     * written, then an ASCII <code>=</code>, then the associated
+     * written, then an ASCII {@code =}, then the associated
      * element string. For the key, all space characters are
-     * written with a preceding <code>\</code> character.  For the
+     * written with a preceding {@code \} character.  For the
      * element, leading space characters, but not embedded or trailing
-     * space characters, are written with a preceding <code>\</code>
-     * character. The key and element characters <code>#</code>,
-     * <code>!</code>, <code>=</code>, and <code>:</code> are written
+     * space characters, are written with a preceding {@code \}
+     * character. The key and element characters {@code #},
+     * {@code !}, {@code =}, and {@code :} are written
      * with a preceding backslash to ensure that they are properly loaded.
      * <p>
      * After the entries have been written, the output stream is flushed.
@@ -755,9 +761,9 @@
      * @param   comments   a description of the property list.
      * @exception  IOException if writing this property list to the specified
      *             output stream throws an <tt>IOException</tt>.
-     * @exception  ClassCastException  if this <code>Properties</code> object
-     *             contains any keys or values that are not <code>Strings</code>.
-     * @exception  NullPointerException  if <code>writer</code> is null.
+     * @exception  ClassCastException  if this {@code Properties} object
+     *             contains any keys or values that are not {@code Strings}.
+     * @exception  NullPointerException  if {@code writer} is null.
      * @since 1.6
      */
     public void store(Writer writer, String comments)
@@ -771,11 +777,11 @@
 
     /**
      * Writes this property list (key and element pairs) in this
-     * <code>Properties</code> table to the output stream in a format suitable
-     * for loading into a <code>Properties</code> table using the
+     * {@code Properties} table to the output stream in a format suitable
+     * for loading into a {@code Properties} table using the
      * {@link #load(InputStream) load(InputStream)} method.
      * <p>
-     * Properties from the defaults table of this <code>Properties</code>
+     * Properties from the defaults table of this {@code Properties}
      * table (if any) are <i>not</i> written out by this method.
      * <p>
      * This method outputs the comments, properties keys and values in
@@ -786,12 +792,12 @@
      * <li>The stream is written using the ISO 8859-1 character encoding.
      *
      * <li>Characters not in Latin-1 in the comments are written as
-     * <code>&#92;u</code><i>xxxx</i> for their appropriate unicode
+     * {@code \u005Cu}<i>xxxx</i> for their appropriate unicode
      * hexadecimal value <i>xxxx</i>.
      *
-     * <li>Characters less than <code>&#92;u0020</code> and characters greater
-     * than <code>&#92;u007E</code> in property keys or values are written
-     * as <code>&#92;u</code><i>xxxx</i> for the appropriate hexadecimal
+     * <li>Characters less than {@code \u005Cu0020} and characters greater
+     * than {@code \u005Cu007E} in property keys or values are written
+     * as {@code \u005Cu}<i>xxxx</i> for the appropriate hexadecimal
      * value <i>xxxx</i>.
      * </ul>
      * <p>
@@ -802,9 +808,9 @@
      * @param   comments   a description of the property list.
      * @exception  IOException if writing this property list to the specified
      *             output stream throws an <tt>IOException</tt>.
-     * @exception  ClassCastException  if this <code>Properties</code> object
-     *             contains any keys or values that are not <code>Strings</code>.
-     * @exception  NullPointerException  if <code>out</code> is null.
+     * @exception  ClassCastException  if this {@code Properties} object
+     *             contains any keys or values that are not {@code Strings}.
+     * @exception  NullPointerException  if {@code out} is null.
      * @since 1.2
      */
     public void store(OutputStream out, String comments)
@@ -824,7 +830,7 @@
         bw.write("#" + new Date().toString());
         bw.newLine();
         synchronized (this) {
-            for (Enumeration e = keys(); e.hasMoreElements();) {
+            for (Enumeration<?> e = keys(); e.hasMoreElements();) {
                 String key = (String)e.nextElement();
                 String val = (String)get(key);
                 key = saveConvert(key, true, escUnicode);
@@ -850,23 +856,36 @@
      * Furthermore, the document must satisfy the properties DTD described
      * above.
      *
+     * <p> An implementation is required to read XML documents that use the
+     * "{@code UTF-8}" or "{@code UTF-16}" encoding. An implementation may
+     * support additional encodings.
+     *
      * <p>The specified stream is closed after this method returns.
      *
      * @param in the input stream from which to read the XML document.
      * @throws IOException if reading from the specified input stream
      *         results in an <tt>IOException</tt>.
+     * @throws java.io.UnsupportedEncodingException if the document's encoding
+     *         declaration can be read and it specifies an encoding that is not
+     *         supported
      * @throws InvalidPropertiesFormatException Data on input stream does not
      *         constitute a valid XML document with the mandated document type.
-     * @throws NullPointerException if <code>in</code> is null.
+     * @throws NullPointerException if {@code in} is null.
      * @see    #storeToXML(OutputStream, String, String)
+     * @see    <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
+     *         Encoding in Entities</a>
      * @since 1.5
      */
     public synchronized void loadFromXML(InputStream in)
         throws IOException, InvalidPropertiesFormatException
     {
-        if (in == null)
-            throw new NullPointerException();
-        XMLUtils.load(this, in);
+        // Android-changed: Keep OpenJDK7u40's XmlUtils.
+        // XmlSupport's system property based XmlPropertiesProvider
+        // selection does not make sense on Android and has too many
+        // dependencies on classes that are not available on Android.
+        //
+        // XmlSupport.load(this, Objects.requireNonNull(in));
+        XMLUtils.load(this, Objects.requireNonNull(in));
         in.close();
     }
 
@@ -879,22 +898,20 @@
      * <tt>props.storeToXML(os, comment, "UTF-8");</tt>.
      *
      * @param os the output stream on which to emit the XML document.
-     * @param comment a description of the property list, or <code>null</code>
+     * @param comment a description of the property list, or {@code null}
      *        if no comment is desired.
      * @throws IOException if writing to the specified output stream
      *         results in an <tt>IOException</tt>.
-     * @throws NullPointerException if <code>os</code> is null.
-     * @throws ClassCastException  if this <code>Properties</code> object
+     * @throws NullPointerException if {@code os} is null.
+     * @throws ClassCastException  if this {@code Properties} object
      *         contains any keys or values that are not
-     *         <code>Strings</code>.
+     *         {@code Strings}.
      * @see    #loadFromXML(InputStream)
      * @since 1.5
      */
     public void storeToXML(OutputStream os, String comment)
         throws IOException
     {
-        if (os == null)
-            throw new NullPointerException();
         storeToXML(os, comment, "UTF-8");
     }
 
@@ -907,13 +924,17 @@
      * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
      * </pre>
      *
-     *<p>If the specified comment is <code>null</code> then no comment
+     * <p>If the specified comment is {@code null} then no comment
      * will be stored in the document.
      *
+     * <p> An implementation is required to support writing of XML documents
+     * that use the "{@code UTF-8}" or "{@code UTF-16}" encoding. An
+     * implementation may support additional encodings.
+     *
      * <p>The specified stream remains open after this method returns.
      *
      * @param os        the output stream on which to emit the XML document.
-     * @param comment   a description of the property list, or <code>null</code>
+     * @param comment   a description of the property list, or {@code null}
      *                  if no comment is desired.
      * @param  encoding the name of a supported
      *                  <a href="../lang/package-summary.html#charenc">
@@ -921,27 +942,37 @@
      *
      * @throws IOException if writing to the specified output stream
      *         results in an <tt>IOException</tt>.
-     * @throws NullPointerException if <code>os</code> is <code>null</code>,
-     *         or if <code>encoding</code> is <code>null</code>.
-     * @throws ClassCastException  if this <code>Properties</code> object
+     * @throws java.io.UnsupportedEncodingException if the encoding is not
+     *         supported by the implementation.
+     * @throws NullPointerException if {@code os} is {@code null},
+     *         or if {@code encoding} is {@code null}.
+     * @throws ClassCastException  if this {@code Properties} object
      *         contains any keys or values that are not
-     *         <code>Strings</code>.
+     *         {@code Strings}.
      * @see    #loadFromXML(InputStream)
+     * @see    <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
+     *         Encoding in Entities</a>
      * @since 1.5
      */
     public void storeToXML(OutputStream os, String comment, String encoding)
         throws IOException
     {
-        if (os == null)
-            throw new NullPointerException();
-        XMLUtils.save(this, os, comment, encoding);
+        // Android-changed: Keep OpenJDK7u40's XmlUtils.
+        // XmlSupport's system property based XmlPropertiesProvider
+        // selection does not make sense on Android and has too many
+        // dependencies on classes that are not available on Android.
+        //
+        // XmlSupport.save(this, Objects.requireNonNull(os), comment,
+        //                Objects.requireNonNull(encoding));
+        XMLUtils.save(this, Objects.requireNonNull(os), comment,
+                       Objects.requireNonNull(encoding));
     }
 
     /**
      * Searches for the property with the specified key in this property list.
      * If the key is not found in this property list, the default property list,
      * and its defaults, recursively, are then checked. The method returns
-     * <code>null</code> if the property is not found.
+     * {@code null} if the property is not found.
      *
      * @param   key   the property key.
      * @return  the value in this property list with the specified key value.
@@ -987,7 +1018,7 @@
      * @see     #stringPropertyNames
      */
     public Enumeration<?> propertyNames() {
-        Hashtable h = new Hashtable();
+        Hashtable<String,Object> h = new Hashtable<>();
         enumerate(h);
         return h.keys();
     }
@@ -1026,10 +1057,10 @@
      */
     public void list(PrintStream out) {
         out.println("-- listing properties --");
-        Hashtable h = new Hashtable();
+        Hashtable<String,Object> h = new Hashtable<>();
         enumerate(h);
-        for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
-            String key = (String)e.nextElement();
+        for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) {
+            String key = e.nextElement();
             String val = (String)h.get(key);
             if (val.length() > 40) {
                 val = val.substring(0, 37) + "...";
@@ -1054,10 +1085,10 @@
      */
     public void list(PrintWriter out) {
         out.println("-- listing properties --");
-        Hashtable h = new Hashtable();
+        Hashtable<String,Object> h = new Hashtable<>();
         enumerate(h);
-        for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
-            String key = (String)e.nextElement();
+        for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) {
+            String key = e.nextElement();
             String val = (String)h.get(key);
             if (val.length() > 40) {
                 val = val.substring(0, 37) + "...";
@@ -1072,11 +1103,11 @@
      * @throws ClassCastException if any of the property keys
      *         is not of String type.
      */
-    private synchronized void enumerate(Hashtable h) {
+    private synchronized void enumerate(Hashtable<String,Object> h) {
         if (defaults != null) {
             defaults.enumerate(h);
         }
-        for (Enumeration e = keys() ; e.hasMoreElements() ;) {
+        for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
             String key = (String)e.nextElement();
             h.put(key, get(key));
         }
@@ -1091,7 +1122,7 @@
         if (defaults != null) {
             defaults.enumerateStringProperties(h);
         }
-        for (Enumeration e = keys() ; e.hasMoreElements() ;) {
+        for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
             Object k = e.nextElement();
             Object v = get(k);
             if (k instanceof String && v instanceof String) {
diff --git a/ojluni/src/main/java/java/util/PropertyResourceBundle.java b/ojluni/src/main/java/java/util/PropertyResourceBundle.java
index c7fe3b4..23c3ffe 100644
--- a/ojluni/src/main/java/java/util/PropertyResourceBundle.java
+++ b/ojluni/src/main/java/java/util/PropertyResourceBundle.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -100,6 +100,11 @@
  * </blockquote>
  *
  * <p>
+ * The implementation of a {@code PropertyResourceBundle} subclass must be
+ * thread-safe if it's simultaneously used by multiple threads. The default
+ * implementations of the non-abstract methods in this class are thread-safe.
+ *
+ * <p>
  * <strong>Note:</strong> PropertyResourceBundle can be constructed either
  * from an InputStream or a Reader, which represents a property file.
  * Constructing a PropertyResourceBundle instance from an InputStream requires
@@ -124,7 +129,10 @@
      *        to read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>stream</code> is null
+     * @throws IllegalArgumentException if {@code stream} contains a
+     *     malformed Unicode escape sequence.
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public PropertyResourceBundle (InputStream stream) throws IOException {
         Properties properties = new Properties();
         properties.load(stream);
@@ -141,8 +149,11 @@
      *        read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>reader</code> is null
+     * @throws IllegalArgumentException if a malformed Unicode escape sequence appears
+     *     from {@code reader}.
      * @since 1.6
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public PropertyResourceBundle (Reader reader) throws IOException {
         Properties properties = new Properties();
         properties.load(reader);
@@ -186,5 +197,8 @@
 
     // ==================privates====================
 
-    private Map<String,Object> lookup;
+    // Android-changed: Fix unsafe publication http://b/31467561
+    // Fixed in OpenJDK 9: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/29ecac30ecae
+    // was: private Map<String,Object> lookup;
+    private final Map<String,Object> lookup;
 }
diff --git a/ojluni/src/main/java/java/util/Random.java b/ojluni/src/main/java/java/util/Random.java
index fb4ecfd..1061b59 100644
--- a/ojluni/src/main/java/java/util/Random.java
+++ b/ojluni/src/main/java/java/util/Random.java
@@ -312,9 +312,8 @@
      * Returns the next pseudorandom, uniformly distributed {@code int}
      * value from this random number generator's sequence. The general
      * contract of {@code nextInt} is that one {@code int} value is
-     * pseudorandomly generated and returned. All 2<font size="-1"><sup>32
-     * </sup></font> possible {@code int} values are produced with
-     * (approximately) equal probability.
+     * pseudorandomly generated and returned. All 2<sup>32</sup> possible
+     * {@code int} values are produced with (approximately) equal probability.
      *
      * <p>The method {@code nextInt} is implemented by class {@code Random}
      * as if by:
@@ -335,23 +334,23 @@
      * between 0 (inclusive) and the specified value (exclusive), drawn from
      * this random number generator's sequence.  The general contract of
      * {@code nextInt} is that one {@code int} value in the specified range
-     * is pseudorandomly generated and returned.  All {@code n} possible
+     * is pseudorandomly generated and returned.  All {@code bound} possible
      * {@code int} values are produced with (approximately) equal
-     * probability.  The method {@code nextInt(int n)} is implemented by
+     * probability.  The method {@code nextInt(int bound)} is implemented by
      * class {@code Random} as if by:
      *  <pre> {@code
-     * public int nextInt(int n) {
-     *   if (n <= 0)
-     *     throw new IllegalArgumentException("n must be positive");
+     * public int nextInt(int bound) {
+     *   if (bound <= 0)
+     *     throw new IllegalArgumentException("bound must be positive");
      *
-     *   if ((n & -n) == n)  // i.e., n is a power of 2
-     *     return (int)((n * (long)next(31)) >> 31);
+     *   if ((bound & -bound) == bound)  // i.e., bound is a power of 2
+     *     return (int)((bound * (long)next(31)) >> 31);
      *
      *   int bits, val;
      *   do {
      *       bits = next(31);
-     *       val = bits % n;
-     *   } while (bits - val + (n-1) < 0);
+     *       val = bits % bound;
+     *   } while (bits - val + (bound-1) < 0);
      *   return val;
      * }}</pre>
      *
@@ -377,28 +376,28 @@
      * greatly increases the length of the sequence of values returned by
      * successive calls to this method if n is a small power of two.
      *
-     * @param n the bound on the random number to be returned.  Must be
-     *        positive.
+     * @param bound the upper bound (exclusive).  Must be positive.
      * @return the next pseudorandom, uniformly distributed {@code int}
-     *         value between {@code 0} (inclusive) and {@code n} (exclusive)
+     *         value between zero (inclusive) and {@code bound} (exclusive)
      *         from this random number generator's sequence
-     * @throws IllegalArgumentException if n is not positive
+     * @throws IllegalArgumentException if bound is not positive
      * @since 1.2
      */
+    public int nextInt(int bound) {
+        if (bound <= 0)
+            throw new IllegalArgumentException(BadBound);
 
-    public int nextInt(int n) {
-        if (n <= 0)
-            throw new IllegalArgumentException("n must be positive");
-
-        if ((n & -n) == n)  // i.e., n is a power of 2
-            return (int)((n * (long)next(31)) >> 31);
-
-        int bits, val;
-        do {
-            bits = next(31);
-            val = bits % n;
-        } while (bits - val + (n-1) < 0);
-        return val;
+        int r = next(31);
+        int m = bound - 1;
+        if ((bound & m) == 0)  // i.e., bound is a power of 2
+            r = (int)((bound * (long)r) >> 31);
+        else {
+            for (int u = r;
+                 u - (r = u % bound) + m < 0;
+                 u = next(31))
+                ;
+        }
+        return r;
     }
 
     /**
@@ -457,11 +456,9 @@
      * <p>The general contract of {@code nextFloat} is that one
      * {@code float} value, chosen (approximately) uniformly from the
      * range {@code 0.0f} (inclusive) to {@code 1.0f} (exclusive), is
-     * pseudorandomly generated and returned. All 2<font
-     * size="-1"><sup>24</sup></font> possible {@code float} values
-     * of the form <i>m&nbsp;x&nbsp</i>2<font
-     * size="-1"><sup>-24</sup></font>, where <i>m</i> is a positive
-     * integer less than 2<font size="-1"><sup>24</sup> </font>, are
+     * pseudorandomly generated and returned. All 2<sup>24</sup> possible
+     * {@code float} values of the form <i>m&nbsp;x&nbsp;</i>2<sup>-24</sup>,
+     * where <i>m</i> is a positive integer less than 2<sup>24</sup>, are
      * produced with (approximately) equal probability.
      *
      * <p>The method {@code nextFloat} is implemented by class {@code Random}
@@ -532,8 +529,7 @@
      * @see Math#random
      */
     public double nextDouble() {
-        return (((long)(next(26)) << 27) + next(27))
-            / (double)(1L << 53);
+        return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
     }
 
     private double nextNextGaussian;
diff --git a/ojluni/src/main/java/java/util/ResourceBundle.java b/ojluni/src/main/java/java/util/ResourceBundle.java
index f604089..bf73b03 100644
--- a/ojluni/src/main/java/java/util/ResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ResourceBundle.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
@@ -41,7 +41,6 @@
 
 package java.util;
 
-import dalvik.system.VMStack;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -59,7 +58,9 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.jar.JarEntry;
+import java.util.spi.ResourceBundleControlProvider;
 
+import dalvik.system.VMStack;
 import sun.reflect.CallerSensitive;
 import sun.util.locale.BaseLocale;
 import sun.util.locale.LocaleObjectCache;
@@ -76,7 +77,7 @@
  *
  * <p>
  * This allows you to write programs that can:
- * <UL type=SQUARE>
+ * <UL>
  * <LI> be easily localized, or translated, into different languages
  * <LI> handle multiple locales at once
  * <LI> be easily modified later to support even more locales
@@ -186,7 +187,14 @@
  * subclass.  Your subclasses must override two methods: <code>handleGetObject</code>
  * and <code>getKeys()</code>.
  *
- * <h4>ResourceBundle.Control</h4>
+ * <p>
+ * The implementation of a {@code ResourceBundle} subclass must be thread-safe
+ * if it's simultaneously used by multiple threads. The default implementations
+ * of the non-abstract methods in this class, and the methods in the direct
+ * known concrete subclasses {@code ListResourceBundle} and
+ * {@code PropertyResourceBundle} are thread-safe.
+ *
+ * <h3>ResourceBundle.Control</h3>
  *
  * The {@link ResourceBundle.Control} class provides information necessary
  * to perform the bundle loading process by the <code>getBundle</code>
@@ -197,7 +205,18 @@
  * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
  * factory method for details.
  *
- * <h4>Cache Management</h4>
+ * <p><a name="modify_default_behavior">For the {@code getBundle} factory</a>
+ * methods that take no {@link Control} instance, their <a
+ * href="#default_behavior"> default behavior</a> of resource bundle loading
+ * can be modified with <em>installed</em> {@link
+ * ResourceBundleControlProvider} implementations. Any installed providers are
+ * detected at the {@code ResourceBundle} class loading time. If any of the
+ * providers provides a {@link Control} for the given base name, that {@link
+ * Control} will be used instead of the default {@link Control}. If there is
+ * more than one service provider installed for supporting the same base name,
+ * the first one returned from {@link ServiceLoader} will be used.
+ *
+ * <h3>Cache Management</h3>
  *
  * Resource bundle instances created by the <code>getBundle</code> factory
  * methods are cached by default, and the factory methods return the same
@@ -213,7 +232,7 @@
  * Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
  * long) ResourceBundle.Control.needsReload} for details.
  *
- * <h4>Example</h4>
+ * <h3>Example</h3>
  *
  * The following is a very simple example of a <code>ResourceBundle</code>
  * subclass, <code>MyResources</code>, that manages two resources (for a larger number of
@@ -299,7 +318,25 @@
     /**
      * Queue for reference objects referring to class loaders or bundles.
      */
-    private static final ReferenceQueue referenceQueue = new ReferenceQueue();
+    private static final ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
+
+    /**
+     * Returns the base name of this bundle, if known, or {@code null} if unknown.
+     *
+     * If not null, then this is the value of the {@code baseName} parameter
+     * that was passed to the {@code ResourceBundle.getBundle(...)} method
+     * when the resource bundle was loaded.
+     *
+     * @return The base name of the resource bundle, as provided to and expected
+     * by the {@code ResourceBundle.getBundle(...)} methods.
+     *
+     * @see #getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+     *
+     * @since 1.8
+     */
+    public String getBaseBundleName() {
+        return name;
+    }
 
     /**
      * The parent bundle of this bundle.
@@ -334,6 +371,21 @@
      */
     private volatile Set<String> keySet;
 
+    private static final List<ResourceBundleControlProvider> providers;
+
+    static {
+        List<ResourceBundleControlProvider> list = null;
+        ServiceLoader<ResourceBundleControlProvider> serviceLoaders
+                = ServiceLoader.loadInstalled(ResourceBundleControlProvider.class);
+        for (ResourceBundleControlProvider provider : serviceLoaders) {
+            if (list == null) {
+                list = new ArrayList<>();
+            }
+            list.add(provider);
+        }
+        providers = list;
+    }
+
     /**
      * Sole constructor.  (For invocation by subclass constructors, typically
      * implicit.)
@@ -394,12 +446,13 @@
             if (parent != null) {
                 obj = parent.getObject(key);
             }
-            if (obj == null)
+            if (obj == null) {
                 throw new MissingResourceException("Can't find resource for bundle "
                                                    +this.getClass().getName()
                                                    +", key "+key,
                                                    this.getClass().getName(),
                                                    key);
+            }
         }
         return obj;
     }
@@ -420,6 +473,10 @@
      * resources on behalf of the client.
      */
     private static ClassLoader getLoader(ClassLoader cl) {
+        // Android-changed: On Android, this method takes a ClassLoader argument:
+        // Callers call {@code getLoader(VMStack.getCallingClassLoader())}
+        // instead of {@code getLoader(Reflection.getCallerClass())}.
+        // ClassLoader cl = caller == null ? null : caller.getClassLoader();
         if (cl == null) {
             // When the caller's loader is the boot class loader, cl is null
             // here. In that case, ClassLoader.getSystemClassLoader() may
@@ -486,7 +543,7 @@
      * null, but the base name and the locale must have a non-null
      * value.
      */
-    private static final class CacheKey implements Cloneable {
+    private static class CacheKey implements Cloneable {
         // These three are the actual keys for lookup in Map.
         private String name;
         private Locale locale;
@@ -581,8 +638,7 @@
                         // treat it as unequal
                         && (loader != null)
                         && (loader == otherEntry.loaderRef.get());
-            } catch (NullPointerException e) {
-            } catch (ClassCastException e) {
+            } catch (    NullPointerException | ClassCastException e) {
             }
             return false;
         }
@@ -612,7 +668,7 @@
                 return clone;
             } catch (CloneNotSupportedException e) {
                 //this should never happen
-                throw new InternalError();
+                throw new InternalError(e);
             }
         }
 
@@ -667,11 +723,11 @@
      * garbage collected when nobody else is using them. The ResourceBundle
      * class has no reason to keep class loaders alive.
      */
-    private static final class LoaderReference extends WeakReference<ClassLoader>
-                                               implements CacheKeyReference {
+    private static class LoaderReference extends WeakReference<ClassLoader>
+                                         implements CacheKeyReference {
         private CacheKey cacheKey;
 
-        LoaderReference(ClassLoader referent, ReferenceQueue q, CacheKey key) {
+        LoaderReference(ClassLoader referent, ReferenceQueue<Object> q, CacheKey key) {
             super(referent, q);
             cacheKey = key;
         }
@@ -685,11 +741,11 @@
      * References to bundles are soft references so that they can be garbage
      * collected when they have no hard references.
      */
-    private static final class BundleReference extends SoftReference<ResourceBundle>
-                                               implements CacheKeyReference {
+    private static class BundleReference extends SoftReference<ResourceBundle>
+                                         implements CacheKeyReference {
         private CacheKey cacheKey;
 
-        BundleReference(ResourceBundle referent, ReferenceQueue q, CacheKey key) {
+        BundleReference(ResourceBundle referent, ReferenceQueue<Object> q, CacheKey key) {
             super(referent, q);
             cacheKey = key;
         }
@@ -721,9 +777,10 @@
     public static final ResourceBundle getBundle(String baseName)
     {
         return getBundleImpl(baseName, Locale.getDefault(),
-                             /* must determine loader here, else we break stack invariant */
+                             // Android-changed: use of VMStack.getCallingClassLoader()
                              getLoader(VMStack.getCallingClassLoader()),
-                             Control.INSTANCE);
+                             // getLoader(Reflection.getCallerClass()),
+                             getDefaultControl(baseName));
     }
 
     /**
@@ -764,8 +821,9 @@
     public static final ResourceBundle getBundle(String baseName,
                                                  Control control) {
         return getBundleImpl(baseName, Locale.getDefault(),
-                             /* must determine loader here, else we break stack invariant */
+                             // Android-changed: use of VMStack.getCallingClassLoader()
                              getLoader(VMStack.getCallingClassLoader()),
+                             // getLoader(Reflection.getCallerClass()),
                              control);
     }
 
@@ -795,9 +853,10 @@
                                                  Locale locale)
     {
         return getBundleImpl(baseName, locale,
-                             /* must determine loader here, else we break stack invariant */
+                             // Android-changed: use of VMStack.getCallingClassLoader()
                              getLoader(VMStack.getCallingClassLoader()),
-                             Control.INSTANCE);
+                             // getLoader(Reflection.getCallerClass()),
+                             getDefaultControl(baseName));
     }
 
     /**
@@ -841,8 +900,9 @@
     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
                                                  Control control) {
         return getBundleImpl(baseName, targetLocale,
-                             /* must determine loader here, else we break stack invariant */
+                             // Android-changed: use of VMStack.getCallingClassLoader()
                              getLoader(VMStack.getCallingClassLoader()),
+                             // getLoader(Reflection.getCallerClass()),
                              control);
     }
 
@@ -850,9 +910,15 @@
      * Gets a resource bundle using the specified base name, locale, and class
      * loader.
      *
-     * <p><a name="default_behavior"></a>This method behaves the same as calling
+     * <p>This method behaves the same as calling
      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
-     * default instance of {@link Control}. The following describes this behavior.
+     * default instance of {@link Control} unless another {@link Control} is
+     * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
+     * description of <a href="#modify_default_behavior">modifying the default
+     * behavior</a>.
+     *
+     * <p><a name="default_behavior">The following describes the default
+     * behavior</a>.
      *
      * <p><code>getBundle</code> uses the base name, the specified locale, and
      * the default locale (obtained from {@link java.util.Locale#getDefault()
@@ -947,8 +1013,8 @@
      * <p>If still no result bundle is found, the base name alone is looked up. If
      * this still fails, a <code>MissingResourceException</code> is thrown.
      *
-     * <p><a name="parent_chain"></a> Once a result resource bundle has been found,
-     * its <em>parent chain</em> is instantiated.  If the result bundle already
+     * <p><a name="parent_chain"> Once a result resource bundle has been found,
+     * its <em>parent chain</em> is instantiated</a>.  If the result bundle already
      * has a parent (perhaps because it was returned from a cache) the chain is
      * complete.
      *
@@ -977,8 +1043,8 @@
      * path name (using "/") instead of a fully qualified class name (using
      * ".").
      *
-     * <p><a name="default_behavior_example"></a>
-     * <strong>Example:</strong>
+     * <p><a name="default_behavior_example">
+     * <strong>Example:</strong></a>
      * <p>
      * The following class and property files are provided:
      * <pre>
@@ -999,7 +1065,7 @@
      * <p>Calling <code>getBundle</code> with the locale arguments below will
      * instantiate resource bundles as follows:
      *
-     * <table>
+     * <table summary="getBundle() locale to resource bundle mapping">
      * <tr><td>Locale("fr", "CH")</td><td>MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class</td></tr>
      * <tr><td>Locale("fr", "FR")</td><td>MyResources_fr.properties, parent MyResources.class</td></tr>
      * <tr><td>Locale("de", "DE")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
@@ -1027,7 +1093,7 @@
         if (loader == null) {
             throw new NullPointerException();
         }
-        return getBundleImpl(baseName, locale, loader, Control.INSTANCE);
+        return getBundleImpl(baseName, locale, loader, getDefaultControl(baseName));
     }
 
     /**
@@ -1039,7 +1105,6 @@
      * bundles. Conceptually, the bundle loading process with the given
      * <code>control</code> is performed in the following steps.
      *
-     * <p>
      * <ol>
      * <li>This factory method looks up the resource bundle in the cache for
      * the specified <code>baseName</code>, <code>targetLocale</code> and
@@ -1079,45 +1144,45 @@
      * <code>control.newBundle</code>.
      *
      * <table style="width: 50%; text-align: left; margin-left: 40px;"
-     *  border="0" cellpadding="2" cellspacing="2">
-     * <tbody><code>
+     *  border="0" cellpadding="2" cellspacing="2" summary="locale-format combinations for newBundle">
+     * <tbody>
      * <tr>
      * <td
-     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;">Locale<br>
+     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;"><code>Locale</code><br>
      * </td>
      * <td
-     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;">format<br>
+     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;"><code>format</code><br>
      * </td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("de", "DE")<br>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("de", "DE")</code><br>
      * </td>
-     * <td style="vertical-align: top; width: 50%;">java.class<br>
+     * <td style="vertical-align: top; width: 50%;"><code>java.class</code><br>
      * </td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("de", "DE")</td>
-     * <td style="vertical-align: top; width: 50%;">java.properties<br>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("de", "DE")</code></td>
+     * <td style="vertical-align: top; width: 50%;"><code>java.properties</code><br>
      * </td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("de")</td>
-     * <td style="vertical-align: top; width: 50%;">java.class</td>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("de")</code></td>
+     * <td style="vertical-align: top; width: 50%;"><code>java.class</code></td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("de")</td>
-     * <td style="vertical-align: top; width: 50%;">java.properties</td>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("de")</code></td>
+     * <td style="vertical-align: top; width: 50%;"><code>java.properties</code></td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("")<br>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("")</code><br>
      * </td>
-     * <td style="vertical-align: top; width: 50%;">java.class</td>
+     * <td style="vertical-align: top; width: 50%;"><code>java.class</code></td>
      * </tr>
      * <tr>
-     * <td style="vertical-align: top; width: 50%;">Locale("")</td>
-     * <td style="vertical-align: top; width: 50%;">java.properties</td>
+     * <td style="vertical-align: top; width: 50%;"><code>Locale("")</code></td>
+     * <td style="vertical-align: top; width: 50%;"><code>java.properties</code></td>
      * </tr>
-     * </code></tbody>
+     * </tbody>
      * </table>
      * </li>
      *
@@ -1210,7 +1275,7 @@
      * <p><code>getBundle</code> finds
      * <code>foo/bar/Messages_fr.properties</code> and creates a
      * <code>ResourceBundle</code> instance. Then, <code>getBundle</code>
-     * sets up its parent chain from the list of the candiate locales.  Only
+     * sets up its parent chain from the list of the candidate locales.  Only
      * <code>foo/bar/Messages.properties</code> is found in the list and
      * <code>getBundle</code> creates a <code>ResourceBundle</code> instance
      * that becomes the parent of the instance for
@@ -1248,6 +1313,18 @@
         return getBundleImpl(baseName, targetLocale, loader, control);
     }
 
+    private static Control getDefaultControl(String baseName) {
+        if (providers != null) {
+            for (ResourceBundleControlProvider provider : providers) {
+                Control control = provider.getControl(baseName);
+                if (control != null) {
+                    return control;
+                }
+            }
+        }
+        return Control.INSTANCE;
+    }
+
     private static ResourceBundle getBundleImpl(String baseName, Locale locale,
                                                 ClassLoader loader, Control control) {
         if (locale == null || control == null) {
@@ -1333,8 +1410,8 @@
      * Checks if the given <code>List</code> is not null, not empty,
      * not having null in its elements.
      */
-    private static final boolean checkList(List a) {
-        boolean valid = (a != null && a.size() != 0);
+    private static boolean checkList(List<?> a) {
+        boolean valid = (a != null && !a.isEmpty());
         if (valid) {
             int size = a.size();
             for (int i = 0; valid && i < size; i++) {
@@ -1344,12 +1421,12 @@
         return valid;
     }
 
-    private static final ResourceBundle findBundle(CacheKey cacheKey,
-                                                   List<Locale> candidateLocales,
-                                                   List<String> formats,
-                                                   int index,
-                                                   Control control,
-                                                   ResourceBundle baseBundle) {
+    private static ResourceBundle findBundle(CacheKey cacheKey,
+                                             List<Locale> candidateLocales,
+                                             List<String> formats,
+                                             int index,
+                                             Control control,
+                                             ResourceBundle baseBundle) {
         Locale targetLocale = candidateLocales.get(index);
         ResourceBundle parent = null;
         if (index != candidateLocales.size() - 1) {
@@ -1421,10 +1498,10 @@
         return parent;
     }
 
-    private static final ResourceBundle loadBundle(CacheKey cacheKey,
-                                                   List<String> formats,
-                                                   Control control,
-                                                   boolean reload) {
+    private static ResourceBundle loadBundle(CacheKey cacheKey,
+                                             List<String> formats,
+                                             Control control,
+                                             boolean reload) {
 
         // Here we actually load the bundle in the order of formats
         // specified by the getFormats() value.
@@ -1461,7 +1538,7 @@
         return bundle;
     }
 
-    private static final boolean isValidBundle(ResourceBundle bundle) {
+    private static boolean isValidBundle(ResourceBundle bundle) {
         return bundle != null && bundle != NONEXISTENT_BUNDLE;
     }
 
@@ -1469,7 +1546,7 @@
      * Determines whether any of resource bundles in the parent chain,
      * including the leaf, have expired.
      */
-    private static final boolean hasValidParentChain(ResourceBundle bundle) {
+    private static boolean hasValidParentChain(ResourceBundle bundle) {
         long now = System.currentTimeMillis();
         while (bundle != null) {
             if (bundle.expired) {
@@ -1490,9 +1567,9 @@
     /**
      * Throw a MissingResourceException with proper message
      */
-    private static final void throwMissingResourceException(String baseName,
-                                                            Locale locale,
-                                                            Throwable cause) {
+    private static void throwMissingResourceException(String baseName,
+                                                      Locale locale,
+                                                      Throwable cause) {
         // If the cause is a MissingResourceException, avoid creating
         // a long chain. (6355009)
         if (cause instanceof MissingResourceException) {
@@ -1515,8 +1592,8 @@
      * cache or its parent has expired. <code>bundle.expire</code> is true
      * upon return if the bundle in the cache has expired.
      */
-    private static final ResourceBundle findBundleInCache(CacheKey cacheKey,
-                                                          Control control) {
+    private static ResourceBundle findBundleInCache(CacheKey cacheKey,
+                                                    Control control) {
         BundleReference bundleRef = cacheList.get(cacheKey);
         if (bundleRef == null) {
             return null;
@@ -1622,9 +1699,9 @@
      * the bundle before this call, the one found in the cache is
      * returned.
      */
-    private static final ResourceBundle putBundleInCache(CacheKey cacheKey,
-                                                         ResourceBundle bundle,
-                                                         Control control) {
+    private static ResourceBundle putBundleInCache(CacheKey cacheKey,
+                                                   ResourceBundle bundle,
+                                                   Control control) {
         setExpirationTime(cacheKey, control);
         if (cacheKey.expirationTime != Control.TTL_DONT_CACHE) {
             CacheKey key = (CacheKey) cacheKey.clone();
@@ -1655,7 +1732,7 @@
         return bundle;
     }
 
-    private static final void setExpirationTime(CacheKey cacheKey, Control control) {
+    private static void setExpirationTime(CacheKey cacheKey, Control control) {
         long ttl = control.getTimeToLive(cacheKey.getName(),
                                          cacheKey.getLocale());
         if (ttl >= 0) {
@@ -1680,7 +1757,9 @@
      */
     @CallerSensitive
     public static final void clearCache() {
+        // Android-changed: use of VMStack.getCallingClassLoader()
         clearCache(getLoader(VMStack.getCallingClassLoader()));
+        // clearCache(getLoader(Reflection.getCallerClass()));
     }
 
     /**
@@ -2160,11 +2239,11 @@
          * one by one as below:
          *
          * <ul>
-         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
-         * <li> [<em>L</em>, <em>C</em>]
-         * <li> [<em>L</em>]
-         * <li> <code>Locale.ROOT</code>
-         * </ul>
+         * <li> [<em>L</em>, <em>C</em>, <em>V</em>] </li>
+         * <li> [<em>L</em>, <em>C</em>] </li>
+         * <li> [<em>L</em>] </li>
+         * <li> <code>Locale.ROOT</code> </li>
+         * </ul></li>
          *
          * <li>For an input <code>Locale</code> with a non-empty script value,
          * append candidate <code>Locale</code>s by omitting the final component
@@ -2172,33 +2251,33 @@
          * <code>Locale</code> with country and variant restored:
          *
          * <ul>
-         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V</em>]
-         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
-         * <li> [<em>L</em>, <em>S</em>]
-         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
-         * <li> [<em>L</em>, <em>C</em>]
-         * <li> [<em>L</em>]
-         * <li> <code>Locale.ROOT</code>
-         * </ul>
+         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V</em>]</li>
+         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]</li>
+         * <li> [<em>L</em>, <em>S</em>]</li>
+         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]</li>
+         * <li> [<em>L</em>, <em>C</em>]</li>
+         * <li> [<em>L</em>]</li>
+         * <li> <code>Locale.ROOT</code></li>
+         * </ul></li>
          *
          * <li>For an input <code>Locale</code> with a variant value consisting
          * of multiple subtags separated by underscore, generate candidate
          * <code>Locale</code>s by omitting the variant subtags one by one, then
-         * insert them after every occurence of <code> Locale</code>s with the
+         * insert them after every occurrence of <code> Locale</code>s with the
          * full variant value in the original list.  For example, if the
          * the variant consists of two subtags <em>V1</em> and <em>V2</em>:
          *
          * <ul>
-         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
-         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>]
-         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
-         * <li> [<em>L</em>, <em>S</em>]
-         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
-         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>]
-         * <li> [<em>L</em>, <em>C</em>]
-         * <li> [<em>L</em>]
-         * <li> <code>Locale.ROOT</code>
-         * </ul>
+         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]</li>
+         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>]</li>
+         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]</li>
+         * <li> [<em>L</em>, <em>S</em>]</li>
+         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]</li>
+         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>]</li>
+         * <li> [<em>L</em>, <em>C</em>]</li>
+         * <li> [<em>L</em>]</li>
+         * <li> <code>Locale.ROOT</code></li>
+         * </ul></li>
          *
          * <li>Special cases for Chinese.  When an input <code>Locale</code> has the
          * language "zh" (Chinese) and an empty script value, either "Hans" (Simplified) or
@@ -2209,21 +2288,21 @@
          * is empty, no script is supplied.  For example, for <code>Locale("zh", "CN")
          * </code>, the candidate list will be:
          * <ul>
-         * <li> [<em>L</em>("zh"), <em>S</em>("Hans"), <em>C</em>("CN")]
-         * <li> [<em>L</em>("zh"), <em>S</em>("Hans")]
-         * <li> [<em>L</em>("zh"), <em>C</em>("CN")]
-         * <li> [<em>L</em>("zh")]
-         * <li> <code>Locale.ROOT</code>
+         * <li> [<em>L</em>("zh"), <em>S</em>("Hans"), <em>C</em>("CN")]</li>
+         * <li> [<em>L</em>("zh"), <em>S</em>("Hans")]</li>
+         * <li> [<em>L</em>("zh"), <em>C</em>("CN")]</li>
+         * <li> [<em>L</em>("zh")]</li>
+         * <li> <code>Locale.ROOT</code></li>
          * </ul>
          *
          * For <code>Locale("zh", "TW")</code>, the candidate list will be:
          * <ul>
-         * <li> [<em>L</em>("zh"), <em>S</em>("Hant"), <em>C</em>("TW")]
-         * <li> [<em>L</em>("zh"), <em>S</em>("Hant")]
-         * <li> [<em>L</em>("zh"), <em>C</em>("TW")]
-         * <li> [<em>L</em>("zh")]
-         * <li> <code>Locale.ROOT</code>
-         * </ul>
+         * <li> [<em>L</em>("zh"), <em>S</em>("Hant"), <em>C</em>("TW")]</li>
+         * <li> [<em>L</em>("zh"), <em>S</em>("Hant")]</li>
+         * <li> [<em>L</em>("zh"), <em>C</em>("TW")]</li>
+         * <li> [<em>L</em>("zh")]</li>
+         * <li> <code>Locale.ROOT</code></li>
+         * </ul></li>
          *
          * <li>Special cases for Norwegian.  Both <code>Locale("no", "NO",
          * "NY")</code> and <code>Locale("nn", "NO")</code> represent Norwegian
@@ -2231,10 +2310,10 @@
          * list is generated up to [<em>L</em>("nn")], and then the following
          * candidates are added:
          *
-         * <ul><li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("NY")]
-         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
-         * <li> [<em>L</em>("no")]
-         * <li> <code>Locale.ROOT</code>
+         * <ul><li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("NY")]</li>
+         * <li> [<em>L</em>("no"), <em>C</em>("NO")]</li>
+         * <li> [<em>L</em>("no")]</li>
+         * <li> <code>Locale.ROOT</code></li>
          * </ul>
          *
          * If the locale is exactly <code>Locale("no", "NO", "NY")</code>, it is first
@@ -2251,20 +2330,18 @@
          * candidate list:
          *
          * <ul>
-         * <li> [<em>L</em>("nb"), <em>C</em>("NO"), <em>V</em>("POSIX")]
-         * <li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("POSIX")]
-         * <li> [<em>L</em>("nb"), <em>C</em>("NO")]
-         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
-         * <li> [<em>L</em>("nb")]
-         * <li> [<em>L</em>("no")]
-         * <li> <code>Locale.ROOT</code>
+         * <li> [<em>L</em>("nb"), <em>C</em>("NO"), <em>V</em>("POSIX")]</li>
+         * <li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("POSIX")]</li>
+         * <li> [<em>L</em>("nb"), <em>C</em>("NO")]</li>
+         * <li> [<em>L</em>("no"), <em>C</em>("NO")]</li>
+         * <li> [<em>L</em>("nb")]</li>
+         * <li> [<em>L</em>("no")]</li>
+         * <li> <code>Locale.ROOT</code></li>
          * </ul>
          *
          * <code>Locale("no", "NO", "POSIX")</code> would generate the same list
          * except that locales with "no" would appear before the corresponding
          * locales with "nb".</li>
-         *
-         * </li>
          * </ol>
          *
          * <p>The default implementation uses an {@link ArrayList} that
@@ -2284,9 +2361,9 @@
          * is returned. And if the resource bundles for the "ja" and
          * "" <code>Locale</code>s are found, then the runtime resource
          * lookup path (parent chain) is:
-         * <pre>
+         * <pre>{@code
          *     Messages_ja -> Messages
-         * </pre>
+         * }</pre>
          *
          * @param baseName
          *        the base name of the resource bundle, a fully
@@ -2353,18 +2430,27 @@
                     if (script.length() == 0 && region.length() > 0) {
                         // Supply script for users who want to use zh_Hans/zh_Hant
                         // as bundle names (recommended for Java7+)
-                        if (region.equals("TW") || region.equals("HK") || region.equals("MO")) {
+                        switch (region) {
+                        case "TW":
+                        case "HK":
+                        case "MO":
                             script = "Hant";
-                        } else if (region.equals("CN") || region.equals("SG")) {
+                            break;
+                        case "CN":
+                        case "SG":
                             script = "Hans";
+                            break;
                         }
                     } else if (script.length() > 0 && region.length() == 0) {
                         // Supply region(country) for users who still package Chinese
                         // bundles using old convension.
-                        if (script.equals("Hans")) {
+                        switch (script) {
+                        case "Hans":
                             region = "CN";
-                        } else if (script.equals("Hant")) {
+                            break;
+                        case "Hant":
                             region = "TW";
+                            break;
                         }
                     }
                 }
@@ -2565,6 +2651,7 @@
             ResourceBundle bundle = null;
             if (format.equals("java.class")) {
                 try {
+                    @SuppressWarnings("unchecked")
                     Class<? extends ResourceBundle> bundleClass
                         = (Class<? extends ResourceBundle>)loader.loadClass(bundleName);
 
@@ -2579,7 +2666,10 @@
                 } catch (ClassNotFoundException e) {
                 }
             } else if (format.equals("java.properties")) {
-                final String resourceName = toResourceName(bundleName, "properties");
+                final String resourceName = toResourceName0(bundleName, "properties");
+                if (resourceName == null) {
+                    return bundle;
+                }
                 final ClassLoader classLoader = loader;
                 final boolean reloadFlag = reload;
                 InputStream stream = null;
@@ -2610,8 +2700,10 @@
                 }
                 if (stream != null) {
                     try {
+                        // Android-changed: Use UTF-8 for property based resources. b/26879578
                         bundle = new PropertyResourceBundle(
                                 new InputStreamReader(stream, StandardCharsets.UTF_8));
+                        // bundle = new PropertyResourceBundle(stream);
                     } finally {
                         stream.close();
                     }
@@ -2734,7 +2826,10 @@
             }
             boolean result = false;
             try {
-                String resourceName = toResourceName(toBundleName(baseName, locale), format);
+                String resourceName = toResourceName0(toBundleName(baseName, locale), format);
+                if (resourceName == null) {
+                    return result;
+                }
                 URL url = loader.getResource(resourceName);
                 if (url != null) {
                     long lastModified = 0;
@@ -2780,7 +2875,7 @@
          * and <code>variant</code> are the language, script, country, and variant
          * values of <code>locale</code>, respectively. Final component values that
          * are empty Strings are omitted along with the preceding '_'.  When the
-         * script is empty, the script value is ommitted along with the preceding '_'.
+         * script is empty, the script value is omitted along with the preceding '_'.
          * If all of the values are empty strings, then <code>baseName</code>
          * is returned.
          *
@@ -2868,6 +2963,15 @@
             sb.append(bundleName.replace('.', '/')).append('.').append(suffix);
             return sb.toString();
         }
+
+        private String toResourceName0(String bundleName, String suffix) {
+            // application protocol check
+            if (bundleName.contains("://")) {
+                return null;
+            } else {
+                return toResourceName(bundleName, suffix);
+            }
+        }
     }
 
     private static class SingleFormatControl extends Control {
diff --git a/ojluni/src/main/java/java/util/ServiceLoader.java b/ojluni/src/main/java/java/util/ServiceLoader.java
index 4b3b029..8a0b3a8 100644
--- a/ojluni/src/main/java/java/util/ServiceLoader.java
+++ b/ojluni/src/main/java/java/util/ServiceLoader.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -66,12 +66,13 @@
  *
  * <p><a name="format"> A service provider is identified by placing a
  * <i>provider-configuration file</i> in the resource directory
- * <tt>META-INF/services</tt>.  The file's name is the fully-qualified <a
+ * <tt>META-INF/services</tt>.</a>  The file's name is the fully-qualified <a
  * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
  * The file contains a list of fully-qualified binary names of concrete
  * provider classes, one per line.  Space and tab characters surrounding each
  * name, as well as blank lines, are ignored.  The comment character is
- * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>, <font size="-1">NUMBER SIGN</font>); on
+ * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>,
+ * <font style="font-size:smaller;">NUMBER SIGN</font>); on
  * each line all characters following the first comment character are ignored.
  * The file must be encoded in UTF-8.
  *
@@ -186,10 +187,14 @@
     private static final String PREFIX = "META-INF/services/";
 
     // The class or interface representing the service being loaded
-    private Class<S> service;
+    private final Class<S> service;
 
     // The class loader used to locate, load, and instantiate providers
-    private ClassLoader loader;
+    private final ClassLoader loader;
+
+    // The access control context taken when the ServiceLoader is created
+    // Android-changed: do not use legacy security code
+    // private final AccessControlContext acc;
 
     // Cached providers, in instantiation order
     private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
@@ -214,25 +219,28 @@
     }
 
     private ServiceLoader(Class<S> svc, ClassLoader cl) {
-        service = svc;
-        loader = cl;
+        service = Objects.requireNonNull(svc, "Service interface cannot be null");
+        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
+        // Android-changed: Do not use legacy security code (System.getSecurtiyManager()
+        // is always null).
+        // acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
         reload();
     }
 
-    private static void fail(Class service, String msg, Throwable cause)
+    private static void fail(Class<?> service, String msg, Throwable cause)
         throws ServiceConfigurationError
     {
         throw new ServiceConfigurationError(service.getName() + ": " + msg,
                                             cause);
     }
 
-    private static void fail(Class service, String msg)
+    private static void fail(Class<?> service, String msg)
         throws ServiceConfigurationError
     {
         throw new ServiceConfigurationError(service.getName() + ": " + msg);
     }
 
-    private static void fail(Class service, URL u, int line, String msg)
+    private static void fail(Class<?> service, URL u, int line, String msg)
         throws ServiceConfigurationError
     {
         fail(service, u + ":" + line + ": " + msg);
@@ -241,7 +249,7 @@
     // Parse a single line from the given configuration file, adding the name
     // on the line to the names list.
     //
-    private int parseLine(Class service, URL u, BufferedReader r, int lc,
+    private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
                           List<String> names)
         throws IOException, ServiceConfigurationError
     {
@@ -287,7 +295,7 @@
     //         If an I/O error occurs while reading from the given URL, or
     //         if a configuration-file format error is detected
     //
-    private Iterator<String> parse(Class service, URL u)
+    private Iterator<String> parse(Class<?> service, URL u)
         throws ServiceConfigurationError
     {
         InputStream in = null;
@@ -328,7 +336,7 @@
             this.loader = loader;
         }
 
-        public boolean hasNext() {
+        private boolean hasNextService() {
             if (nextName != null) {
                 return true;
             }
@@ -353,10 +361,9 @@
             return true;
         }
 
-        public S next() {
-            if (!hasNext()) {
+        private S nextService() {
+            if (!hasNextService())
                 throw new NoSuchElementException();
-            }
             String cn = nextName;
             nextName = null;
             Class<?> c = null;
@@ -364,13 +371,18 @@
                 c = Class.forName(cn, false, loader);
             } catch (ClassNotFoundException x) {
                 fail(service,
+                     // Android-changed: Let the ServiceConfigurationError have a cause.
                      "Provider " + cn + " not found", x);
+                     // "Provider " + cn + " not found");
             }
             if (!service.isAssignableFrom(c)) {
+                // Android-changed: Let the ServiceConfigurationError have a cause.
                 ClassCastException cce = new ClassCastException(
                         service.getCanonicalName() + " is not assignable from " + c.getCanonicalName());
                 fail(service,
                      "Provider " + cn  + " not a subtype", cce);
+                // fail(service,
+                //        "Provider " + cn  + " not a subtype");
             }
             try {
                 S p = service.cast(c.newInstance());
@@ -378,12 +390,40 @@
                 return p;
             } catch (Throwable x) {
                 fail(service,
-                     "Provider " + cn + " could not be instantiated: " + x,
+                     "Provider " + cn + " could not be instantiated",
                      x);
             }
             throw new Error();          // This cannot happen
         }
 
+        public boolean hasNext() {
+            // Android-changed: do not use legacy security code
+            /* if (acc == null) { */
+                return hasNextService();
+            /*
+            } else {
+                PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
+                    public Boolean run() { return hasNextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
+            }
+            */
+        }
+
+        public S next() {
+            // Android-changed: do not use legacy security code
+            /* if (acc == null) { */
+                return nextService();
+            /*
+            } else {
+                PrivilegedAction<S> action = new PrivilegedAction<S>() {
+                    public S run() { return nextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
+            }
+            */
+        }
+
         public void remove() {
             throw new UnsupportedOperationException();
         }
@@ -427,6 +467,12 @@
      * Invoking its {@link java.util.Iterator#remove() remove} method will
      * cause an {@link UnsupportedOperationException} to be thrown.
      *
+     * @implNote When adding providers to the cache, the {@link #iterator
+     * Iterator} processes resources in the order that the {@link
+     * java.lang.ClassLoader#getResources(java.lang.String)
+     * ClassLoader.getResources(String)} method finds the service configuration
+     * files.
+     *
      * @return  An iterator that lazily loads providers for this loader's
      *          service
      */
@@ -459,6 +505,8 @@
      * Creates a new service loader for the given service type and class
      * loader.
      *
+     * @param  <S> the class of the service type
+     *
      * @param  service
      *         The interface or abstract class representing the service
      *
@@ -492,6 +540,8 @@
      * ServiceLoader.load(<i>service</i>,
      *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
      *
+     * @param  <S> the class of the service type
+     *
      * @param  service
      *         The interface or abstract class representing the service
      *
@@ -521,6 +571,8 @@
      * have been installed into the current Java virtual machine; providers on
      * the application's class path will be ignored.
      *
+     * @param  <S> the class of the service type
+     *
      * @param  service
      *         The interface or abstract class representing the service
      *
@@ -536,6 +588,8 @@
         return ServiceLoader.load(service, prev);
     }
 
+    // Android-changed BEGIN: Add a method to instantiate a class from a system
+    // property (used in other parts of libcore).
     /**
      * Internal API to support built-in SPIs that check a system property first.
      * Returns an instance specified by a property with the class' binary name, or null if
@@ -554,6 +608,7 @@
             throw new Error(e);
         }
     }
+    // Android-changed END
 
     /**
      * Returns a string describing this service.
diff --git a/ojluni/src/main/java/java/util/TimerTask.java b/ojluni/src/main/java/java/util/TimerTask.java
index b8c8340..5750486 100644
--- a/ojluni/src/main/java/java/util/TimerTask.java
+++ b/ojluni/src/main/java/java/util/TimerTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,14 +130,14 @@
      * <p>This method is typically invoked from within a task's run method, to
      * determine whether the current execution of the task is sufficiently
      * timely to warrant performing the scheduled activity:
-     * <pre>
+     * <pre>{@code
      *   public void run() {
      *       if (System.currentTimeMillis() - scheduledExecutionTime() >=
      *           MAX_TARDINESS)
      *               return;  // Too late; skip this execution.
      *       // Perform the task
      *   }
-     * </pre>
+     * }</pre>
      * This method is typically <i>not</i> used in conjunction with
      * <i>fixed-delay execution</i> repeating tasks, as their scheduled
      * execution times are allowed to drift over time, and so are not terribly
diff --git a/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java b/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java
new file mode 100644
index 0000000..e731f0f
--- /dev/null
+++ b/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.spi;
+
+import java.util.ResourceBundle;
+
+/**
+ * An interface for service providers that provide implementations of {@link
+ * java.util.ResourceBundle.Control}. The <a
+ * href="../ResourceBundle.html#default_behavior">default resource bundle loading
+ * behavior</a> of the {@code ResourceBundle.getBundle} factory methods that take
+ * no {@link java.util.ResourceBundle.Control} instance can be modified with {@code
+ * ResourceBundleControlProvider} implementations.
+ *
+ * <p>Provider implementations must be packaged using the <a
+ * href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/extensions/index.html">Java Extension
+ * Mechanism</a> as installed extensions. Refer to {@link java.util.ServiceLoader}
+ * for the extension packaging. Any installed {@code
+ * ResourceBundleControlProvider} implementations are loaded using {@link
+ * java.util.ServiceLoader} at the {@code ResourceBundle} class loading time.
+ *
+ * @author Masayoshi Okutsu
+ * @since 1.8
+ * @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
+ *      ResourceBundle.getBundle
+ * @see java.util.ServiceLoader#loadInstalled(Class)
+ */
+public interface ResourceBundleControlProvider {
+    /**
+     * Returns a {@code ResourceBundle.Control} instance that is used
+     * to handle resource bundle loading for the given {@code
+     * baseName}. This method must return {@code null} if the given
+     * {@code baseName} isn't handled by this provider.
+     *
+     * @param baseName the base name of the resource bundle
+     * @return a {@code ResourceBundle.Control} instance,
+     *         or {@code null} if the given {@code baseName} is not
+     *         applicable to this provider.
+     * @throws NullPointerException if {@code baseName} is {@code null}
+     */
+    public ResourceBundle.Control getControl(String baseName);
+}
diff --git a/ojluni/src/main/java/javax/crypto/CipherOutputStream.java b/ojluni/src/main/java/javax/crypto/CipherOutputStream.java
index 15edd45..6b8d273 100644
--- a/ojluni/src/main/java/javax/crypto/CipherOutputStream.java
+++ b/ojluni/src/main/java/javax/crypto/CipherOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,9 @@
     // the buffer holding data ready to be written out
     private byte[] obuffer;
 
+    // stream status
+    private boolean closed = false;
+
     /**
      *
      * Constructs a CipherOutputStream from an OutputStream and a
@@ -198,11 +201,14 @@
      * @since      JCE1.2
      */
     public void close() throws IOException {
+        if (closed) {
+            return;
+        }
+
+        closed = true;
         try {
             obuffer = cipher.doFinal();
-        } catch (IllegalBlockSizeException e) {
-            obuffer = null;
-        } catch (BadPaddingException e) {
+        } catch (IllegalBlockSizeException | BadPaddingException e) {
             obuffer = null;
         }
         try {
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLContext.java b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
index 7e615b8..fa8a3af 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLContext.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
@@ -50,13 +50,13 @@
  *             <td>Default</td>
  *             <td>10+</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSL</td>
- *             <td>10+</td>
+ *             <td>10&ndash;TBD</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSLv3</td>
- *             <td>10+</td>
+ *             <td>10&ndash;TBD</td>
  *         </tr>
  *         <tr>
  *             <td>TLS</td>
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
index f460d5f..c4b3df0 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -380,9 +380,9 @@
  *         </tr>
  *     </thead>
  *     <tbody>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSLv3</td>
- *             <td>1+</td>
+ *             <td>1&ndash;TBD</td>
  *             <td>1&ndash;22</td>
  *         </tr>
  *         <tr>
@@ -498,14 +498,14 @@
  *             <td>9&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSL_RSA_WITH_RC4_128_MD5</td>
- *             <td>9+</td>
+ *             <td>9&ndash;TBD</td>
  *             <td>9&ndash;19</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSL_RSA_WITH_RC4_128_SHA</td>
- *             <td>9+</td>
+ *             <td>9&ndash;TBD</td>
  *             <td>9&ndash;23</td>
  *         </tr>
  *         <tr class="deprecated">
@@ -718,9 +718,9 @@
  *             <td>20&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
- *             <td>20+</td>
+ *             <td>20&ndash;TBD</td>
  *             <td>20&ndash;23</td>
  *         </tr>
  *         <tr>
@@ -783,9 +783,9 @@
  *             <td>20&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
- *             <td>20+</td>
+ *             <td>20&ndash;TBD</td>
  *             <td>20&ndash;23</td>
  *         </tr>
  *         <tr class="deprecated">
@@ -933,9 +933,9 @@
  *             <td>21+</td>
  *             <td>21+</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_PSK_WITH_RC4_128_SHA</td>
- *             <td>21+</td>
+ *             <td>21&ndash;TBD</td>
  *             <td></td>
  *         </tr>
  *         <tr class="deprecated">
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLSocket.java b/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
index 7203166..093f2d9 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
@@ -155,10 +155,10 @@
  *         </tr>
  *     </thead>
  *     <tbody>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSLv3</td>
- *             <td>1+</td>
- *             <td>1+</td>
+ *             <td>1&ndash;TBD</td>
+ *             <td>1&ndash;22</td>
  *         </tr>
  *         <tr>
  *             <td>TLSv1</td>
@@ -188,9 +188,9 @@
  *         </tr>
  *     </thead>
  *     <tbody>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSLv3</td>
- *             <td>1+</td>
+ *             <td>1&ndash;TBD</td>
  *             <td>1&ndash;22</td>
  *         </tr>
  *         <tr>
@@ -313,14 +313,14 @@
  *             <td>9&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSL_RSA_WITH_RC4_128_MD5</td>
- *             <td>9+</td>
+ *             <td>9&ndash;TBD</td>
  *             <td>9&ndash;19</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>SSL_RSA_WITH_RC4_128_SHA</td>
- *             <td>9+</td>
+ *             <td>9&ndash;TBD</td>
  *             <td>9&ndash;23</td>
  *         </tr>
  *         <tr class="deprecated">
@@ -458,9 +458,9 @@
  *             <td>11&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
- *             <td>11+</td>
+ *             <td>11&ndash;TBD</td>
  *             <td>11&ndash;23</td>
  *         </tr>
  *         <tr>
@@ -518,9 +518,9 @@
  *             <td>11&ndash;22</td>
  *             <td></td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
- *             <td>11+</td>
+ *             <td>11&ndash;TBD</td>
  *             <td>11&ndash;23</td>
  *         </tr>
  *         <tr class="deprecated">
@@ -663,9 +663,9 @@
  *             <td>21+</td>
  *             <td>21+</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>TLS_PSK_WITH_RC4_128_SHA</td>
- *             <td>21+</td>
+ *             <td>21&ndash;TBD</td>
  *             <td></td>
  *         </tr>
  *         <tr>
@@ -848,16 +848,16 @@
  *             <td>1&ndash;8</td>
  *             <td>1&ndash;8</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>RC4-MD5</td>
  *             <td>SSL_RSA_WITH_RC4_128_MD5</td>
- *             <td>1+</td>
+ *             <td>1&ndash;TBD</td>
  *             <td>1&ndash;19</td>
  *         </tr>
- *         <tr>
+ *         <tr class="deprecated">
  *             <td>RC4-SHA</td>
  *             <td>SSL_RSA_WITH_RC4_128_SHA</td>
- *             <td>1+</td>
+ *             <td>1&ndash;TBD</td>
  *             <td>1&ndash;23</td>
  *         </tr>
  *     </tbody>
diff --git a/ojluni/src/main/java/javax/security/auth/Subject.java b/ojluni/src/main/java/javax/security/auth/Subject.java
index 56e864c..2c9e8b8 100644
--- a/ojluni/src/main/java/javax/security/auth/Subject.java
+++ b/ojluni/src/main/java/javax/security/auth/Subject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,39 +42,39 @@
 import sun.security.util.ResourcesMgr;
 
 /**
- * <p> A <code>Subject</code> represents a grouping of related information
+ * <p> A {@code Subject} represents a grouping of related information
  * for a single entity, such as a person.
  * Such information includes the Subject's identities as well as
  * its security-related attributes
  * (passwords and cryptographic keys, for example).
  *
  * <p> Subjects may potentially have multiple identities.
- * Each identity is represented as a <code>Principal</code>
- * within the <code>Subject</code>.  Principals simply bind names to a
- * <code>Subject</code>.  For example, a <code>Subject</code> that happens
+ * Each identity is represented as a {@code Principal}
+ * within the {@code Subject}.  Principals simply bind names to a
+ * {@code Subject}.  For example, a {@code Subject} that happens
  * to be a person, Alice, might have two Principals:
  * one which binds "Alice Bar", the name on her driver license,
- * to the <code>Subject</code>, and another which binds,
+ * to the {@code Subject}, and another which binds,
  * "999-99-9999", the number on her student identification card,
- * to the <code>Subject</code>.  Both Principals refer to the same
- * <code>Subject</code> even though each has a different name.
+ * to the {@code Subject}.  Both Principals refer to the same
+ * {@code Subject} even though each has a different name.
  *
- * <p> A <code>Subject</code> may also own security-related attributes,
+ * <p> A {@code Subject} may also own security-related attributes,
  * which are referred to as credentials.
  * Sensitive credentials that require special protection, such as
  * private cryptographic keys, are stored within a private credential
- * <code>Set</code>.  Credentials intended to be shared, such as
+ * {@code Set}.  Credentials intended to be shared, such as
  * public key certificates or Kerberos server tickets are stored
- * within a public credential <code>Set</code>.  Different permissions
+ * within a public credential {@code Set}.  Different permissions
  * are required to access and modify the different credential Sets.
  *
- * <p> To retrieve all the Principals associated with a <code>Subject</code>,
- * invoke the <code>getPrincipals</code> method.  To retrieve
- * all the public or private credentials belonging to a <code>Subject</code>,
- * invoke the <code>getPublicCredentials</code> method or
- * <code>getPrivateCredentials</code> method, respectively.
- * To modify the returned <code>Set</code> of Principals and credentials,
- * use the methods defined in the <code>Set</code> class.
+ * <p> To retrieve all the Principals associated with a {@code Subject},
+ * invoke the {@code getPrincipals} method.  To retrieve
+ * all the public or private credentials belonging to a {@code Subject},
+ * invoke the {@code getPublicCredentials} method or
+ * {@code getPrivateCredentials} method, respectively.
+ * To modify the returned {@code Set} of Principals and credentials,
+ * use the methods defined in the {@code Set} class.
  * For example:
  * <pre>
  *      Subject subject;
@@ -86,13 +86,13 @@
  *      subject.getPublicCredentials().add(credential);
  * </pre>
  *
- * <p> This <code>Subject</code> class implements <code>Serializable</code>.
- * While the Principals associated with the <code>Subject</code> are serialized,
- * the credentials associated with the <code>Subject</code> are not.
- * Note that the <code>java.security.Principal</code> class
- * does not implement <code>Serializable</code>.  Therefore all concrete
- * <code>Principal</code> implementations associated with Subjects
- * must implement <code>Serializable</code>.
+ * <p> This {@code Subject} class implements {@code Serializable}.
+ * While the Principals associated with the {@code Subject} are serialized,
+ * the credentials associated with the {@code Subject} are not.
+ * Note that the {@code java.security.Principal} class
+ * does not implement {@code Serializable}.  Therefore all concrete
+ * {@code Principal} implementations associated with Subjects
+ * must implement {@code Serializable}.
  *
  * @see java.security.Principal
  * @see java.security.DomainCombiner
@@ -102,14 +102,14 @@
     private static final long serialVersionUID = -8308522755600156056L;
 
     /**
-     * A <code>Set</code> that provides a view of all of this
+     * A {@code Set} that provides a view of all of this
      * Subject's Principals
      *
      * <p>
      *
      * @serial Each element in this set is a
-     *          <code>java.security.Principal</code>.
-     *          The set is a <code>Subject.SecureSet</code>.
+     *          {@code java.security.Principal}.
+     *          The set is a {@code Subject.SecureSet}.
      */
     Set<Principal> principals;
 
@@ -135,21 +135,21 @@
         = new ProtectionDomain[0];
 
     /**
-     * Create an instance of a <code>Subject</code>
-     * with an empty <code>Set</code> of Principals and empty
+     * Create an instance of a {@code Subject}
+     * with an empty {@code Set} of Principals and empty
      * Sets of public and private credentials.
      *
-     * <p> The newly constructed Sets check whether this <code>Subject</code>
+     * <p> The newly constructed Sets check whether this {@code Subject}
      * has been set read-only before permitting subsequent modifications.
      * The newly created Sets also prevent illegal modifications
      * by ensuring that callers have sufficient permissions.
      *
      * <p> To modify the Principals Set, the caller must have
-     * <code>AuthPermission("modifyPrincipals")</code>.
+     * {@code AuthPermission("modifyPrincipals")}.
      * To modify the public credential Set, the caller must have
-     * <code>AuthPermission("modifyPublicCredentials")</code>.
+     * {@code AuthPermission("modifyPublicCredentials")}.
      * To modify the private credential Set, the caller must have
-     * <code>AuthPermission("modifyPrivateCredentials")</code>.
+     * {@code AuthPermission("modifyPrivateCredentials")}.
      */
     public Subject() {
 
@@ -162,39 +162,39 @@
     }
 
     /**
-     * Create an instance of a <code>Subject</code> with
+     * Create an instance of a {@code Subject} with
      * Principals and credentials.
      *
      * <p> The Principals and credentials from the specified Sets
      * are copied into newly constructed Sets.
-     * These newly created Sets check whether this <code>Subject</code>
+     * These newly created Sets check whether this {@code Subject}
      * has been set read-only before permitting subsequent modifications.
      * The newly created Sets also prevent illegal modifications
      * by ensuring that callers have sufficient permissions.
      *
      * <p> To modify the Principals Set, the caller must have
-     * <code>AuthPermission("modifyPrincipals")</code>.
+     * {@code AuthPermission("modifyPrincipals")}.
      * To modify the public credential Set, the caller must have
-     * <code>AuthPermission("modifyPublicCredentials")</code>.
+     * {@code AuthPermission("modifyPublicCredentials")}.
      * To modify the private credential Set, the caller must have
-     * <code>AuthPermission("modifyPrivateCredentials")</code>.
+     * {@code AuthPermission("modifyPrivateCredentials")}.
      * <p>
      *
-     * @param readOnly true if the <code>Subject</code> is to be read-only,
+     * @param readOnly true if the {@code Subject} is to be read-only,
      *          and false otherwise. <p>
      *
-     * @param principals the <code>Set</code> of Principals
-     *          to be associated with this <code>Subject</code>. <p>
+     * @param principals the {@code Set} of Principals
+     *          to be associated with this {@code Subject}. <p>
      *
-     * @param pubCredentials the <code>Set</code> of public credentials
-     *          to be associated with this <code>Subject</code>. <p>
+     * @param pubCredentials the {@code Set} of public credentials
+     *          to be associated with this {@code Subject}. <p>
      *
-     * @param privCredentials the <code>Set</code> of private credentials
-     *          to be associated with this <code>Subject</code>.
+     * @param privCredentials the {@code Set} of private credentials
+     *          to be associated with this {@code Subject}.
      *
      * @exception NullPointerException if the specified
-     *          <code>principals</code>, <code>pubCredentials</code>,
-     *          or <code>privCredentials</code> are <code>null</code>.
+     *          {@code principals}, {@code pubCredentials},
+     *          or {@code privCredentials} are {@code null}.
      */
     public Subject(boolean readOnly, Set<? extends Principal> principals,
                    Set<?> pubCredentials, Set<?> privCredentials)
@@ -216,24 +216,24 @@
     }
 
     /**
-     * Set this <code>Subject</code> to be read-only.
+     * Set this {@code Subject} to be read-only.
      *
      * <p> Modifications (additions and removals) to this Subject's
-     * <code>Principal</code> <code>Set</code> and
+     * {@code Principal} {@code Set} and
      * credential Sets will be disallowed.
-     * The <code>destroy</code> operation on this Subject's credentials will
+     * The {@code destroy} operation on this Subject's credentials will
      * still be permitted.
      *
-     * <p> Subsequent attempts to modify the Subject's <code>Principal</code>
+     * <p> Subsequent attempts to modify the Subject's {@code Principal}
      * and credential Sets will result in an
-     * <code>IllegalStateException</code> being thrown.
-     * Also, once a <code>Subject</code> is read-only,
+     * {@code IllegalStateException} being thrown.
+     * Also, once a {@code Subject} is read-only,
      * it can not be reset to being writable again.
      *
      * <p>
      *
      * @exception SecurityException if the caller does not have permission
-     *          to set this <code>Subject</code> to be read-only.
+     *          to set this {@code Subject} to be read-only.
      */
     public void setReadOnly() {
         java.lang.SecurityManager sm = System.getSecurityManager();
@@ -245,40 +245,40 @@
     }
 
     /**
-     * Query whether this <code>Subject</code> is read-only.
+     * Query whether this {@code Subject} is read-only.
      *
      * <p>
      *
-     * @return true if this <code>Subject</code> is read-only, false otherwise.
+     * @return true if this {@code Subject} is read-only, false otherwise.
      */
     public boolean isReadOnly() {
         return this.readOnly;
     }
 
     /**
-     * Get the <code>Subject</code> associated with the provided
-     * <code>AccessControlContext</code>.
+     * Get the {@code Subject} associated with the provided
+     * {@code AccessControlContext}.
      *
-     * <p> The <code>AccessControlContext</code> may contain many
-     * Subjects (from nested <code>doAs</code> calls).
-     * In this situation, the most recent <code>Subject</code> associated
-     * with the <code>AccessControlContext</code> is returned.
+     * <p> The {@code AccessControlContext} may contain many
+     * Subjects (from nested {@code doAs} calls).
+     * In this situation, the most recent {@code Subject} associated
+     * with the {@code AccessControlContext} is returned.
      *
      * <p>
      *
-     * @param  acc the <code>AccessControlContext</code> from which to retrieve
-     *          the <code>Subject</code>.
+     * @param  acc the {@code AccessControlContext} from which to retrieve
+     *          the {@code Subject}.
      *
-     * @return  the <code>Subject</code> associated with the provided
-     *          <code>AccessControlContext</code>, or <code>null</code>
-     *          if no <code>Subject</code> is associated
-     *          with the provided <code>AccessControlContext</code>.
+     * @return  the {@code Subject} associated with the provided
+     *          {@code AccessControlContext}, or {@code null}
+     *          if no {@code Subject} is associated
+     *          with the provided {@code AccessControlContext}.
      *
      * @exception SecurityException if the caller does not have permission
-     *          to get the <code>Subject</code>. <p>
+     *          to get the {@code Subject}. <p>
      *
      * @exception NullPointerException if the provided
-     *          <code>AccessControlContext</code> is <code>null</code>.
+     *          {@code AccessControlContext} is {@code null}.
      */
     public static Subject getSubject(final AccessControlContext acc) {
 
@@ -306,33 +306,36 @@
     }
 
     /**
-     * Perform work as a particular <code>Subject</code>.
+     * Perform work as a particular {@code Subject}.
      *
      * <p> This method first retrieves the current Thread's
-     * <code>AccessControlContext</code> via
-     * <code>AccessController.getContext</code>,
-     * and then instantiates a new <code>AccessControlContext</code>
+     * {@code AccessControlContext} via
+     * {@code AccessController.getContext},
+     * and then instantiates a new {@code AccessControlContext}
      * using the retrieved context along with a new
-     * <code>SubjectDomainCombiner</code> (constructed using
-     * the provided <code>Subject</code>).
-     * Finally, this method invokes <code>AccessController.doPrivileged</code>,
-     * passing it the provided <code>PrivilegedAction</code>,
-     * as well as the newly constructed <code>AccessControlContext</code>.
+     * {@code SubjectDomainCombiner} (constructed using
+     * the provided {@code Subject}).
+     * Finally, this method invokes {@code AccessController.doPrivileged},
+     * passing it the provided {@code PrivilegedAction},
+     * as well as the newly constructed {@code AccessControlContext}.
      *
      * <p>
      *
-     * @param subject the <code>Subject</code> that the specified
-     *                  <code>action</code> will run as.  This parameter
-     *                  may be <code>null</code>. <p>
+     * @param subject the {@code Subject} that the specified
+     *                  {@code action} will run as.  This parameter
+     *                  may be {@code null}. <p>
+     *
+     * @param <T> the type of the value returned by the PrivilegedAction's
+     *                  {@code run} method.
      *
      * @param action the code to be run as the specified
-     *                  <code>Subject</code>. <p>
+     *                  {@code Subject}. <p>
      *
      * @return the value returned by the PrivilegedAction's
-     *                  <code>run</code> method.
+     *                  {@code run} method.
      *
-     * @exception NullPointerException if the <code>PrivilegedAction</code>
-     *                  is <code>null</code>. <p>
+     * @exception NullPointerException if the {@code PrivilegedAction}
+     *                  is {@code null}. <p>
      *
      * @exception SecurityException if the caller does not have permission
      *                  to invoke this method.
@@ -359,38 +362,41 @@
     }
 
     /**
-     * Perform work as a particular <code>Subject</code>.
+     * Perform work as a particular {@code Subject}.
      *
      * <p> This method first retrieves the current Thread's
-     * <code>AccessControlContext</code> via
-     * <code>AccessController.getContext</code>,
-     * and then instantiates a new <code>AccessControlContext</code>
+     * {@code AccessControlContext} via
+     * {@code AccessController.getContext},
+     * and then instantiates a new {@code AccessControlContext}
      * using the retrieved context along with a new
-     * <code>SubjectDomainCombiner</code> (constructed using
-     * the provided <code>Subject</code>).
-     * Finally, this method invokes <code>AccessController.doPrivileged</code>,
-     * passing it the provided <code>PrivilegedExceptionAction</code>,
-     * as well as the newly constructed <code>AccessControlContext</code>.
+     * {@code SubjectDomainCombiner} (constructed using
+     * the provided {@code Subject}).
+     * Finally, this method invokes {@code AccessController.doPrivileged},
+     * passing it the provided {@code PrivilegedExceptionAction},
+     * as well as the newly constructed {@code AccessControlContext}.
      *
      * <p>
      *
-     * @param subject the <code>Subject</code> that the specified
-     *                  <code>action</code> will run as.  This parameter
-     *                  may be <code>null</code>. <p>
+     * @param subject the {@code Subject} that the specified
+     *                  {@code action} will run as.  This parameter
+     *                  may be {@code null}. <p>
+     *
+     * @param <T> the type of the value returned by the
+     *                  PrivilegedExceptionAction's {@code run} method.
      *
      * @param action the code to be run as the specified
-     *                  <code>Subject</code>. <p>
+     *                  {@code Subject}. <p>
      *
      * @return the value returned by the
-     *                  PrivilegedExceptionAction's <code>run</code> method.
+     *                  PrivilegedExceptionAction's {@code run} method.
      *
      * @exception PrivilegedActionException if the
-     *                  <code>PrivilegedExceptionAction.run</code>
+     *                  {@code PrivilegedExceptionAction.run}
      *                  method throws a checked exception. <p>
      *
      * @exception NullPointerException if the specified
-     *                  <code>PrivilegedExceptionAction</code> is
-     *                  <code>null</code>. <p>
+     *                  {@code PrivilegedExceptionAction} is
+     *                  {@code null}. <p>
      *
      * @exception SecurityException if the caller does not have permission
      *                  to invoke this method.
@@ -418,33 +424,36 @@
     }
 
     /**
-     * Perform privileged work as a particular <code>Subject</code>.
+     * Perform privileged work as a particular {@code Subject}.
      *
-     * <p> This method behaves exactly as <code>Subject.doAs</code>,
+     * <p> This method behaves exactly as {@code Subject.doAs},
      * except that instead of retrieving the current Thread's
-     * <code>AccessControlContext</code>, it uses the provided
-     * <code>AccessControlContext</code>.  If the provided
-     * <code>AccessControlContext</code> is <code>null</code>,
-     * this method instantiates a new <code>AccessControlContext</code>
+     * {@code AccessControlContext}, it uses the provided
+     * {@code AccessControlContext}.  If the provided
+     * {@code AccessControlContext} is {@code null},
+     * this method instantiates a new {@code AccessControlContext}
      * with an empty collection of ProtectionDomains.
      *
      * <p>
      *
-     * @param subject the <code>Subject</code> that the specified
-     *                  <code>action</code> will run as.  This parameter
-     *                  may be <code>null</code>. <p>
+     * @param subject the {@code Subject} that the specified
+     *                  {@code action} will run as.  This parameter
+     *                  may be {@code null}. <p>
+     *
+     * @param <T> the type of the value returned by the PrivilegedAction's
+     *                  {@code run} method.
      *
      * @param action the code to be run as the specified
-     *                  <code>Subject</code>. <p>
+     *                  {@code Subject}. <p>
      *
-     * @param acc the <code>AccessControlContext</code> to be tied to the
+     * @param acc the {@code AccessControlContext} to be tied to the
      *                  specified <i>subject</i> and <i>action</i>. <p>
      *
      * @return the value returned by the PrivilegedAction's
-     *                  <code>run</code> method.
+     *                  {@code run} method.
      *
-     * @exception NullPointerException if the <code>PrivilegedAction</code>
-     *                  is <code>null</code>. <p>
+     * @exception NullPointerException if the {@code PrivilegedAction}
+     *                  is {@code null}. <p>
      *
      * @exception SecurityException if the caller does not have permission
      *                  to invoke this method.
@@ -476,38 +485,41 @@
     }
 
     /**
-     * Perform privileged work as a particular <code>Subject</code>.
+     * Perform privileged work as a particular {@code Subject}.
      *
-     * <p> This method behaves exactly as <code>Subject.doAs</code>,
+     * <p> This method behaves exactly as {@code Subject.doAs},
      * except that instead of retrieving the current Thread's
-     * <code>AccessControlContext</code>, it uses the provided
-     * <code>AccessControlContext</code>.  If the provided
-     * <code>AccessControlContext</code> is <code>null</code>,
-     * this method instantiates a new <code>AccessControlContext</code>
+     * {@code AccessControlContext}, it uses the provided
+     * {@code AccessControlContext}.  If the provided
+     * {@code AccessControlContext} is {@code null},
+     * this method instantiates a new {@code AccessControlContext}
      * with an empty collection of ProtectionDomains.
      *
      * <p>
      *
-     * @param subject the <code>Subject</code> that the specified
-     *                  <code>action</code> will run as.  This parameter
-     *                  may be <code>null</code>. <p>
+     * @param subject the {@code Subject} that the specified
+     *                  {@code action} will run as.  This parameter
+     *                  may be {@code null}. <p>
+     *
+     * @param <T> the type of the value returned by the
+     *                  PrivilegedExceptionAction's {@code run} method.
      *
      * @param action the code to be run as the specified
-     *                  <code>Subject</code>. <p>
+     *                  {@code Subject}. <p>
      *
-     * @param acc the <code>AccessControlContext</code> to be tied to the
+     * @param acc the {@code AccessControlContext} to be tied to the
      *                  specified <i>subject</i> and <i>action</i>. <p>
      *
      * @return the value returned by the
-     *                  PrivilegedExceptionAction's <code>run</code> method.
+     *                  PrivilegedExceptionAction's {@code run} method.
      *
      * @exception PrivilegedActionException if the
-     *                  <code>PrivilegedExceptionAction.run</code>
+     *                  {@code PrivilegedExceptionAction.run}
      *                  method throws a checked exception. <p>
      *
      * @exception NullPointerException if the specified
-     *                  <code>PrivilegedExceptionAction</code> is
-     *                  <code>null</code>. <p>
+     *                  {@code PrivilegedExceptionAction} is
+     *                  {@code null}. <p>
      *
      * @exception SecurityException if the caller does not have permission
      *                  to invoke this method.
@@ -556,19 +568,19 @@
     }
 
     /**
-     * Return the <code>Set</code> of Principals associated with this
-     * <code>Subject</code>.  Each <code>Principal</code> represents
-     * an identity for this <code>Subject</code>.
+     * Return the {@code Set} of Principals associated with this
+     * {@code Subject}.  Each {@code Principal} represents
+     * an identity for this {@code Subject}.
      *
-     * <p> The returned <code>Set</code> is backed by this Subject's
-     * internal <code>Principal</code> <code>Set</code>.  Any modification
-     * to the returned <code>Set</code> affects the internal
-     * <code>Principal</code> <code>Set</code> as well.
+     * <p> The returned {@code Set} is backed by this Subject's
+     * internal {@code Principal} {@code Set}.  Any modification
+     * to the returned {@code Set} affects the internal
+     * {@code Principal} {@code Set} as well.
      *
      * <p>
      *
-     * @return  The <code>Set</code> of Principals associated with this
-     *          <code>Subject</code>.
+     * @return  The {@code Set} of Principals associated with this
+     *          {@code Subject}.
      */
     public Set<Principal> getPrincipals() {
 
@@ -578,26 +590,28 @@
     }
 
     /**
-     * Return a <code>Set</code> of Principals associated with this
-     * <code>Subject</code> that are instances or subclasses of the specified
-     * <code>Class</code>.
+     * Return a {@code Set} of Principals associated with this
+     * {@code Subject} that are instances or subclasses of the specified
+     * {@code Class}.
      *
-     * <p> The returned <code>Set</code> is not backed by this Subject's
-     * internal <code>Principal</code> <code>Set</code>.  A new
-     * <code>Set</code> is created and returned for each method invocation.
-     * Modifications to the returned <code>Set</code>
-     * will not affect the internal <code>Principal</code> <code>Set</code>.
+     * <p> The returned {@code Set} is not backed by this Subject's
+     * internal {@code Principal} {@code Set}.  A new
+     * {@code Set} is created and returned for each method invocation.
+     * Modifications to the returned {@code Set}
+     * will not affect the internal {@code Principal} {@code Set}.
      *
      * <p>
      *
-     * @param c the returned <code>Set</code> of Principals will all be
+     * @param <T> the type of the class modeled by {@code c}
+     *
+     * @param c the returned {@code Set} of Principals will all be
      *          instances of this class.
      *
-     * @return a <code>Set</code> of Principals that are instances of the
-     *          specified <code>Class</code>.
+     * @return a {@code Set} of Principals that are instances of the
+     *          specified {@code Class}.
      *
-     * @exception NullPointerException if the specified <code>Class</code>
-     *                  is <code>null</code>.
+     * @exception NullPointerException if the specified {@code Class}
+     *                  is {@code null}.
      */
     public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
 
@@ -611,18 +625,18 @@
     }
 
     /**
-     * Return the <code>Set</code> of public credentials held by this
-     * <code>Subject</code>.
+     * Return the {@code Set} of public credentials held by this
+     * {@code Subject}.
      *
-     * <p> The returned <code>Set</code> is backed by this Subject's
-     * internal public Credential <code>Set</code>.  Any modification
-     * to the returned <code>Set</code> affects the internal public
-     * Credential <code>Set</code> as well.
+     * <p> The returned {@code Set} is backed by this Subject's
+     * internal public Credential {@code Set}.  Any modification
+     * to the returned {@code Set} affects the internal public
+     * Credential {@code Set} as well.
      *
      * <p>
      *
-     * @return  A <code>Set</code> of public credentials held by this
-     *          <code>Subject</code>.
+     * @return  A {@code Set} of public credentials held by this
+     *          {@code Subject}.
      */
     public Set<Object> getPublicCredentials() {
 
@@ -632,29 +646,29 @@
     }
 
     /**
-     * Return the <code>Set</code> of private credentials held by this
-     * <code>Subject</code>.
+     * Return the {@code Set} of private credentials held by this
+     * {@code Subject}.
      *
-     * <p> The returned <code>Set</code> is backed by this Subject's
-     * internal private Credential <code>Set</code>.  Any modification
-     * to the returned <code>Set</code> affects the internal private
-     * Credential <code>Set</code> as well.
+     * <p> The returned {@code Set} is backed by this Subject's
+     * internal private Credential {@code Set}.  Any modification
+     * to the returned {@code Set} affects the internal private
+     * Credential {@code Set} as well.
      *
      * <p> A caller requires permissions to access the Credentials
-     * in the returned <code>Set</code>, or to modify the
-     * <code>Set</code> itself.  A <code>SecurityException</code>
+     * in the returned {@code Set}, or to modify the
+     * {@code Set} itself.  A {@code SecurityException}
      * is thrown if the caller does not have the proper permissions.
      *
-     * <p> While iterating through the <code>Set</code>,
-     * a <code>SecurityException</code> is thrown
+     * <p> While iterating through the {@code Set},
+     * a {@code SecurityException} is thrown
      * if the caller does not have permission to access a
-     * particular Credential.  The <code>Iterator</code>
-     * is nevertheless advanced to next element in the <code>Set</code>.
+     * particular Credential.  The {@code Iterator}
+     * is nevertheless advanced to next element in the {@code Set}.
      *
      * <p>
      *
-     * @return  A <code>Set</code> of private credentials held by this
-     *          <code>Subject</code>.
+     * @return  A {@code Set} of private credentials held by this
+     *          {@code Subject}.
      */
     public Set<Object> getPrivateCredentials() {
 
@@ -672,26 +686,28 @@
     }
 
     /**
-     * Return a <code>Set</code> of public credentials associated with this
-     * <code>Subject</code> that are instances or subclasses of the specified
-     * <code>Class</code>.
+     * Return a {@code Set} of public credentials associated with this
+     * {@code Subject} that are instances or subclasses of the specified
+     * {@code Class}.
      *
-     * <p> The returned <code>Set</code> is not backed by this Subject's
-     * internal public Credential <code>Set</code>.  A new
-     * <code>Set</code> is created and returned for each method invocation.
-     * Modifications to the returned <code>Set</code>
-     * will not affect the internal public Credential <code>Set</code>.
+     * <p> The returned {@code Set} is not backed by this Subject's
+     * internal public Credential {@code Set}.  A new
+     * {@code Set} is created and returned for each method invocation.
+     * Modifications to the returned {@code Set}
+     * will not affect the internal public Credential {@code Set}.
      *
      * <p>
      *
-     * @param c the returned <code>Set</code> of public credentials will all be
+     * @param <T> the type of the class modeled by {@code c}
+     *
+     * @param c the returned {@code Set} of public credentials will all be
      *          instances of this class.
      *
-     * @return a <code>Set</code> of public credentials that are instances
-     *          of the  specified <code>Class</code>.
+     * @return a {@code Set} of public credentials that are instances
+     *          of the  specified {@code Class}.
      *
-     * @exception NullPointerException if the specified <code>Class</code>
-     *          is <code>null</code>.
+     * @exception NullPointerException if the specified {@code Class}
+     *          is {@code null}.
      */
     public <T> Set<T> getPublicCredentials(Class<T> c) {
 
@@ -705,30 +721,32 @@
     }
 
     /**
-     * Return a <code>Set</code> of private credentials associated with this
-     * <code>Subject</code> that are instances or subclasses of the specified
-     * <code>Class</code>.
+     * Return a {@code Set} of private credentials associated with this
+     * {@code Subject} that are instances or subclasses of the specified
+     * {@code Class}.
      *
      * <p> The caller must have permission to access all of the
-     * requested Credentials, or a <code>SecurityException</code>
+     * requested Credentials, or a {@code SecurityException}
      * will be thrown.
      *
-     * <p> The returned <code>Set</code> is not backed by this Subject's
-     * internal private Credential <code>Set</code>.  A new
-     * <code>Set</code> is created and returned for each method invocation.
-     * Modifications to the returned <code>Set</code>
-     * will not affect the internal private Credential <code>Set</code>.
+     * <p> The returned {@code Set} is not backed by this Subject's
+     * internal private Credential {@code Set}.  A new
+     * {@code Set} is created and returned for each method invocation.
+     * Modifications to the returned {@code Set}
+     * will not affect the internal private Credential {@code Set}.
      *
      * <p>
      *
-     * @param c the returned <code>Set</code> of private credentials will all be
+     * @param <T> the type of the class modeled by {@code c}
+     *
+     * @param c the returned {@code Set} of private credentials will all be
      *          instances of this class.
      *
-     * @return a <code>Set</code> of private credentials that are instances
-     *          of the  specified <code>Class</code>.
+     * @return a {@code Set} of private credentials that are instances
+     *          of the  specified {@code Class}.
      *
-     * @exception NullPointerException if the specified <code>Class</code>
-     *          is <code>null</code>.
+     * @exception NullPointerException if the specified {@code Class}
+     *          is {@code null}.
      */
     public <T> Set<T> getPrivateCredentials(Class<T> c) {
 
@@ -750,25 +768,25 @@
     }
 
     /**
-     * Compares the specified Object with this <code>Subject</code>
+     * Compares the specified Object with this {@code Subject}
      * for equality.  Returns true if the given object is also a Subject
-     * and the two <code>Subject</code> instances are equivalent.
-     * More formally, two <code>Subject</code> instances are
-     * equal if their <code>Principal</code> and <code>Credential</code>
+     * and the two {@code Subject} instances are equivalent.
+     * More formally, two {@code Subject} instances are
+     * equal if their {@code Principal} and {@code Credential}
      * Sets are equal.
      *
      * <p>
      *
      * @param o Object to be compared for equality with this
-     *          <code>Subject</code>.
+     *          {@code Subject}.
      *
      * @return true if the specified Object is equal to this
-     *          <code>Subject</code>.
+     *          {@code Subject}.
      *
      * @exception SecurityException if the caller does not have permission
-     *          to access the private credentials for this <code>Subject</code>,
+     *          to access the private credentials for this {@code Subject},
      *          or if the caller does not have permission to access the
-     *          private credentials for the provided <code>Subject</code>.
+     *          private credentials for the provided {@code Subject}.
      */
     public boolean equals(Object o) {
 
@@ -815,11 +833,11 @@
     }
 
     /**
-     * Return the String representation of this <code>Subject</code>.
+     * Return the String representation of this {@code Subject}.
      *
      * <p>
      *
-     * @return the String representation of this <code>Subject</code>.
+     * @return the String representation of this {@code Subject}.
      */
     public String toString() {
         return toString(true);
@@ -876,11 +894,11 @@
     }
 
     /**
-     * Returns a hashcode for this <code>Subject</code>.
+     * Returns a hashcode for this {@code Subject}.
      *
      * <p>
      *
-     * @return a hashcode for this <code>Subject</code>.
+     * @return a hashcode for this {@code Subject}.
      *
      * @exception SecurityException if the caller does not have permission
      *          to access this Subject's private credentials.
@@ -892,10 +910,10 @@
          * hashcodes of this Subject's Principals and credentials.
          *
          * If a particular credential was destroyed
-         * (<code>credential.hashCode()</code> throws an
-         * <code>IllegalStateException</code>),
+         * ({@code credential.hashCode()} throws an
+         * {@code IllegalStateException}),
          * the hashcode for that credential is derived via:
-         * <code>credential.getClass().toString().hashCode()</code>.
+         * {@code credential.getClass().toString().hashCode()}.
          */
 
         int hashCode = 0;
@@ -941,12 +959,32 @@
     /**
      * Reads this object from a stream (i.e., deserializes it)
      */
+    @SuppressWarnings("unchecked")
     private void readObject(java.io.ObjectInputStream s)
                 throws java.io.IOException, ClassNotFoundException {
 
-        s.defaultReadObject();
+        ObjectInputStream.GetField gf = s.readFields();
 
-        // The Credential <code>Set</code> is not serialized, but we do not
+        readOnly = gf.get("readOnly", false);
+
+        Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
+
+        // Rewrap the principals into a SecureSet
+        if (inputPrincs == null) {
+            throw new NullPointerException
+                (ResourcesMgr.getString("invalid.null.input.s."));
+        }
+        try {
+            principals = Collections.synchronizedSet(new SecureSet<Principal>
+                                (this, PRINCIPAL_SET, inputPrincs));
+        } catch (NullPointerException npe) {
+            // Sometimes people deserialize the principals set only.
+            // Subject is not accessible, so just don't fail.
+            principals = Collections.synchronizedSet
+                        (new SecureSet<Principal>(this, PRINCIPAL_SET));
+        }
+
+        // The Credential {@code Set} is not serialized, but we do not
         // want the default deserialization routine to set it to null.
         this.pubCredentials = Collections.synchronizedSet
                         (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));
@@ -980,13 +1018,13 @@
 
         /**
          * @serial An integer identifying the type of objects contained
-         *      in this set.  If <code>which == 1</code>,
+         *      in this set.  If {@code which == 1},
          *      this is a Principal set and all the elements are
-         *      of type <code>java.security.Principal</code>.
-         *      If <code>which == 2</code>, this is a public credential
-         *      set and all the elements are of type <code>Object</code>.
-         *      If <code>which == 3</code>, this is a private credential
-         *      set and all the elements are of type <code>Object</code>.
+         *      of type {@code java.security.Principal}.
+         *      If {@code which == 2}, this is a public credential
+         *      set and all the elements are of type {@code Object}.
+         *      If {@code which == 3}, this is a private credential
+         *      set and all the elements are of type {@code Object}.
          */
         private int which;
 
@@ -1168,7 +1206,7 @@
         }
 
         public boolean removeAll(Collection<?> c) {
-
+            Objects.requireNonNull(c);
             boolean modified = false;
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
@@ -1204,7 +1242,7 @@
         }
 
         public boolean retainAll(Collection<?> c) {
-
+            Objects.requireNonNull(c);
             boolean modified = false;
             boolean retain = false;
             final Iterator<E> e = iterator();
@@ -1291,18 +1329,25 @@
             oos.writeFields();
         }
 
+        @SuppressWarnings("unchecked")
         private void readObject(ObjectInputStream ois)
             throws IOException, ClassNotFoundException
         {
             ObjectInputStream.GetField fields = ois.readFields();
             subject = (Subject) fields.get("this$0", null);
-            elements = (LinkedList<E>) fields.get("elements", null);
             which = fields.get("which", 0);
+
+            LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
+            if (tmp.getClass() != LinkedList.class) {
+                elements = new LinkedList<E>(tmp);
+            } else {
+                elements = tmp;
+            }
         }
     }
 
     /**
-     * This class implements a <code>Set</code> which returns only
+     * This class implements a {@code Set} which returns only
      * members that are an instance of a specified Class.
      */
     private class ClassSet<T> extends AbstractSet<T> {
@@ -1329,6 +1374,7 @@
             }
         }
 
+        @SuppressWarnings("unchecked")     /*To suppress warning from line 1374*/
         private void populateSet() {
             final Iterator<?> iterator;
             switch(which) {
diff --git a/ojluni/src/main/java/sun/invoke/util/VerifyAccess.java b/ojluni/src/main/java/sun/invoke/util/VerifyAccess.java
new file mode 100644
index 0000000..d2e5820
--- /dev/null
+++ b/ojluni/src/main/java/sun/invoke/util/VerifyAccess.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.reflect.Modifier;
+import static java.lang.reflect.Modifier.*;
+import sun.reflect.Reflection;
+
+/**
+ * This class centralizes information about the JVM's linkage access control.
+ * @author jrose
+ */
+public class VerifyAccess {
+
+    private VerifyAccess() { }  // cannot instantiate
+
+    private static final int PACKAGE_ONLY = 0;
+    private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
+    private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
+    private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
+    private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+    /**
+     * Evaluate the JVM linkage rules for access to the given method
+     * on behalf of a caller class which proposes to perform the access.
+     * Return true if the caller class has privileges to invoke a method
+     * or access a field with the given properties.
+     * This requires an accessibility check of the referencing class,
+     * plus an accessibility check of the member within the class,
+     * which depends on the member's modifier flags.
+     * <p>
+     * The relevant properties include the defining class ({@code defc})
+     * of the member, and its modifier flags ({@code mods}).
+     * Also relevant is the class used to make the initial symbolic reference
+     * to the member ({@code refc}).  If this latter class is not distinguished,
+     * the defining class should be passed for both arguments ({@code defc == refc}).
+     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+     * A field or method R is accessible to a class or interface D if
+     * and only if any of the following conditions is true:<ul>
+     * <li>R is public.
+     * <li>R is protected and is declared in a class C, and D is either
+     *     a subclass of C or C itself.  Furthermore, if R is not
+     *     static, then the symbolic reference to R must contain a
+     *     symbolic reference to a class T, such that T is either a
+     *     subclass of D, a superclass of D or D itself.
+     * <li>R is either protected or has default access (that is,
+     *     neither public nor protected nor private), and is declared
+     *     by a class in the same runtime package as D.
+     * <li>R is private and is declared in D.
+     * </ul>
+     * This discussion of access control omits a related restriction
+     * on the target of a protected field access or method invocation
+     * (the target must be of class D or a subtype of D). That
+     * requirement is checked as part of the verification process
+     * (5.4.1); it is not part of link-time access control.
+     * @param refc the class used in the symbolic reference to the proposed member
+     * @param defc the class in which the proposed member is actually defined
+     * @param mods modifier flags for the proposed member
+     * @param lookupClass the class for which the access check is being made
+     * @return true iff the the accessing class can access such a member
+     */
+    public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
+                                             Class<?> defc,  // actual def class
+                                             int      mods,  // actual member mods
+                                             Class<?> lookupClass,
+                                             int      allowedModes) {
+        if (allowedModes == 0)  return false;
+        assert((allowedModes & PUBLIC) != 0 &&
+               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
+        // The symbolic reference class (refc) must always be fully verified.
+        if (!isClassAccessible(refc, lookupClass, allowedModes)) {
+            return false;
+        }
+        // Usually refc and defc are the same, but verify defc also in case they differ.
+        if (defc == lookupClass &&
+            (allowedModes & PRIVATE) != 0)
+            return true;        // easy check; all self-access is OK
+        switch (mods & ALL_ACCESS_MODES) {
+        case PUBLIC:
+            return true;  // already checked above
+        case PROTECTED:
+            assert !defc.isInterface(); // protected members aren't allowed in interfaces
+            if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
+                isSamePackage(defc, lookupClass))
+                return true;
+            if ((allowedModes & PROTECTED) == 0)
+                return false;
+            // Protected members are accessible by subclasses, which does not include interfaces.
+            // Interfaces are types, not classes. They should not have access to
+            // protected members in j.l.Object, even though it is their superclass.
+            if ((mods & STATIC) != 0 &&
+                !isRelatedClass(refc, lookupClass))
+                return false;
+            if ((allowedModes & PROTECTED) != 0 &&
+                isSubClass(lookupClass, defc))
+                return true;
+            return false;
+        case PACKAGE_ONLY:  // That is, zero.  Unmarked member is package-only access.
+            assert !defc.isInterface(); // package-private members aren't allowed in interfaces
+            return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
+                    isSamePackage(defc, lookupClass));
+        case PRIVATE:
+            // Loosened rules for privates follows access rules for inner classes.
+            return (ALLOW_NESTMATE_ACCESS &&
+                    (allowedModes & PRIVATE) != 0 &&
+                    isSamePackageMember(defc, lookupClass));
+        default:
+            throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
+        }
+    }
+
+    static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
+        return (refc == lookupClass ||
+                isSubClass(refc, lookupClass) ||
+                isSubClass(lookupClass, refc));
+    }
+
+    static boolean isSubClass(Class<?> lookupClass, Class<?> defc) {
+        return defc.isAssignableFrom(lookupClass) &&
+               !lookupClass.isInterface(); // interfaces are types, not classes.
+    }
+
+    /**
+     * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
+     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+     * A class or interface C is accessible to a class or interface D
+     * if and only if either of the following conditions are true:<ul>
+     * <li>C is public.
+     * <li>C and D are members of the same runtime package.
+     * </ul>
+     * @param refc the symbolic reference class to which access is being checked (C)
+     * @param lookupClass the class performing the lookup (D)
+     */
+    public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
+                                            int allowedModes) {
+        if (allowedModes == 0)  return false;
+        // Android-changed: Use public APIs to figure out whether a class
+        // is public or not.
+        if (Modifier.isPublic(refc.getModifiers()))
+            return true;
+        if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
+            isSamePackage(lookupClass, refc))
+            return true;
+        return false;
+    }
+
+    /**
+     * Decide if the given method type, attributed to a member or symbolic
+     * reference of a given reference class, is really visible to that class.
+     * @param type the supposed type of a member or symbolic reference of refc
+     * @param refc the class attempting to make the reference
+     */
+    public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
+        if (type == refc)  return true;  // easy check
+        while (type.isArray())  type = type.getComponentType();
+        if (type.isPrimitive() || type == Object.class)  return true;
+        ClassLoader parent = type.getClassLoader();
+        if (parent == null)  return true;
+        ClassLoader child  = refc.getClassLoader();
+        if (child == null)  return false;
+        if (parent == child || loadersAreRelated(parent, child, true))
+            return true;
+        // Do it the hard way:  Look up the type name from the refc loader.
+        try {
+            Class<?> res = child.loadClass(type.getName());
+            return (type == res);
+        } catch (ClassNotFoundException ex) {
+            return false;
+        }
+    }
+
+    /**
+     * Decide if the given method type, attributed to a member or symbolic
+     * reference of a given reference class, is really visible to that class.
+     * @param type the supposed type of a member or symbolic reference of refc
+     * @param refc the class attempting to make the reference
+     */
+    public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
+        for (int n = -1, max = type.parameterCount(); n < max; n++) {
+            Class<?> ptype = (n < 0 ? type.returnType() : type.parameterType(n));
+            if (!isTypeVisible(ptype, refc))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Test if two classes have the same class loader and package qualifier.
+     * @param class1 a class
+     * @param class2 another class
+     * @return whether they are in the same package
+     */
+    public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+        // Android-changed: Throw IAE (instead of asserting) if called with array classes.
+        if (class1.isArray() || class2.isArray()) {
+            throw new IllegalArgumentException();
+        }
+
+        if (class1 == class2)
+            return true;
+        if (class1.getClassLoader() != class2.getClassLoader())
+            return false;
+        String name1 = class1.getName(), name2 = class2.getName();
+        int dot = name1.lastIndexOf('.');
+        if (dot != name2.lastIndexOf('.'))
+            return false;
+        for (int i = 0; i < dot; i++) {
+            if (name1.charAt(i) != name2.charAt(i))
+                return false;
+        }
+        return true;
+    }
+
+    /** Return the package name for this class.
+     */
+    public static String getPackageName(Class<?> cls) {
+        assert(!cls.isArray());
+        String name = cls.getName();
+        int dot = name.lastIndexOf('.');
+        if (dot < 0)  return "";
+        return name.substring(0, dot);
+    }
+
+    /**
+     * Test if two classes are defined as part of the same package member (top-level class).
+     * If this is true, they can share private access with each other.
+     * @param class1 a class
+     * @param class2 another class
+     * @return whether they are identical or nested together
+     */
+    public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
+        if (class1 == class2)
+            return true;
+        if (!isSamePackage(class1, class2))
+            return false;
+        if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
+            return false;
+        return true;
+    }
+
+    private static Class<?> getOutermostEnclosingClass(Class<?> c) {
+        Class<?> pkgmem = c;
+        for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
+            pkgmem = enc;
+        return pkgmem;
+    }
+
+    private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
+                                             boolean loader1MustBeParent) {
+        if (loader1 == loader2 || loader1 == null
+                || (loader2 == null && !loader1MustBeParent)) {
+            return true;
+        }
+        for (ClassLoader scan2 = loader2;
+                scan2 != null; scan2 = scan2.getParent()) {
+            if (scan2 == loader1)  return true;
+        }
+        if (loader1MustBeParent)  return false;
+        // see if loader2 is a parent of loader1:
+        for (ClassLoader scan1 = loader1;
+                scan1 != null; scan1 = scan1.getParent()) {
+            if (scan1 == loader2)  return true;
+        }
+        return false;
+    }
+
+    /**
+     * Is the class loader of parentClass identical to, or an ancestor of,
+     * the class loader of childClass?
+     * @param parentClass a class
+     * @param childClass another class, which may be a descendent of the first class
+     * @return whether parentClass precedes or equals childClass in class loader order
+     */
+    public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
+        return loadersAreRelated(parentClass.getClassLoader(), childClass.getClassLoader(), true);
+    }
+}
diff --git a/ojluni/src/main/java/sun/misc/IoTrace.java b/ojluni/src/main/java/sun/misc/IoTrace.java
deleted file mode 100644
index ab15ed1..0000000
--- a/ojluni/src/main/java/sun/misc/IoTrace.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.misc;
-
-import java.net.InetAddress;
-
-/**
- * Utility class used to identify trace points for I/O calls.
- * <p>
- * To use this class, a diagnostic tool must redefine this class with a version
- * that contains calls to the the diagnostic tool. This implementation will then
- * receive callbacks when file and socket operations are performed. The reason
- * for requiring a redefine of the class is to avoid any overhead caused by the
- * instrumentation.
- * <p>
- * The xxBegin() methods return a "context". This can be any Object. This
- * context will be passed to the corresponding xxEnd() method. This way, an
- * implementation can correlate the beginning of an operation with the end.
- * <p>
- * It is possible for a xxEnd() method to be called with a null handle. This
- * happens if tracing was started between the call to xxBegin() and xxEnd(), in
- * which case xxBegin() would not have been called. It is the implementation's
- * responsibility to not throw an exception in this case.
- * <p>
- * Only blocking I/O operations are identified with this facility.
- * <p>
- * <b>Warning</b>
- * <p>
- * These methods are called from sensitive points in the I/O subsystem. Great
- * care must be taken to not interfere with ongoing operations or cause
- * deadlocks. In particular:
- * <ul>
- * <li>Implementations must not throw exceptions since this will cause
- * disruptions to the I/O operations.
- * <li>Implementations must not do I/O operations since this will lead to an
- * endless loop.
- * <li>Since the hooks may be called while holding low-level locks in the I/O
- * subsystem, implementations must be careful with synchronization or
- * interaction with other threads to avoid deadlocks in the VM.
- * </ul>
- */
-public final class IoTrace {
-    private IoTrace() {
-    }
-
-    /**
-     * Called before data is read from a socket.
-     *
-     * @return a context object
-     */
-    public static Object socketReadBegin() {
-        return null;
-    }
-
-    /**
-     * Called after data is read from the socket.
-     *
-     * @param context
-     *            the context returned by the previous call to socketReadBegin()
-     * @param address
-     *            the remote address the socket is bound to
-     * @param port
-     *            the remote port the socket is bound to
-     * @param timeout
-     *            the SO_TIMEOUT value of the socket (in milliseconds) or 0 if
-     *            there is no timeout set
-     * @param bytesRead
-     *            the number of bytes read from the socket, 0 if there was an
-     *            error reading from the socket
-     */
-    public static void socketReadEnd(Object context, InetAddress address, int port,
-                                     int timeout, long bytesRead) {
-    }
-
-    /**
-     * Called before data is written to a socket.
-     *
-     * @return a context object
-     */
-    public static Object socketWriteBegin() {
-        return null;
-    }
-
-    /**
-     * Called after data is written to a socket.
-     *
-     * @param context
-     *            the context returned by the previous call to
-     *            socketWriteBegin()
-     * @param address
-     *            the remote address the socket is bound to
-     * @param port
-     *            the remote port the socket is bound to
-     * @param bytesWritten
-     *            the number of bytes written to the socket, 0 if there was an
-     *            error writing to the socket
-     */
-    public static void socketWriteEnd(Object context, InetAddress address, int port,
-                                      long bytesWritten) {
-    }
-
-    /**
-     * Called before data is read from a file.
-     *
-     * @param path
-     *            the path of the file
-     * @return a context object
-     */
-    public static Object fileReadBegin(String path) {
-        return null;
-    }
-
-    /**
-     * Called after data is read from a file.
-     *
-     * @param context
-     *            the context returned by the previous call to fileReadBegin()
-     * @param bytesRead
-     *            the number of bytes written to the file, 0 if there was an
-     *            error writing to the file
-     */
-    public static void fileReadEnd(Object context, long bytesRead) {
-    }
-
-    /**
-     * Called before data is written to a file.
-     *
-     * @param path
-     *            the path of the file
-     * @return a context object
-     */
-    public static Object fileWriteBegin(String path) {
-        return null;
-    }
-
-    /**
-     * Called after data is written to a file.
-     *
-     * @param context
-     *            the context returned by the previous call to fileReadBegin()
-     * @param bytesWritten
-     *            the number of bytes written to the file, 0 if there was an
-     *            error writing to the file
-     */
-    public static void fileWriteEnd(Object context, long bytesWritten) {
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/util/ManifestEntryVerifier.java b/ojluni/src/main/java/sun/security/util/ManifestEntryVerifier.java
index 3d1b473..8e0169e 100644
--- a/ojluni/src/main/java/sun/security/util/ManifestEntryVerifier.java
+++ b/ojluni/src/main/java/sun/security/util/ManifestEntryVerifier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
 import java.util.*;
 import java.util.jar.*;
 
-import sun.misc.BASE64Decoder;
+import java.util.Base64;
 
 import sun.security.jca.Providers;
 
@@ -63,7 +63,6 @@
     /** the manifest hashes for the digests in use */
     ArrayList<byte[]> manifestHashes;
 
-    private BASE64Decoder decoder = null;
     private String name = null;
     private Manifest man;
 
@@ -81,7 +80,6 @@
         createdDigests = new HashMap<String, MessageDigest>(11);
         digests = new ArrayList<MessageDigest>();
         manifestHashes = new ArrayList<byte[]>();
-        decoder = new BASE64Decoder();
         this.man = man;
     }
 
@@ -147,7 +145,7 @@
                     digest.reset();
                     digests.add(digest);
                     manifestHashes.add(
-                                decoder.decodeBuffer((String)se.getValue()));
+                                Base64.getMimeDecoder().decode((String)se.getValue()));
                 }
             }
         }
diff --git a/ojluni/src/main/java/sun/security/util/Resources.java b/ojluni/src/main/java/sun/security/util/Resources.java
index 299facc..286acc9 100644
--- a/ojluni/src/main/java/sun/security/util/Resources.java
+++ b/ojluni/src/main/java/sun/security/util/Resources.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,509 +34,6 @@
 
     private static final Object[][] contents = {
 
-        // shared (from jarsigner)
-        {"SPACE", " "},
-        {"2SPACE", "  "},
-        {"6SPACE", "      "},
-        {"COMMA", ", "},
-        // shared (from keytool)
-        {"NEWLINE", "\n"},
-        {"STAR",
-                "*******************************************"},
-        {"STARNN",
-                "*******************************************\n\n"},
-
-        // keytool: Help part
-        {".OPTION.", " [OPTION]..."},
-        {"Options.", "Options:"},
-        {"Use.keytool.help.for.all.available.commands",
-                 "Use \"keytool -help\" for all available commands"},
-        {"Key.and.Certificate.Management.Tool",
-                 "Key and Certificate Management Tool"},
-        {"Commands.", "Commands:"},
-        {"Use.keytool.command.name.help.for.usage.of.command.name",
-                "Use \"keytool -command_name -help\" for usage of command_name"},
-        // keytool: help: commands
-        {"Generates.a.certificate.request",
-                "Generates a certificate request"}, //-certreq
-        {"Changes.an.entry.s.alias",
-                "Changes an entry's alias"}, //-changealias
-        {"Deletes.an.entry",
-                "Deletes an entry"}, //-delete
-        {"Exports.certificate",
-                "Exports certificate"}, //-exportcert
-        {"Generates.a.key.pair",
-                "Generates a key pair"}, //-genkeypair
-        {"Generates.a.secret.key",
-                "Generates a secret key"}, //-genseckey
-        {"Generates.certificate.from.a.certificate.request",
-                "Generates certificate from a certificate request"}, //-gencert
-        {"Generates.CRL", "Generates CRL"}, //-gencrl
-        {"Imports.entries.from.a.JDK.1.1.x.style.identity.database",
-                "Imports entries from a JDK 1.1.x-style identity database"}, //-identitydb
-        {"Imports.a.certificate.or.a.certificate.chain",
-                "Imports a certificate or a certificate chain"}, //-importcert
-        {"Imports.one.or.all.entries.from.another.keystore",
-                "Imports one or all entries from another keystore"}, //-importkeystore
-        {"Clones.a.key.entry",
-                "Clones a key entry"}, //-keyclone
-        {"Changes.the.key.password.of.an.entry",
-                "Changes the key password of an entry"}, //-keypasswd
-        {"Lists.entries.in.a.keystore",
-                "Lists entries in a keystore"}, //-list
-        {"Prints.the.content.of.a.certificate",
-                "Prints the content of a certificate"}, //-printcert
-        {"Prints.the.content.of.a.certificate.request",
-                "Prints the content of a certificate request"}, //-printcertreq
-        {"Prints.the.content.of.a.CRL.file",
-                "Prints the content of a CRL file"}, //-printcrl
-        {"Generates.a.self.signed.certificate",
-                "Generates a self-signed certificate"}, //-selfcert
-        {"Changes.the.store.password.of.a.keystore",
-                "Changes the store password of a keystore"}, //-storepasswd
-        // keytool: help: options
-        {"alias.name.of.the.entry.to.process",
-                "alias name of the entry to process"}, //-alias
-        {"destination.alias",
-                "destination alias"}, //-destalias
-        {"destination.key.password",
-                "destination key password"}, //-destkeypass
-        {"destination.keystore.name",
-                "destination keystore name"}, //-destkeystore
-        {"destination.keystore.password.protected",
-                "destination keystore password protected"}, //-destprotected
-        {"destination.keystore.provider.name",
-                "destination keystore provider name"}, //-destprovidername
-        {"destination.keystore.password",
-                "destination keystore password"}, //-deststorepass
-        {"destination.keystore.type",
-                "destination keystore type"}, //-deststoretype
-        {"distinguished.name",
-                "distinguished name"}, //-dname
-        {"X.509.extension",
-                "X.509 extension"}, //-ext
-        {"output.file.name",
-                "output file name"}, //-file and -outfile
-        {"input.file.name",
-                "input file name"}, //-file and -infile
-        {"key.algorithm.name",
-                "key algorithm name"}, //-keyalg
-        {"key.password",
-                "key password"}, //-keypass
-        {"key.bit.size",
-                "key bit size"}, //-keysize
-        {"keystore.name",
-                "keystore name"}, //-keystore
-        {"new.password",
-                "new password"}, //-new
-        {"do.not.prompt",
-                "do not prompt"}, //-noprompt
-        {"password.through.protected.mechanism",
-                "password through protected mechanism"}, //-protected
-        {"provider.argument",
-                "provider argument"}, //-providerarg
-        {"provider.class.name",
-                "provider class name"}, //-providerclass
-        {"provider.name",
-                "provider name"}, //-providername
-        {"provider.classpath",
-                "provider classpath"}, //-providerpath
-        {"output.in.RFC.style",
-                "output in RFC style"}, //-rfc
-        {"signature.algorithm.name",
-                "signature algorithm name"}, //-sigalg
-        {"source.alias",
-                "source alias"}, //-srcalias
-        {"source.key.password",
-                "source key password"}, //-srckeypass
-        {"source.keystore.name",
-                "source keystore name"}, //-srckeystore
-        {"source.keystore.password.protected",
-                "source keystore password protected"}, //-srcprotected
-        {"source.keystore.provider.name",
-                "source keystore provider name"}, //-srcprovidername
-        {"source.keystore.password",
-                "source keystore password"}, //-srcstorepass
-        {"source.keystore.type",
-                "source keystore type"}, //-srcstoretype
-        {"SSL.server.host.and.port",
-                "SSL server host and port"}, //-sslserver
-        {"signed.jar.file",
-                "signed jar file"}, //=jarfile
-        {"certificate.validity.start.date.time",
-                "certificate validity start date/time"}, //-startdate
-        {"keystore.password",
-                "keystore password"}, //-storepass
-        {"keystore.type",
-                "keystore type"}, //-storetype
-        {"trust.certificates.from.cacerts",
-                "trust certificates from cacerts"}, //-trustcacerts
-        {"verbose.output",
-                "verbose output"}, //-v
-        {"validity.number.of.days",
-                "validity number of days"}, //-validity
-        {"Serial.ID.of.cert.to.revoke",
-                 "Serial ID of cert to revoke"}, //-id
-        // keytool: Running part
-        {"keytool.error.", "keytool error: "},
-        {"Illegal.option.", "Illegal option:  "},
-        {"Illegal.value.", "Illegal value: "},
-        {"Unknown.password.type.", "Unknown password type: "},
-        {"Cannot.find.environment.variable.",
-                "Cannot find environment variable: "},
-        {"Cannot.find.file.", "Cannot find file: "},
-        {"Command.option.flag.needs.an.argument.", "Command option {0} needs an argument."},
-        {"Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value.",
-                "Warning:  Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified {0} value."},
-        {".keystore.must.be.NONE.if.storetype.is.{0}",
-                "-keystore must be NONE if -storetype is {0}"},
-        {"Too.many.retries.program.terminated",
-                 "Too many retries, program terminated"},
-        {".storepasswd.and.keypasswd.commands.not.supported.if.storetype.is.{0}",
-                "-storepasswd and -keypasswd commands not supported if -storetype is {0}"},
-        {".keypasswd.commands.not.supported.if.storetype.is.PKCS12",
-                "-keypasswd commands not supported if -storetype is PKCS12"},
-        {".keypass.and.new.can.not.be.specified.if.storetype.is.{0}",
-                "-keypass and -new can not be specified if -storetype is {0}"},
-        {"if.protected.is.specified.then.storepass.keypass.and.new.must.not.be.specified",
-                "if -protected is specified, then -storepass, -keypass, and -new must not be specified"},
-        {"if.srcprotected.is.specified.then.srcstorepass.and.srckeypass.must.not.be.specified",
-                "if -srcprotected is specified, then -srcstorepass and -srckeypass must not be specified"},
-        {"if.keystore.is.not.password.protected.then.storepass.keypass.and.new.must.not.be.specified",
-                "if keystore is not password protected, then -storepass, -keypass, and -new must not be specified"},
-        {"if.source.keystore.is.not.password.protected.then.srcstorepass.and.srckeypass.must.not.be.specified",
-                "if source keystore is not password protected, then -srcstorepass and -srckeypass must not be specified"},
-        {"Illegal.startdate.value", "Illegal startdate value"},
-        {"Validity.must.be.greater.than.zero",
-                "Validity must be greater than zero"},
-        {"provName.not.a.provider", "{0} not a provider"},
-        {"Usage.error.no.command.provided", "Usage error: no command provided"},
-        {"Source.keystore.file.exists.but.is.empty.", "Source keystore file exists, but is empty: "},
-        {"Please.specify.srckeystore", "Please specify -srckeystore"},
-        {"Must.not.specify.both.v.and.rfc.with.list.command",
-                "Must not specify both -v and -rfc with 'list' command"},
-        {"Key.password.must.be.at.least.6.characters",
-                "Key password must be at least 6 characters"},
-        {"New.password.must.be.at.least.6.characters",
-                "New password must be at least 6 characters"},
-        {"Keystore.file.exists.but.is.empty.",
-                "Keystore file exists, but is empty: "},
-        {"Keystore.file.does.not.exist.",
-                "Keystore file does not exist: "},
-        {"Must.specify.destination.alias", "Must specify destination alias"},
-        {"Must.specify.alias", "Must specify alias"},
-        {"Keystore.password.must.be.at.least.6.characters",
-                "Keystore password must be at least 6 characters"},
-        {"Enter.keystore.password.", "Enter keystore password:  "},
-        {"Enter.source.keystore.password.", "Enter source keystore password:  "},
-        {"Enter.destination.keystore.password.", "Enter destination keystore password:  "},
-        {"Keystore.password.is.too.short.must.be.at.least.6.characters",
-         "Keystore password is too short - must be at least 6 characters"},
-        {"Unknown.Entry.Type", "Unknown Entry Type"},
-        {"Too.many.failures.Alias.not.changed", "Too many failures. Alias not changed"},
-        {"Entry.for.alias.alias.successfully.imported.",
-                 "Entry for alias {0} successfully imported."},
-        {"Entry.for.alias.alias.not.imported.", "Entry for alias {0} not imported."},
-        {"Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported.",
-                 "Problem importing entry for alias {0}: {1}.\nEntry for alias {0} not imported."},
-        {"Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled",
-                 "Import command completed:  {0} entries successfully imported, {1} entries failed or cancelled"},
-        {"Warning.Overwriting.existing.alias.alias.in.destination.keystore",
-                 "Warning: Overwriting existing alias {0} in destination keystore"},
-        {"Existing.entry.alias.alias.exists.overwrite.no.",
-                 "Existing entry alias {0} exists, overwrite? [no]:  "},
-        {"Too.many.failures.try.later", "Too many failures - try later"},
-        {"Certification.request.stored.in.file.filename.",
-                "Certification request stored in file <{0}>"},
-        {"Submit.this.to.your.CA", "Submit this to your CA"},
-        {"if.alias.not.specified.destalias.srckeypass.and.destkeypass.must.not.be.specified",
-            "if alias not specified, destalias, srckeypass, and destkeypass must not be specified"},
-        {"Certificate.stored.in.file.filename.",
-                "Certificate stored in file <{0}>"},
-        {"Certificate.reply.was.installed.in.keystore",
-                "Certificate reply was installed in keystore"},
-        {"Certificate.reply.was.not.installed.in.keystore",
-                "Certificate reply was not installed in keystore"},
-        {"Certificate.was.added.to.keystore",
-                "Certificate was added to keystore"},
-        {"Certificate.was.not.added.to.keystore",
-                "Certificate was not added to keystore"},
-        {".Storing.ksfname.", "[Storing {0}]"},
-        {"alias.has.no.public.key.certificate.",
-                "{0} has no public key (certificate)"},
-        {"Cannot.derive.signature.algorithm",
-                "Cannot derive signature algorithm"},
-        {"Alias.alias.does.not.exist",
-                "Alias <{0}> does not exist"},
-        {"Alias.alias.has.no.certificate",
-                "Alias <{0}> has no certificate"},
-        {"Key.pair.not.generated.alias.alias.already.exists",
-                "Key pair not generated, alias <{0}> already exists"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for",
-                "Generating {0} bit {1} key pair and self-signed certificate ({2}) with a validity of {3} days\n\tfor: {4}"},
-        {"Enter.key.password.for.alias.", "Enter key password for <{0}>"},
-        {".RETURN.if.same.as.keystore.password.",
-                "\t(RETURN if same as keystore password):  "},
-        {"Key.password.is.too.short.must.be.at.least.6.characters",
-                "Key password is too short - must be at least 6 characters"},
-        {"Too.many.failures.key.not.added.to.keystore",
-                "Too many failures - key not added to keystore"},
-        {"Destination.alias.dest.already.exists",
-                "Destination alias <{0}> already exists"},
-        {"Password.is.too.short.must.be.at.least.6.characters",
-                "Password is too short - must be at least 6 characters"},
-        {"Too.many.failures.Key.entry.not.cloned",
-                "Too many failures. Key entry not cloned"},
-        {"key.password.for.alias.", "key password for <{0}>"},
-        {"Keystore.entry.for.id.getName.already.exists",
-                "Keystore entry for <{0}> already exists"},
-        {"Creating.keystore.entry.for.id.getName.",
-                "Creating keystore entry for <{0}> ..."},
-        {"No.entries.from.identity.database.added",
-                "No entries from identity database added"},
-        {"Alias.name.alias", "Alias name: {0}"},
-        {"Creation.date.keyStore.getCreationDate.alias.",
-                "Creation date: {0,date}"},
-        {"alias.keyStore.getCreationDate.alias.",
-                "{0}, {1,date}, "},
-        {"alias.", "{0}, "},
-        {"Entry.type.type.", "Entry type: {0}"},
-        {"Certificate.chain.length.", "Certificate chain length: "},
-        {"Certificate.i.1.", "Certificate[{0,number,integer}]:"},
-        {"Certificate.fingerprint.SHA1.", "Certificate fingerprint (SHA1): "},
-        {"Keystore.type.", "Keystore type: "},
-        {"Keystore.provider.", "Keystore provider: "},
-        {"Your.keystore.contains.keyStore.size.entry",
-                "Your keystore contains {0,number,integer} entry"},
-        {"Your.keystore.contains.keyStore.size.entries",
-                "Your keystore contains {0,number,integer} entries"},
-        {"Failed.to.parse.input", "Failed to parse input"},
-        {"Empty.input", "Empty input"},
-        {"Not.X.509.certificate", "Not X.509 certificate"},
-        {"alias.has.no.public.key", "{0} has no public key"},
-        {"alias.has.no.X.509.certificate", "{0} has no X.509 certificate"},
-        {"New.certificate.self.signed.", "New certificate (self-signed):"},
-        {"Reply.has.no.certificates", "Reply has no certificates"},
-        {"Certificate.not.imported.alias.alias.already.exists",
-                "Certificate not imported, alias <{0}> already exists"},
-        {"Input.not.an.X.509.certificate", "Input not an X.509 certificate"},
-        {"Certificate.already.exists.in.keystore.under.alias.trustalias.",
-                "Certificate already exists in keystore under alias <{0}>"},
-        {"Do.you.still.want.to.add.it.no.",
-                "Do you still want to add it? [no]:  "},
-        {"Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.",
-                "Certificate already exists in system-wide CA keystore under alias <{0}>"},
-        {"Do.you.still.want.to.add.it.to.your.own.keystore.no.",
-                "Do you still want to add it to your own keystore? [no]:  "},
-        {"Trust.this.certificate.no.", "Trust this certificate? [no]:  "},
-        {"YES", "YES"},
-        {"New.prompt.", "New {0}: "},
-        {"Passwords.must.differ", "Passwords must differ"},
-        {"Re.enter.new.prompt.", "Re-enter new {0}: "},
-        {"Re.enter.new.password.", "Re-enter new password: "},
-        {"They.don.t.match.Try.again", "They don't match. Try again"},
-        {"Enter.prompt.alias.name.", "Enter {0} alias name:  "},
-        {"Enter.new.alias.name.RETURN.to.cancel.import.for.this.entry.",
-                 "Enter new alias name\t(RETURN to cancel import for this entry):  "},
-        {"Enter.alias.name.", "Enter alias name:  "},
-        {".RETURN.if.same.as.for.otherAlias.",
-                "\t(RETURN if same as for <{0}>)"},
-        {".PATTERN.printX509Cert",
-                "Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t MD5:  {5}\n\t SHA1: {6}\n\t SHA256: {7}\n\t Signature algorithm name: {8}\n\t Version: {9}"},
-        {"What.is.your.first.and.last.name.",
-                "What is your first and last name?"},
-        {"What.is.the.name.of.your.organizational.unit.",
-                "What is the name of your organizational unit?"},
-        {"What.is.the.name.of.your.organization.",
-                "What is the name of your organization?"},
-        {"What.is.the.name.of.your.City.or.Locality.",
-                "What is the name of your City or Locality?"},
-        {"What.is.the.name.of.your.State.or.Province.",
-                "What is the name of your State or Province?"},
-        {"What.is.the.two.letter.country.code.for.this.unit.",
-                "What is the two-letter country code for this unit?"},
-        {"Is.name.correct.", "Is {0} correct?"},
-        {"no", "no"},
-        {"yes", "yes"},
-        {"y", "y"},
-        {".defaultValue.", "  [{0}]:  "},
-        {"Alias.alias.has.no.key",
-                "Alias <{0}> has no key"},
-        {"Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key",
-                 "Alias <{0}> references an entry type that is not a private key entry.  The -keyclone command only supports cloning of private key entries"},
-
-        {".WARNING.WARNING.WARNING.",
-            "*****************  WARNING WARNING WARNING  *****************"},
-        {"Signer.d.", "Signer #%d:"},
-        {"Timestamp.", "Timestamp:"},
-        {"Signature.", "Signature:"},
-        {"CRLs.", "CRLs:"},
-        {"Certificate.owner.", "Certificate owner: "},
-        {"Not.a.signed.jar.file", "Not a signed jar file"},
-        {"No.certificate.from.the.SSL.server",
-                "No certificate from the SSL server"},
-
-        {".The.integrity.of.the.information.stored.in.your.keystore.",
-            "* The integrity of the information stored in your keystore  *\n" +
-            "* has NOT been verified!  In order to verify its integrity, *\n" +
-            "* you must provide your keystore password.                  *"},
-        {".The.integrity.of.the.information.stored.in.the.srckeystore.",
-            "* The integrity of the information stored in the srckeystore*\n" +
-            "* has NOT been verified!  In order to verify its integrity, *\n" +
-            "* you must provide the srckeystore password.                *"},
-
-        {"Certificate.reply.does.not.contain.public.key.for.alias.",
-                "Certificate reply does not contain public key for <{0}>"},
-        {"Incomplete.certificate.chain.in.reply",
-                "Incomplete certificate chain in reply"},
-        {"Certificate.chain.in.reply.does.not.verify.",
-                "Certificate chain in reply does not verify: "},
-        {"Top.level.certificate.in.reply.",
-                "Top-level certificate in reply:\n"},
-        {".is.not.trusted.", "... is not trusted. "},
-        {"Install.reply.anyway.no.", "Install reply anyway? [no]:  "},
-        {"NO", "NO"},
-        {"Public.keys.in.reply.and.keystore.don.t.match",
-                "Public keys in reply and keystore don't match"},
-        {"Certificate.reply.and.certificate.in.keystore.are.identical",
-                "Certificate reply and certificate in keystore are identical"},
-        {"Failed.to.establish.chain.from.reply",
-                "Failed to establish chain from reply"},
-        {"n", "n"},
-        {"Wrong.answer.try.again", "Wrong answer, try again"},
-        {"Secret.key.not.generated.alias.alias.already.exists",
-                "Secret Key not generated, alias <{0}> already exists"},
-        {"Please.provide.keysize.for.secret.key.generation",
-                "Please provide -keysize for secret key generation"},
-
-        {"Extensions.", "Extensions: "},
-        {".Empty.value.", "(Empty value)"},
-        {"Extension.Request.", "Extension Request:"},
-        {"PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key.",
-                "PKCS #10 Certificate Request (Version 1.0)\n" +
-                "Subject: %s\nPublic Key: %s format %s key\n"},
-        {"Unknown.keyUsage.type.", "Unknown keyUsage type: "},
-        {"Unknown.extendedkeyUsage.type.", "Unknown extendedkeyUsage type: "},
-        {"Unknown.AccessDescription.type.", "Unknown AccessDescription type: "},
-        {"Unrecognized.GeneralName.type.", "Unrecognized GeneralName type: "},
-        {"This.extension.cannot.be.marked.as.critical.",
-                 "This extension cannot be marked as critical. "},
-        {"Odd.number.of.hex.digits.found.", "Odd number of hex digits found: "},
-        {"Unknown.extension.type.", "Unknown extension type: "},
-        {"command.{0}.is.ambiguous.", "command {0} is ambiguous:"},
-
-        // policytool
-        {"Warning.A.public.key.for.alias.signers.i.does.not.exist.Make.sure.a.KeyStore.is.properly.configured.",
-                "Warning: A public key for alias {0} does not exist.  Make sure a KeyStore is properly configured."},
-        {"Warning.Class.not.found.class", "Warning: Class not found: {0}"},
-        {"Warning.Invalid.argument.s.for.constructor.arg",
-                "Warning: Invalid argument(s) for constructor: {0}"},
-        {"Illegal.Principal.Type.type", "Illegal Principal Type: {0}"},
-        {"Illegal.option.option", "Illegal option: {0}"},
-        {"Usage.policytool.options.", "Usage: policytool [options]"},
-        {".file.file.policy.file.location",
-                "  [-file <file>]    policy file location"},
-        {"New", "New"},
-        {"Open", "Open"},
-        {"Save", "Save"},
-        {"Save.As", "Save As"},
-        {"View.Warning.Log", "View Warning Log"},
-        {"Exit", "Exit"},
-        {"Add.Policy.Entry", "Add Policy Entry"},
-        {"Edit.Policy.Entry", "Edit Policy Entry"},
-        {"Remove.Policy.Entry", "Remove Policy Entry"},
-        {"Edit", "Edit"},
-        {"Retain", "Retain"},
-
-        {"Warning.File.name.may.include.escaped.backslash.characters.It.is.not.necessary.to.escape.backslash.characters.the.tool.escapes",
-            "Warning: File name may include escaped backslash characters. " +
-                        "It is not necessary to escape backslash characters " +
-                        "(the tool escapes characters as necessary when writing " +
-                        "the policy contents to the persistent store).\n\n" +
-                        "Click on Retain to retain the entered name, or click on " +
-                        "Edit to edit the name."},
-
-        {"Add.Public.Key.Alias", "Add Public Key Alias"},
-        {"Remove.Public.Key.Alias", "Remove Public Key Alias"},
-        {"File", "File"},
-        {"KeyStore", "KeyStore"},
-        {"Policy.File.", "Policy File:"},
-        {"Could.not.open.policy.file.policyFile.e.toString.",
-                "Could not open policy file: {0}: {1}"},
-        {"Policy.Tool", "Policy Tool"},
-        {"Errors.have.occurred.while.opening.the.policy.configuration.View.the.Warning.Log.for.more.information.",
-                "Errors have occurred while opening the policy configuration.  View the Warning Log for more information."},
-        {"Error", "Error"},
-        {"OK", "OK"},
-        {"Status", "Status"},
-        {"Warning", "Warning"},
-        {"Permission.",
-                "Permission:                                                       "},
-        {"Principal.Type.", "Principal Type:"},
-        {"Principal.Name.", "Principal Name:"},
-        {"Target.Name.",
-                "Target Name:                                                    "},
-        {"Actions.",
-                "Actions:                                                             "},
-        {"OK.to.overwrite.existing.file.filename.",
-                "OK to overwrite existing file {0}?"},
-        {"Cancel", "Cancel"},
-        {"CodeBase.", "CodeBase:"},
-        {"SignedBy.", "SignedBy:"},
-        {"Add.Principal", "Add Principal"},
-        {"Edit.Principal", "Edit Principal"},
-        {"Remove.Principal", "Remove Principal"},
-        {"Principals.", "Principals:"},
-        {".Add.Permission", "  Add Permission"},
-        {".Edit.Permission", "  Edit Permission"},
-        {"Remove.Permission", "Remove Permission"},
-        {"Done", "Done"},
-        {"KeyStore.URL.", "KeyStore URL:"},
-        {"KeyStore.Type.", "KeyStore Type:"},
-        {"KeyStore.Provider.", "KeyStore Provider:"},
-        {"KeyStore.Password.URL.", "KeyStore Password URL:"},
-        {"Principals", "Principals"},
-        {".Edit.Principal.", "  Edit Principal:"},
-        {".Add.New.Principal.", "  Add New Principal:"},
-        {"Permissions", "Permissions"},
-        {".Edit.Permission.", "  Edit Permission:"},
-        {".Add.New.Permission.", "  Add New Permission:"},
-        {"Signed.By.", "Signed By:"},
-        {"Cannot.Specify.Principal.with.a.Wildcard.Class.without.a.Wildcard.Name",
-            "Cannot Specify Principal with a Wildcard Class without a Wildcard Name"},
-        {"Cannot.Specify.Principal.without.a.Name",
-            "Cannot Specify Principal without a Name"},
-        {"Permission.and.Target.Name.must.have.a.value",
-                "Permission and Target Name must have a value"},
-        {"Remove.this.Policy.Entry.", "Remove this Policy Entry?"},
-        {"Overwrite.File", "Overwrite File"},
-        {"Policy.successfully.written.to.filename",
-                "Policy successfully written to {0}"},
-        {"null.filename", "null filename"},
-        {"Save.changes.", "Save changes?"},
-        {"Yes", "Yes"},
-        {"No", "No"},
-        {"Policy.Entry", "Policy Entry"},
-        {"Save.Changes", "Save Changes"},
-        {"No.Policy.Entry.selected", "No Policy Entry selected"},
-        {"Unable.to.open.KeyStore.ex.toString.",
-                "Unable to open KeyStore: {0}"},
-        {"No.principal.selected", "No principal selected"},
-        {"No.permission.selected", "No permission selected"},
-        {"name", "name"},
-        {"configuration.type", "configuration type"},
-        {"environment.variable.name", "environment variable name"},
-        {"library.name", "library name"},
-        {"package.name", "package name"},
-        {"policy.type", "policy type"},
-        {"property.name", "property name"},
-        {"Principal.List", "Principal List"},
-        {"Permission.List", "Permission List"},
-        {"Code.Base", "Code Base"},
-        {"KeyStore.U.R.L.", "KeyStore U R L:"},
-        {"KeyStore.Password.U.R.L.", "KeyStore Password U R L:"},
-
-
         // javax.security.auth.PrivateCredentialPermission
         {"invalid.null.input.s.", "invalid null input(s)"},
         {"actions.can.only.be.read.", "actions can only be 'read'"},
@@ -561,6 +58,7 @@
         {"provided.null.OID.map", "provided null OID map"},
 
         // javax.security.auth.Subject
+        {"NEWLINE", "\n"},
         {"invalid.null.AccessControlContext.provided",
                 "invalid null AccessControlContext provided"},
         {"invalid.null.action.provided", "invalid null action provided"},
@@ -629,6 +127,8 @@
         {"multiple.Codebase.expressions",
                 "multiple Codebase expressions"},
         {"multiple.SignedBy.expressions","multiple SignedBy expressions"},
+        {"duplicate.keystore.domain.name","duplicate keystore domain name: {0}"},
+        {"duplicate.keystore.name","duplicate keystore name: {0}"},
         {"SignedBy.has.empty.alias","SignedBy has empty alias"},
         {"can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name",
                 "can not specify Principal with a wildcard class without a wildcard name"},
@@ -664,6 +164,7 @@
      *
      * @return the contents of this <code>ResourceBundle</code>.
      */
+    @Override
     public Object[][] getContents() {
         return contents;
     }
diff --git a/ojluni/src/main/java/sun/security/util/SecurityConstants.java b/ojluni/src/main/java/sun/security/util/SecurityConstants.java
index adad3fa..39fabcf 100644
--- a/ojluni/src/main/java/sun/security/util/SecurityConstants.java
+++ b/ojluni/src/main/java/sun/security/util/SecurityConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,35 +71,6 @@
     public static final AllPermission ALL_PERMISSION = new AllPermission();
 
     /**
-     * Permission type used when AWT is not present.
-     */
-    /* ----- BEGIN android -----
-    private static class FakeAWTPermission extends BasicPermission {
-        private static final long serialVersionUID = -1L;
-        public FakeAWTPermission(String name) {
-            super(name);
-        }
-        public String toString() {
-            return "(\"java.awt.AWTPermission\" \"" + getName() + "\")";
-        }
-    }
-    ----- END android ----- */
-
-    /**
-     * Permission factory used when AWT is not present.
-     */
-    /* ----- BEGIN android -----
-    private static class FakeAWTPermissionFactory
-        implements PermissionFactory<FakeAWTPermission>
-    {
-        @Override
-        public FakeAWTPermission newPermission(String name) {
-            return new FakeAWTPermission(name);
-        }
-    }
-    ----- END android ----- */
-
-    /**
      * AWT Permissions used in the JDK.
      */
     /* ----- BEGIN android -----
@@ -109,38 +80,28 @@
         // The class name of the factory to create java.awt.AWTPermission objects.
         private static final String AWTFactory = "sun.awt.AWTPermissionFactory";
 
-         // The PermissionFactory to create AWT permissions (or fake permissions
-         // if AWT is not present).
+        // The PermissionFactory to create AWT permissions (or null if AWT is
+        // not present)
         private static final PermissionFactory<?> factory = permissionFactory();
 
         private static PermissionFactory<?> permissionFactory() {
-            Class<?> c = AccessController
-                .doPrivileged(new PrivilegedAction<Class<?>>() {
-                    public Class<?> run() {
-                        try {
-                           return Class.forName(AWTFactory, true, null);
-                        } catch (ClassNotFoundException e) {
-                            // not available
-                            return null;
-                        }
-                    }});
-            if (c != null) {
-                // AWT present
-                try {
-                    return (PermissionFactory<?>)c.newInstance();
-                } catch (InstantiationException x) {
-                    throw new InternalError(x.getMessage());
-                } catch (IllegalAccessException x) {
-                    throw new InternalError(x.getMessage());
-                }
-            } else {
-                // AWT not present
-                return new FakeAWTPermissionFactory();
+            Class<?> c;
+            try {
+                c = Class.forName(AWTFactory, false, AWT.class.getClassLoader());
+            } catch (ClassNotFoundException e) {
+                // not available
+                return null;
+            }
+            // AWT present
+            try {
+                return (PermissionFactory<?>)c.newInstance();
+            } catch (ReflectiveOperationException x) {
+                throw new InternalError(x);
             }
         }
 
         private static Permission newAWTPermission(String name) {
-            return factory.newPermission(name);
+            return (factory == null) ? null : factory.newPermission(name);
         }
 
         // java.lang.SecurityManager
@@ -259,5 +220,5 @@
 
     // java.lang.SecurityManager
     public static final SocketPermission LOCAL_LISTEN_PERMISSION =
-        new SocketPermission("localhost:1024-", SOCKET_LISTEN_ACTION);
+        new SocketPermission("localhost:0", SOCKET_LISTEN_ACTION);
 }
diff --git a/ojluni/src/main/java/sun/security/validator/EndEntityChecker.java b/ojluni/src/main/java/sun/security/validator/EndEntityChecker.java
deleted file mode 100644
index 4ca79f0..0000000
--- a/ojluni/src/main/java/sun/security/validator/EndEntityChecker.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, 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.validator;
-
-import java.util.*;
-
-import java.security.cert.*;
-
-import sun.security.x509.NetscapeCertTypeExtension;
-
-/**
- * Class to check if an end entity cert is suitable for use in some
- * context.<p>
- *
- * This class is used internally by the validator. Currently, seven variants
- * are supported defined as VAR_XXX constants in the Validator class:
- * <ul>
- * <li>Generic. No additional requirements, all certificates are ok.
- *
- * <li>TLS server. Requires that a String parameter is passed to
- * validate that specifies the name of the TLS key exchange algorithm
- * in use. See the JSSE X509TrustManager spec for details.
- *
- * <li>TLS client.
- *
- * <li>Code signing.
- *
- * <li>JCE code signing. Some early JCE code signing certs issued to
- * providers had incorrect extensions. In this mode the checks
- * are relaxed compared to standard code signing checks in order to
- * allow these certificates to pass.
- *
- * <li>Plugin code signing. WebStart and Plugin require their own variant
- * which is equivalent to VAR_CODE_SIGNING with additional checks for
- * compatibility/special cases. See also PKIXValidator.
- *
- * <li>TSA Server (see RFC 3161, section 2.3).
- *
- * </ul>
- *
- * @author Andreas Sterbenz
- */
-class EndEntityChecker {
-
-    // extended key usage OIDs for TLS server, TLS client, code signing
-    // and any usage
-
-    private final static String OID_EXTENDED_KEY_USAGE =
-                                SimpleValidator.OID_EXTENDED_KEY_USAGE;
-
-    private final static String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1";
-
-    private final static String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2";
-
-    private final static String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3";
-
-    private final static String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8";
-
-    private final static String OID_EKU_ANY_USAGE = "2.5.29.37.0";
-
-    // the Netscape Server-Gated-Cryptography EKU extension OID
-    private final static String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1";
-
-    // the Microsoft Server-Gated-Cryptography EKU extension OID
-    private final static String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";
-
-    // the recognized extension OIDs
-    private final static String OID_SUBJECT_ALT_NAME = "2.5.29.17";
-
-    private final static String NSCT_SSL_CLIENT =
-                                NetscapeCertTypeExtension.SSL_CLIENT;
-
-    private final static String NSCT_SSL_SERVER =
-                                NetscapeCertTypeExtension.SSL_SERVER;
-
-    private final static String NSCT_CODE_SIGNING =
-                                NetscapeCertTypeExtension.OBJECT_SIGNING;
-
-    // bit numbers in the key usage extension
-    private final static int KU_SIGNATURE = 0;
-    private final static int KU_KEY_ENCIPHERMENT = 2;
-    private final static int KU_KEY_AGREEMENT = 4;
-
-    // TLS key exchange algorithms requiring digitalSignature key usage
-    private final static Collection<String> KU_SERVER_SIGNATURE =
-        Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",
-            "RSA_EXPORT", "UNKNOWN");
-
-    // TLS key exchange algorithms requiring keyEncipherment key usage
-    private final static Collection<String> KU_SERVER_ENCRYPTION =
-        Arrays.asList("RSA");
-
-    // TLS key exchange algorithms requiring keyAgreement key usage
-    private final static Collection<String> KU_SERVER_KEY_AGREEMENT =
-        Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");
-
-    // variant of this end entity cert checker
-    private final String variant;
-
-    // type of the validator this checker belongs to
-    private final String type;
-
-    private EndEntityChecker(String type, String variant) {
-        this.type = type;
-        this.variant = variant;
-    }
-
-    static EndEntityChecker getInstance(String type, String variant) {
-        return new EndEntityChecker(type, variant);
-    }
-
-    void check(X509Certificate cert, Object parameter)
-            throws CertificateException {
-        if (variant.equals(Validator.VAR_GENERIC)) {
-            // no checks
-            return;
-        } else if (variant.equals(Validator.VAR_TLS_SERVER)) {
-            checkTLSServer(cert, (String)parameter);
-        } else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
-            checkTLSClient(cert);
-        } else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
-            checkCodeSigning(cert);
-        } else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
-            checkCodeSigning(cert);
-        } else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
-            checkCodeSigning(cert);
-        } else if (variant.equals(Validator.VAR_TSA_SERVER)) {
-            checkTSAServer(cert);
-        } else {
-            throw new CertificateException("Unknown variant: " + variant);
-        }
-    }
-
-    /**
-     * Utility method returning the Set of critical extensions for
-     * certificate cert (never null).
-     */
-    private Set<String> getCriticalExtensions(X509Certificate cert) {
-        Set<String> exts = cert.getCriticalExtensionOIDs();
-        if (exts == null) {
-            exts = Collections.emptySet();
-        }
-        return exts;
-    }
-
-    /**
-     * Utility method checking if there are any unresolved critical extensions.
-     * @throws CertificateException if so.
-     */
-    private void checkRemainingExtensions(Set<String> exts)
-            throws CertificateException {
-        // basic constraints irrelevant in EE certs
-        exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
-
-        // If the subject field contains an empty sequence, the subjectAltName
-        // extension MUST be marked critical.
-        // We do not check the validity of the critical extension, just mark
-        // it recognizable here.
-        exts.remove(OID_SUBJECT_ALT_NAME);
-
-        if (!exts.isEmpty()) {
-            throw new CertificateException("Certificate contains unsupported "
-                + "critical extensions: " + exts);
-        }
-    }
-
-    /**
-     * Utility method checking if the extended key usage extension in
-     * certificate cert allows use for expectedEKU.
-     */
-    private boolean checkEKU(X509Certificate cert, Set<String> exts,
-            String expectedEKU) throws CertificateException {
-        List<String> eku = cert.getExtendedKeyUsage();
-        if (eku == null) {
-            return true;
-        }
-        return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);
-    }
-
-    /**
-     * Utility method checking if bit 'bit' is set in this certificates
-     * key usage extension.
-     * @throws CertificateException if not
-     */
-    private boolean checkKeyUsage(X509Certificate cert, int bit)
-            throws CertificateException {
-        boolean[] keyUsage = cert.getKeyUsage();
-        if (keyUsage == null) {
-            return true;
-        }
-        return (keyUsage.length > bit) && keyUsage[bit];
-    }
-
-    /**
-     * Check whether this certificate can be used for TLS client
-     * authentication.
-     * @throws CertificateException if not.
-     */
-    private void checkTLSClient(X509Certificate cert)
-            throws CertificateException {
-        Set<String> exts = getCriticalExtensions(cert);
-
-        if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
-            throw new ValidatorException
-                ("KeyUsage does not allow digital signatures",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {
-            throw new ValidatorException("Extended key usage does not "
-                + "permit use for TLS client authentication",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
-            throw new ValidatorException
-                ("Netscape cert type does not permit use for SSL client",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        // remove extensions we checked
-        exts.remove(SimpleValidator.OID_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
-
-        checkRemainingExtensions(exts);
-    }
-
-    /**
-     * Check whether this certificate can be used for TLS server authentication
-     * using the specified authentication type parameter. See X509TrustManager
-     * specification for details.
-     * @throws CertificateException if not.
-     */
-    private void checkTLSServer(X509Certificate cert, String parameter)
-            throws CertificateException {
-        Set<String> exts = getCriticalExtensions(cert);
-
-        if (KU_SERVER_ENCRYPTION.contains(parameter)) {
-            if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {
-                throw new ValidatorException
-                        ("KeyUsage does not allow key encipherment",
-                        ValidatorException.T_EE_EXTENSIONS, cert);
-            }
-        } else if (KU_SERVER_SIGNATURE.contains(parameter)) {
-            if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
-                throw new ValidatorException
-                        ("KeyUsage does not allow digital signatures",
-                        ValidatorException.T_EE_EXTENSIONS, cert);
-            }
-        } else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {
-            if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {
-                throw new ValidatorException
-                        ("KeyUsage does not allow key agreement",
-                        ValidatorException.T_EE_EXTENSIONS, cert);
-            }
-        } else {
-            throw new CertificateException("Unknown authType: " + parameter);
-        }
-
-        if (checkEKU(cert, exts, OID_EKU_TLS_SERVER) == false) {
-            // check for equivalent but now obsolete Server-Gated-Cryptography
-            // (aka Step-Up, 128 bit) EKU OIDs
-            if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&
-                (checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {
-                throw new ValidatorException
-                    ("Extended key usage does not permit use for TLS "
-                    + "server authentication",
-                    ValidatorException.T_EE_EXTENSIONS, cert);
-            }
-        }
-
-        if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {
-            throw new ValidatorException
-                ("Netscape cert type does not permit use for SSL server",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        // remove extensions we checked
-        exts.remove(SimpleValidator.OID_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
-
-        checkRemainingExtensions(exts);
-    }
-
-    /**
-     * Check whether this certificate can be used for code signing.
-     * @throws CertificateException if not.
-     */
-    private void checkCodeSigning(X509Certificate cert)
-            throws CertificateException {
-        Set<String> exts = getCriticalExtensions(cert);
-
-        if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
-            throw new ValidatorException
-                ("KeyUsage does not allow digital signatures",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
-            throw new ValidatorException
-                ("Extended key usage does not permit use for code signing",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        // do not check Netscape cert type for JCE code signing checks
-        // (some certs were issued with incorrect extensions)
-        if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
-            if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
-                throw new ValidatorException
-                    ("Netscape cert type does not permit use for code signing",
-                    ValidatorException.T_EE_EXTENSIONS, cert);
-            }
-            exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
-        }
-
-        // remove extensions we checked
-        exts.remove(SimpleValidator.OID_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
-
-        checkRemainingExtensions(exts);
-    }
-
-    /**
-     * Check whether this certificate can be used by a time stamping authority
-     * server (see RFC 3161, section 2.3).
-     * @throws CertificateException if not.
-     */
-    private void checkTSAServer(X509Certificate cert)
-            throws CertificateException {
-        Set<String> exts = getCriticalExtensions(cert);
-
-        if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
-            throw new ValidatorException
-                ("KeyUsage does not allow digital signatures",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        if (cert.getExtendedKeyUsage() == null) {
-            throw new ValidatorException
-                ("Certificate does not contain an extended key usage " +
-                "extension required for a TSA server",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {
-            throw new ValidatorException
-                ("Extended key usage does not permit use for TSA server",
-                ValidatorException.T_EE_EXTENSIONS, cert);
-        }
-
-        // remove extensions we checked
-        exts.remove(SimpleValidator.OID_KEY_USAGE);
-        exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
-
-        checkRemainingExtensions(exts);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/validator/KeyStores.java b/ojluni/src/main/java/sun/security/validator/KeyStores.java
deleted file mode 100644
index 8a33cd3..0000000
--- a/ojluni/src/main/java/sun/security/validator/KeyStores.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2002, 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.validator;
-
-import java.io.*;
-import java.util.*;
-
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import sun.security.action.*;
-
-/**
- * Collection of static utility methods related to KeyStores.
- *
- * @author Andreas Sterbenz
- */
-public class KeyStores {
-
-    private KeyStores() {
-        // empty
-    }
-
-    // in the future, all accesses to the system cacerts keystore should
-    // go through this class. but not right now.
-/*
-    private final static String javaHome =
-        (String)AccessController.doPrivileged(new GetPropertyAction("java.home"));
-
-    private final static char SEP = File.separatorChar;
-
-    private static KeyStore caCerts;
-
-    private static KeyStore getKeyStore(String type, String name,
-            char[] password) throws IOException {
-        if (type == null) {
-            type = "JKS";
-        }
-        try {
-            KeyStore ks = KeyStore.getInstance(type);
-            FileInputStream in = (FileInputStream)AccessController.doPrivileged
-                                        (new OpenFileInputStreamAction(name));
-            ks.load(in, password);
-            return ks;
-        } catch (GeneralSecurityException e) {
-            // XXX
-            throw new IOException();
-        } catch (PrivilegedActionException e) {
-            throw (IOException)e.getCause();
-        }
-    }
-
-    /**
-     * Return a KeyStore with the contents of the lib/security/cacerts file.
-     * The file is only opened once per JVM invocation and the contents
-     * cached subsequently.
-     *
-    public synchronized static KeyStore getCaCerts() throws IOException {
-        if (caCerts != null) {
-            return caCerts;
-        }
-        String name = javaHome + SEP + "lib" + SEP + "security" + SEP + "cacerts";
-        caCerts = getKeyStore(null, name, null);
-        return caCerts;
-    }
-*/
-
-    /**
-     * Return a Set with all trusted X509Certificates contained in
-     * this KeyStore.
-     */
-    public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
-        Set<X509Certificate> set = new HashSet<X509Certificate>();
-        try {
-            for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
-                String alias = e.nextElement();
-                if (ks.isCertificateEntry(alias)) {
-                    Certificate cert = ks.getCertificate(alias);
-                    if (cert instanceof X509Certificate) {
-                        set.add((X509Certificate)cert);
-                    }
-                } else if (ks.isKeyEntry(alias)) {
-                    Certificate[] certs = ks.getCertificateChain(alias);
-                    if ((certs != null) && (certs.length > 0) &&
-                            (certs[0] instanceof X509Certificate)) {
-                        set.add((X509Certificate)certs[0]);
-                    }
-                }
-            }
-        } catch (KeyStoreException e) {
-            // ignore
-        }
-        return set;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/validator/PKIXValidator.java b/ojluni/src/main/java/sun/security/validator/PKIXValidator.java
deleted file mode 100644
index 51761e1..0000000
--- a/ojluni/src/main/java/sun/security/validator/PKIXValidator.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.validator;
-
-import java.util.*;
-
-import java.security.*;
-import java.security.cert.*;
-
-import javax.security.auth.x500.X500Principal;
-import sun.security.action.GetBooleanAction;
-import sun.security.provider.certpath.AlgorithmChecker;
-
-/**
- * Validator implementation built on the PKIX CertPath API. This
- * implementation will be emphasized going forward.<p>
- * <p>
- * Note that the validate() implementation tries to use a PKIX validator
- * if that appears possible and a PKIX builder otherwise. This increases
- * performance and currently also leads to better exception messages
- * in case of failures.
- * <p>
- * {@code PKIXValidator} objects are immutable once they have been created.
- * Please DO NOT add methods that can change the state of an instance once
- * it has been created.
- *
- * @author Andreas Sterbenz
- */
-public final class PKIXValidator extends Validator {
-
-    /**
-     * Flag indicating whether to enable revocation check for the PKIX trust
-     * manager. Typically, this will only work if the PKIX implementation
-     * supports CRL distribution points as we do not manually setup CertStores.
-     */
-    private final static boolean checkTLSRevocation =
-        AccessController.doPrivileged
-            (new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
-
-    // enable use of the validator if possible
-    private final static boolean TRY_VALIDATOR = true;
-
-    private final Set<X509Certificate> trustedCerts;
-    private final PKIXBuilderParameters parameterTemplate;
-    private int certPathLength = -1;
-
-    // needed only for the validator
-    private final Map<X500Principal, List<PublicKey>> trustedSubjects;
-    private final CertificateFactory factory;
-
-    private final boolean plugin;
-
-    PKIXValidator(String variant, Collection<X509Certificate> trustedCerts) {
-        super(TYPE_PKIX, variant);
-        if (trustedCerts instanceof Set) {
-            this.trustedCerts = (Set<X509Certificate>)trustedCerts;
-        } else {
-            this.trustedCerts = new HashSet<X509Certificate>(trustedCerts);
-        }
-        Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
-        for (X509Certificate cert : trustedCerts) {
-            trustAnchors.add(new TrustAnchor(cert, null));
-        }
-        try {
-            parameterTemplate = new PKIXBuilderParameters(trustAnchors, null);
-        } catch (InvalidAlgorithmParameterException e) {
-            throw new RuntimeException("Unexpected error: " + e.toString(), e);
-        }
-        setDefaultParameters(variant);
-
-        // initCommon();
-        if (TRY_VALIDATOR) {
-            if (TRY_VALIDATOR == false) {
-                return;
-            }
-            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
-            for (X509Certificate cert : trustedCerts) {
-                X500Principal dn = cert.getSubjectX500Principal();
-                List<PublicKey> keys;
-                if (trustedSubjects.containsKey(dn)) {
-                    keys = trustedSubjects.get(dn);
-                } else {
-                    keys = new ArrayList<PublicKey>();
-                    trustedSubjects.put(dn, keys);
-                }
-                keys.add(cert.getPublicKey());
-            }
-            try {
-                factory = CertificateFactory.getInstance("X.509");
-            } catch (CertificateException e) {
-                throw new RuntimeException("Internal error", e);
-            }
-            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
-        } else {
-            plugin = false;
-        }
-    }
-
-    PKIXValidator(String variant, PKIXBuilderParameters params) {
-        super(TYPE_PKIX, variant);
-        trustedCerts = new HashSet<X509Certificate>();
-        for (TrustAnchor anchor : params.getTrustAnchors()) {
-            X509Certificate cert = anchor.getTrustedCert();
-            if (cert != null) {
-                trustedCerts.add(cert);
-            }
-        }
-        parameterTemplate = params;
-
-        // initCommon();
-        if (TRY_VALIDATOR) {
-            if (TRY_VALIDATOR == false) {
-                return;
-            }
-            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
-            for (X509Certificate cert : trustedCerts) {
-                X500Principal dn = cert.getSubjectX500Principal();
-                List<PublicKey> keys;
-                if (trustedSubjects.containsKey(dn)) {
-                    keys = trustedSubjects.get(dn);
-                } else {
-                    keys = new ArrayList<PublicKey>();
-                    trustedSubjects.put(dn, keys);
-                }
-                keys.add(cert.getPublicKey());
-            }
-            try {
-                factory = CertificateFactory.getInstance("X.509");
-            } catch (CertificateException e) {
-                throw new RuntimeException("Internal error", e);
-            }
-            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
-        } else {
-            plugin = false;
-        }
-    }
-
-    public Collection<X509Certificate> getTrustedCertificates() {
-        return trustedCerts;
-    }
-
-    /**
-     * Returns the length of the last certification path that is validated by
-     * CertPathValidator. This is intended primarily as a callback mechanism
-     * for PKIXCertPathCheckers to determine the length of the certification
-     * path that is being validated. It is necessary since engineValidate()
-     * may modify the length of the path.
-     *
-     * @return the length of the last certification path passed to
-     *   CertPathValidator.validate, or -1 if it has not been invoked yet
-     */
-    public int getCertPathLength() { // mutable, should be private
-        return certPathLength;
-    }
-
-    /**
-     * Set J2SE global default PKIX parameters. Currently, hardcoded to disable
-     * revocation checking. In the future, this should be configurable.
-     */
-    private void setDefaultParameters(String variant) {
-        if ((variant == Validator.VAR_TLS_SERVER) ||
-                (variant == Validator.VAR_TLS_CLIENT)) {
-            parameterTemplate.setRevocationEnabled(checkTLSRevocation);
-        } else {
-            parameterTemplate.setRevocationEnabled(false);
-        }
-    }
-
-    /**
-     * Return the PKIX parameters used by this instance. An application may
-     * modify the parameters but must make sure not to perform any concurrent
-     * validations.
-     */
-    public PKIXBuilderParameters getParameters() { // mutable, should be private
-        return parameterTemplate;
-    }
-
-    @Override
-    X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts,
-            AlgorithmConstraints constraints,
-            Object parameter) throws CertificateException {
-        if ((chain == null) || (chain.length == 0)) {
-            throw new CertificateException
-                ("null or zero-length certificate chain");
-        }
-
-        // add  new algorithm constraints checker
-        PKIXBuilderParameters pkixParameters =
-                    (PKIXBuilderParameters) parameterTemplate.clone();
-        AlgorithmChecker algorithmChecker = null;
-        if (constraints != null) {
-            algorithmChecker = new AlgorithmChecker(constraints);
-            pkixParameters.addCertPathChecker(algorithmChecker);
-        }
-
-        if (TRY_VALIDATOR) {
-            // check that chain is in correct order and check if chain contains
-            // trust anchor
-            X500Principal prevIssuer = null;
-            for (int i = 0; i < chain.length; i++) {
-                X509Certificate cert = chain[i];
-                X500Principal dn = cert.getSubjectX500Principal();
-                if (i != 0 &&
-                    !dn.equals(prevIssuer)) {
-                    // chain is not ordered correctly, call builder instead
-                    return doBuild(chain, otherCerts, pkixParameters);
-                }
-
-                // Check if chain[i] is already trusted. It may be inside
-                // trustedCerts, or has the same dn and public key as a cert
-                // inside trustedCerts. The latter happens when a CA has
-                // updated its cert with a stronger signature algorithm in JRE
-                // but the weak one is still in circulation.
-
-                if (trustedCerts.contains(cert) ||          // trusted cert
-                        (trustedSubjects.containsKey(dn) && // replacing ...
-                         trustedSubjects.get(dn).contains(  // ... weak cert
-                            cert.getPublicKey()))) {
-                    if (i == 0) {
-                        return new X509Certificate[] {chain[0]};
-                    }
-                    // Remove and call validator on partial chain [0 .. i-1]
-                    X509Certificate[] newChain = new X509Certificate[i];
-                    System.arraycopy(chain, 0, newChain, 0, i);
-                    return doValidate(newChain, pkixParameters);
-                }
-                prevIssuer = cert.getIssuerX500Principal();
-            }
-
-            // apparently issued by trust anchor?
-            X509Certificate last = chain[chain.length - 1];
-            X500Principal issuer = last.getIssuerX500Principal();
-            X500Principal subject = last.getSubjectX500Principal();
-            if (trustedSubjects.containsKey(issuer) &&
-                    isSignatureValid(trustedSubjects.get(issuer), last)) {
-                return doValidate(chain, pkixParameters);
-            }
-
-            // don't fallback to builder if called from plugin/webstart
-            if (plugin) {
-                // Validate chain even if no trust anchor is found. This
-                // allows plugin/webstart to make sure the chain is
-                // otherwise valid
-                if (chain.length > 1) {
-                    X509Certificate[] newChain =
-                        new X509Certificate[chain.length-1];
-                    System.arraycopy(chain, 0, newChain, 0, newChain.length);
-
-                    // temporarily set last cert as sole trust anchor
-                    try {
-                        pkixParameters.setTrustAnchors
-                            (Collections.singleton(new TrustAnchor
-                                (chain[chain.length-1], null)));
-                    } catch (InvalidAlgorithmParameterException iape) {
-                        // should never occur, but ...
-                        throw new CertificateException(iape);
-                    }
-                    doValidate(newChain, pkixParameters);
-                }
-                // if the rest of the chain is valid, throw exception
-                // indicating no trust anchor was found
-                throw new ValidatorException
-                    (ValidatorException.T_NO_TRUST_ANCHOR);
-            }
-            // otherwise, fall back to builder
-        }
-
-        return doBuild(chain, otherCerts, pkixParameters);
-    }
-
-    private boolean isSignatureValid(List<PublicKey> keys,
-            X509Certificate sub) {
-        if (plugin) {
-            for (PublicKey key: keys) {
-                try {
-                    sub.verify(key);
-                    return true;
-                } catch (Exception ex) {
-                    continue;
-                }
-            }
-            return false;
-        }
-        return true; // only check if PLUGIN is set
-    }
-
-    private static X509Certificate[] toArray(CertPath path, TrustAnchor anchor)
-            throws CertificateException {
-        List<? extends java.security.cert.Certificate> list =
-                                                path.getCertificates();
-        X509Certificate[] chain = new X509Certificate[list.size() + 1];
-        list.toArray(chain);
-        X509Certificate trustedCert = anchor.getTrustedCert();
-        if (trustedCert == null) {
-            throw new ValidatorException
-                ("TrustAnchor must be specified as certificate");
-        }
-        chain[chain.length - 1] = trustedCert;
-        return chain;
-    }
-
-    /**
-     * Set the check date (for debugging).
-     */
-    private void setDate(PKIXBuilderParameters params) {
-        @SuppressWarnings("deprecation")
-        Date date = validationDate;
-        if (date != null) {
-            params.setDate(date);
-        }
-    }
-
-    private X509Certificate[] doValidate(X509Certificate[] chain,
-            PKIXBuilderParameters params) throws CertificateException {
-        try {
-            setDate(params);
-
-            // do the validation
-            CertPathValidator validator = CertPathValidator.getInstance("PKIX");
-            CertPath path = factory.generateCertPath(Arrays.asList(chain));
-            certPathLength = chain.length;
-            PKIXCertPathValidatorResult result =
-                (PKIXCertPathValidatorResult)validator.validate(path, params);
-
-            return toArray(path, result.getTrustAnchor());
-        } catch (GeneralSecurityException e) {
-            throw new ValidatorException
-                ("PKIX path validation failed: " + e.toString(), e);
-        }
-    }
-
-    private X509Certificate[] doBuild(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts,
-        PKIXBuilderParameters params) throws CertificateException {
-
-        try {
-            setDate(params);
-
-            // setup target constraints
-            X509CertSelector selector = new X509CertSelector();
-            selector.setCertificate(chain[0]);
-            params.setTargetCertConstraints(selector);
-
-            // setup CertStores
-            Collection<X509Certificate> certs =
-                                        new ArrayList<X509Certificate>();
-            certs.addAll(Arrays.asList(chain));
-            if (otherCerts != null) {
-                certs.addAll(otherCerts);
-            }
-            CertStore store = CertStore.getInstance("Collection",
-                                new CollectionCertStoreParameters(certs));
-            params.addCertStore(store);
-
-            // do the build
-            CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
-            PKIXCertPathBuilderResult result =
-                (PKIXCertPathBuilderResult)builder.build(params);
-
-            return toArray(result.getCertPath(), result.getTrustAnchor());
-        } catch (GeneralSecurityException e) {
-            throw new ValidatorException
-                ("PKIX path building failed: " + e.toString(), e);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/validator/SimpleValidator.java b/ojluni/src/main/java/sun/security/validator/SimpleValidator.java
deleted file mode 100644
index ad5e253..0000000
--- a/ojluni/src/main/java/sun/security/validator/SimpleValidator.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.validator;
-
-import java.io.IOException;
-import java.util.*;
-
-import java.security.*;
-import java.security.cert.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.NetscapeCertTypeExtension;
-import sun.security.util.DerValue;
-import sun.security.util.DerInputStream;
-import sun.security.util.DerOutputStream;
-import sun.security.util.ObjectIdentifier;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-import sun.security.provider.certpath.UntrustedChecker;
-
-/**
- * A simple validator implementation. It is based on code from the JSSE
- * X509TrustManagerImpl. This implementation is designed for compatibility with
- * deployed certificates and previous J2SE versions. It will never support
- * more advanced features and will be deemphasized in favor of the PKIX
- * validator going forward.
- * <p>
- * {@code SimpleValidator} objects are immutable once they have been created.
- * Please DO NOT add methods that can change the state of an instance once
- * it has been created.
- *
- * @author Andreas Sterbenz
- */
-public final class SimpleValidator extends Validator {
-
-    // Constants for the OIDs we need
-
-    final static String OID_BASIC_CONSTRAINTS = "2.5.29.19";
-
-    final static String OID_NETSCAPE_CERT_TYPE = "2.16.840.1.113730.1.1";
-
-    final static String OID_KEY_USAGE = "2.5.29.15";
-
-    final static String OID_EXTENDED_KEY_USAGE = "2.5.29.37";
-
-    final static String OID_EKU_ANY_USAGE = "2.5.29.37.0";
-
-    final static ObjectIdentifier OBJID_NETSCAPE_CERT_TYPE =
-        NetscapeCertTypeExtension.NetscapeCertType_Id;
-
-    private final static String NSCT_SSL_CA =
-                                NetscapeCertTypeExtension.SSL_CA;
-
-    private final static String NSCT_CODE_SIGNING_CA =
-                                NetscapeCertTypeExtension.OBJECT_SIGNING_CA;
-
-    /**
-     * The trusted certificates as:
-     * Map (X500Principal)subject of trusted cert -> List of X509Certificate
-     * The list is used because there may be multiple certificates
-     * with an identical subject DN.
-     */
-    private final Map<X500Principal, List<X509Certificate>>
-                                            trustedX500Principals;
-
-    /**
-     * Set of the trusted certificates. Present only for
-     * getTrustedCertificates().
-     */
-    private final Collection<X509Certificate> trustedCerts;
-
-    SimpleValidator(String variant, Collection<X509Certificate> trustedCerts) {
-        super(TYPE_SIMPLE, variant);
-        this.trustedCerts = trustedCerts;
-        trustedX500Principals =
-                        new HashMap<X500Principal, List<X509Certificate>>();
-        for (X509Certificate cert : trustedCerts) {
-            X500Principal principal = cert.getSubjectX500Principal();
-            List<X509Certificate> list = trustedX500Principals.get(principal);
-            if (list == null) {
-                // this actually should be a set, but duplicate entries
-                // are not a problem and we can avoid the Set overhead
-                list = new ArrayList<X509Certificate>(2);
-                trustedX500Principals.put(principal, list);
-            }
-            list.add(cert);
-        }
-    }
-
-    public Collection<X509Certificate> getTrustedCertificates() {
-        return trustedCerts;
-    }
-
-    /**
-     * Perform simple validation of chain. The arguments otherCerts and
-     * parameter are ignored.
-     */
-    @Override
-    X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts,
-            AlgorithmConstraints constraints,
-            Object parameter) throws CertificateException {
-        if ((chain == null) || (chain.length == 0)) {
-            throw new CertificateException
-                ("null or zero-length certificate chain");
-        }
-
-        // make sure chain includes a trusted cert
-        chain = buildTrustedChain(chain);
-
-        Date date = validationDate;
-        if (date == null) {
-            date = new Date();
-        }
-
-        // create distrusted certificates checker
-        UntrustedChecker untrustedChecker = new UntrustedChecker();
-
-        // create default algorithm constraints checker
-        TrustAnchor anchor = new TrustAnchor(chain[chain.length - 1], null);
-        AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor);
-
-        // create application level algorithm constraints checker
-        AlgorithmChecker appAlgChecker = null;
-        if (constraints != null) {
-            appAlgChecker = new AlgorithmChecker(anchor, constraints);
-        }
-
-        // verify top down, starting at the certificate issued by
-        // the trust anchor
-        int maxPathLength = chain.length - 1;
-        for (int i = chain.length - 2; i >= 0; i--) {
-            X509Certificate issuerCert = chain[i + 1];
-            X509Certificate cert = chain[i];
-
-            // check untrusted certificate
-            try {
-                // Untrusted checker does not care about the unresolved
-                // critical extensions.
-                untrustedChecker.check(cert, Collections.<String>emptySet());
-            } catch (CertPathValidatorException cpve) {
-                throw new ValidatorException(
-                    "Untrusted certificate: " + cert.getSubjectX500Principal(),
-                    ValidatorException.T_UNTRUSTED_CERT, cert, cpve);
-            }
-
-            // check certificate algorithm
-            try {
-                // Algorithm checker does not care about the unresolved
-                // critical extensions.
-                defaultAlgChecker.check(cert, Collections.<String>emptySet());
-                if (appAlgChecker != null) {
-                    appAlgChecker.check(cert, Collections.<String>emptySet());
-                }
-            } catch (CertPathValidatorException cpve) {
-                throw new ValidatorException
-                        (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
-            }
-
-            // no validity check for code signing certs
-            if ((variant.equals(VAR_CODE_SIGNING) == false)
-                        && (variant.equals(VAR_JCE_SIGNING) == false)) {
-                cert.checkValidity(date);
-            }
-
-            // check name chaining
-            if (cert.getIssuerX500Principal().equals(
-                        issuerCert.getSubjectX500Principal()) == false) {
-                throw new ValidatorException
-                        (ValidatorException.T_NAME_CHAINING, cert);
-            }
-
-            // check signature
-            try {
-                cert.verify(issuerCert.getPublicKey());
-            } catch (GeneralSecurityException e) {
-                throw new ValidatorException
-                        (ValidatorException.T_SIGNATURE_ERROR, cert, e);
-            }
-
-            // check extensions for CA certs
-            if (i != 0) {
-                maxPathLength = checkExtensions(cert, maxPathLength);
-            }
-        }
-
-        return chain;
-    }
-
-    private int checkExtensions(X509Certificate cert, int maxPathLen)
-            throws CertificateException {
-        Set<String> critSet = cert.getCriticalExtensionOIDs();
-        if (critSet == null) {
-            critSet = Collections.<String>emptySet();
-        }
-
-        // Check the basic constraints extension
-        int pathLenConstraint =
-                checkBasicConstraints(cert, critSet, maxPathLen);
-
-        // Check the key usage and extended key usage extensions
-        checkKeyUsage(cert, critSet);
-
-        // check Netscape certificate type extension
-        checkNetscapeCertType(cert, critSet);
-
-        if (!critSet.isEmpty()) {
-            throw new ValidatorException
-                ("Certificate contains unknown critical extensions: " + critSet,
-                ValidatorException.T_CA_EXTENSIONS, cert);
-        }
-
-        return pathLenConstraint;
-    }
-
-    private void checkNetscapeCertType(X509Certificate cert,
-            Set<String> critSet) throws CertificateException {
-        if (variant.equals(VAR_GENERIC)) {
-            // nothing
-        } else if (variant.equals(VAR_TLS_CLIENT)
-                || variant.equals(VAR_TLS_SERVER)) {
-            if (getNetscapeCertTypeBit(cert, NSCT_SSL_CA) == false) {
-                throw new ValidatorException
-                        ("Invalid Netscape CertType extension for SSL CA "
-                        + "certificate",
-                        ValidatorException.T_CA_EXTENSIONS, cert);
-            }
-            critSet.remove(OID_NETSCAPE_CERT_TYPE);
-        } else if (variant.equals(VAR_CODE_SIGNING)
-                || variant.equals(VAR_JCE_SIGNING)) {
-            if (getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING_CA) == false) {
-                throw new ValidatorException
-                        ("Invalid Netscape CertType extension for code "
-                        + "signing CA certificate",
-                        ValidatorException.T_CA_EXTENSIONS, cert);
-            }
-            critSet.remove(OID_NETSCAPE_CERT_TYPE);
-        } else {
-            throw new CertificateException("Unknown variant " + variant);
-        }
-    }
-
-    /**
-     * Get the value of the specified bit in the Netscape certificate type
-     * extension. If the extension is not present at all, we return true.
-     */
-    static boolean getNetscapeCertTypeBit(X509Certificate cert, String type) {
-        try {
-            NetscapeCertTypeExtension ext;
-            if (cert instanceof X509CertImpl) {
-                X509CertImpl certImpl = (X509CertImpl)cert;
-                ObjectIdentifier oid = OBJID_NETSCAPE_CERT_TYPE;
-                ext = (NetscapeCertTypeExtension)certImpl.getExtension(oid);
-                if (ext == null) {
-                    return true;
-                }
-            } else {
-                byte[] extVal = cert.getExtensionValue(OID_NETSCAPE_CERT_TYPE);
-                if (extVal == null) {
-                    return true;
-                }
-                DerInputStream in = new DerInputStream(extVal);
-                byte[] encoded = in.getOctetString();
-                encoded = new DerValue(encoded).getUnalignedBitString()
-                                                                .toByteArray();
-                ext = new NetscapeCertTypeExtension(encoded);
-            }
-            Boolean val = (Boolean)ext.get(type);
-            return val.booleanValue();
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    private int checkBasicConstraints(X509Certificate cert,
-            Set<String> critSet, int maxPathLen) throws CertificateException {
-
-        critSet.remove(OID_BASIC_CONSTRAINTS);
-        int constraints = cert.getBasicConstraints();
-        // reject, if extension missing or not a CA (constraints == -1)
-        if (constraints < 0) {
-            throw new ValidatorException("End user tried to act as a CA",
-                ValidatorException.T_CA_EXTENSIONS, cert);
-        }
-
-        // if the certificate is self-issued, ignore the pathLenConstraint
-        // checking.
-        if (!X509CertImpl.isSelfIssued(cert)) {
-            if (maxPathLen <= 0) {
-                throw new ValidatorException("Violated path length constraints",
-                    ValidatorException.T_CA_EXTENSIONS, cert);
-            }
-
-            maxPathLen--;
-        }
-
-        if (maxPathLen > constraints) {
-            maxPathLen = constraints;
-        }
-
-        return maxPathLen;
-    }
-
-    /*
-     * Verify the key usage and extended key usage for intermediate
-     * certificates.
-     */
-    private void checkKeyUsage(X509Certificate cert, Set<String> critSet)
-            throws CertificateException {
-
-        critSet.remove(OID_KEY_USAGE);
-        // EKU irrelevant in CA certificates
-        critSet.remove(OID_EXTENDED_KEY_USAGE);
-
-        // check key usage extension
-        boolean[] keyUsageInfo = cert.getKeyUsage();
-        if (keyUsageInfo != null) {
-            // keyUsageInfo[5] is for keyCertSign.
-            if ((keyUsageInfo.length < 6) || (keyUsageInfo[5] == false)) {
-                throw new ValidatorException
-                        ("Wrong key usage: expected keyCertSign",
-                        ValidatorException.T_CA_EXTENSIONS, cert);
-            }
-        }
-    }
-
-    /**
-     * Build a trusted certificate chain. This method always returns a chain
-     * with a trust anchor as the final cert in the chain. If no trust anchor
-     * could be found, a CertificateException is thrown.
-     */
-    private X509Certificate[] buildTrustedChain(X509Certificate[] chain)
-            throws CertificateException {
-        List<X509Certificate> c = new ArrayList<X509Certificate>(chain.length);
-        // scan chain starting at EE cert
-        // if a trusted certificate is found, append it and return
-        for (int i = 0; i < chain.length; i++) {
-            X509Certificate cert = chain[i];
-            X509Certificate trustedCert = getTrustedCertificate(cert);
-            if (trustedCert != null) {
-                c.add(trustedCert);
-                return c.toArray(CHAIN0);
-            }
-            c.add(cert);
-        }
-
-        // check if we can append a trusted cert
-        X509Certificate cert = chain[chain.length - 1];
-        X500Principal subject = cert.getSubjectX500Principal();
-        X500Principal issuer = cert.getIssuerX500Principal();
-        List<X509Certificate> list = trustedX500Principals.get(issuer);
-        if (list != null) {
-            X509Certificate trustedCert = list.iterator().next();
-            c.add(trustedCert);
-            return c.toArray(CHAIN0);
-        }
-
-        // no trusted cert found, error
-        throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR);
-    }
-
-    /**
-     * Return a trusted certificate that matches the input certificate,
-     * or null if no such certificate can be found. This method also handles
-     * cases where a CA re-issues a trust anchor with the same public key and
-     * same subject and issuer names but a new validity period, etc.
-     */
-    private X509Certificate getTrustedCertificate(X509Certificate cert) {
-        Principal certSubjectName = cert.getSubjectX500Principal();
-        List<X509Certificate> list = trustedX500Principals.get(certSubjectName);
-        if (list == null) {
-            return null;
-        }
-
-        Principal certIssuerName = cert.getIssuerX500Principal();
-        PublicKey certPublicKey = cert.getPublicKey();
-
-        for (X509Certificate mycert : list) {
-            if (mycert.equals(cert)) {
-                return cert;
-            }
-            if (!mycert.getIssuerX500Principal().equals(certIssuerName)) {
-                continue;
-            }
-            if (!mycert.getPublicKey().equals(certPublicKey)) {
-                continue;
-            }
-
-            // All tests pass, this must be the one to use...
-            return mycert;
-        }
-        return null;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/validator/Validator.java b/ojluni/src/main/java/sun/security/validator/Validator.java
deleted file mode 100644
index 863566c..0000000
--- a/ojluni/src/main/java/sun/security/validator/Validator.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.validator;
-
-import java.util.*;
-
-import java.security.AlgorithmConstraints;
-import java.security.KeyStore;
-import java.security.cert.*;
-
-/**
- * Validator abstract base class. Concrete classes are instantiated by calling
- * one of the getInstance() methods. All methods defined in this class
- * must be safe for concurrent use by multiple threads.<p>
- *
- * The model is that a Validator instance is created specifying validation
- * settings, such as trust anchors or PKIX parameters. Then one or more
- * paths are validated using those parameters. In some cases, additional
- * information can be provided per path validation. This is independent of
- * the validation parameters and currently only used for TLS server validation.
- * <p>
- * Path validation is performed by calling one of the validate() methods. It
- * specifies a suggested path to be used for validation if available, or only
- * the end entity certificate otherwise. Optionally additional certificates can
- * be specified that the caller believes could be helpful. Implementations are
- * free to make use of this information or validate the path using other means.
- * validate() also checks that the end entity certificate is suitable for the
- * intended purpose as described below.
- *
- * <p>There are two orthogonal parameters to select the Validator
- * implementation: type and variant. Type selects the validation algorithm.
- * Currently supported are TYPE_SIMPLE and TYPE_PKIX. See SimpleValidator and
- * PKIXValidator for details.
- * <p>
- * Variant controls additional extension checks. Currently supported are
- * five variants:
- * <ul>
- * <li>VAR_GENERIC (no additional checks),
- * <li>VAR_TLS_CLIENT (TLS client specific checks)
- * <li>VAR_TLS_SERVER (TLS server specific checks), and
- * <li>VAR_CODE_SIGNING (code signing specific checks).
- * <li>VAR_JCE_SIGNING (JCE code signing specific checks).
- * <li>VAR_TSA_SERVER (TSA server specific checks).
- * <li>VAR_PLUGIN_CODE_SIGNING (Plugin/WebStart code signing specific checks).
- * </ul>
- * See EndEntityChecker for more information.
- * <p>
- * Examples:
- * <pre>
- *   // instantiate validator specifying type, variant, and trust anchors
- *   Validator validator = Validator.getInstance(Validator.TYPE_PKIX,
- *                                               Validator.VAR_TLS_CLIENT,
- *                                               trustedCerts);
- *   // validate one or more chains using the validator
- *   validator.validate(chain); // throws CertificateException if failed
- * </pre>
- *
- * @see SimpleValidator
- * @see PKIXValidator
- * @see EndEntityChecker
- *
- * @author Andreas Sterbenz
- */
-public abstract class Validator {
-
-    final static X509Certificate[] CHAIN0 = {};
-
-    /**
-     * Constant for a validator of type Simple.
-     * @see #getInstance
-     */
-    public final static String TYPE_SIMPLE = "Simple";
-
-    /**
-     * Constant for a validator of type PKIX.
-     * @see #getInstance
-     */
-    public final static String TYPE_PKIX = "PKIX";
-
-    /**
-     * Constant for a Generic variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_GENERIC = "generic";
-
-    /**
-     * Constant for a Code Signing variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_CODE_SIGNING = "code signing";
-
-    /**
-     * Constant for a JCE Code Signing variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_JCE_SIGNING = "jce signing";
-
-    /**
-     * Constant for a TLS Client variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_TLS_CLIENT = "tls client";
-
-    /**
-     * Constant for a TLS Server variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_TLS_SERVER = "tls server";
-
-    /**
-     * Constant for a TSA Server variant of a validator.
-     * @see #getInstance
-     */
-    public final static String VAR_TSA_SERVER = "tsa server";
-
-    /**
-     * Constant for a Code Signing variant of a validator for use by
-     * the J2SE Plugin/WebStart code.
-     * @see #getInstance
-     */
-    public final static String VAR_PLUGIN_CODE_SIGNING = "plugin code signing";
-
-    final EndEntityChecker endEntityChecker;
-    final String variant;
-
-    /**
-     * @deprecated
-     * @see #setValidationDate
-     */
-    @Deprecated
-    volatile Date validationDate;
-
-    Validator(String type, String variant) {
-        this.variant = variant;
-        endEntityChecker = EndEntityChecker.getInstance(type, variant);
-    }
-
-    /**
-     * Get a new Validator instance using the trusted certificates from the
-     * specified KeyStore as trust anchors.
-     */
-    public static Validator getInstance(String type, String variant,
-            KeyStore ks) {
-        return getInstance(type, variant, KeyStores.getTrustedCerts(ks));
-    }
-
-    /**
-     * Get a new Validator instance using the Set of X509Certificates as trust
-     * anchors.
-     */
-    public static Validator getInstance(String type, String variant,
-            Collection<X509Certificate> trustedCerts) {
-        if (type.equals(TYPE_SIMPLE)) {
-            return new SimpleValidator(variant, trustedCerts);
-        } else if (type.equals(TYPE_PKIX)) {
-            return new PKIXValidator(variant, trustedCerts);
-        } else {
-            throw new IllegalArgumentException
-                ("Unknown validator type: " + type);
-        }
-    }
-
-    /**
-     * Get a new Validator instance using the provided PKIXBuilderParameters.
-     * This method can only be used with the PKIX validator.
-     */
-    public static Validator getInstance(String type, String variant,
-            PKIXBuilderParameters params) {
-        if (type.equals(TYPE_PKIX) == false) {
-            throw new IllegalArgumentException
-                ("getInstance(PKIXBuilderParameters) can only be used "
-                + "with PKIX validator");
-        }
-        return new PKIXValidator(variant, params);
-    }
-
-    /**
-     * Validate the given certificate chain.
-     */
-    public final X509Certificate[] validate(X509Certificate[] chain)
-            throws CertificateException {
-        return validate(chain, null, null);
-    }
-
-    /**
-     * Validate the given certificate chain. If otherCerts is non-null, it is
-     * a Collection of additional X509Certificates that could be helpful for
-     * path building.
-     */
-    public final X509Certificate[] validate(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts) throws CertificateException {
-        return validate(chain, otherCerts, null);
-    }
-
-    /**
-     * Validate the given certificate chain. If otherCerts is non-null, it is
-     * a Collection of additional X509Certificates that could be helpful for
-     * path building.
-     * <p>
-     * Parameter is an additional parameter with variant specific meaning.
-     * Currently, it is only defined for TLS_SERVER variant validators, where
-     * it must be non null and the name of the TLS key exchange algorithm being
-     * used (see JSSE X509TrustManager specification). In the future, it
-     * could be used to pass in a PKCS#7 object for code signing to check time
-     * stamps.
-     * <p>
-     * @return a non-empty chain that was used to validate the path. The
-     * end entity cert is at index 0, the trust anchor at index n-1.
-     */
-    public final X509Certificate[] validate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
-        return validate(chain, otherCerts, null, parameter);
-    }
-
-    /**
-     * Validate the given certificate chain.
-     *
-     * @param chain the target certificate chain
-     * @param otherCerts a Collection of additional X509Certificates that
-     *        could be helpful for path building (or null)
-     * @param constraints algorithm constraints for certification path
-     *        processing
-     * @param parameter an additional parameter with variant specific meaning.
-     *        Currently, it is only defined for TLS_SERVER variant validators,
-     *        where it must be non null and the name of the TLS key exchange
-     *        algorithm being used (see JSSE X509TrustManager specification).
-     *        In the future, it could be used to pass in a PKCS#7 object for
-     *        code signing to check time stamps.
-     * @return a non-empty chain that was used to validate the path. The
-     *        end entity cert is at index 0, the trust anchor at index n-1.
-     */
-    public final X509Certificate[] validate(X509Certificate[] chain,
-                Collection<X509Certificate> otherCerts,
-                AlgorithmConstraints constraints,
-                Object parameter) throws CertificateException {
-        chain = engineValidate(chain, otherCerts, constraints, parameter);
-
-        // omit EE extension check if EE cert is also trust anchor
-        if (chain.length > 1) {
-            endEntityChecker.check(chain[0], parameter);
-        }
-
-        return chain;
-    }
-
-    abstract X509Certificate[] engineValidate(X509Certificate[] chain,
-                Collection<X509Certificate> otherCerts,
-                AlgorithmConstraints constraints,
-                Object parameter) throws CertificateException;
-
-    /**
-     * Returns an immutable Collection of the X509Certificates this instance
-     * uses as trust anchors.
-     */
-    public abstract Collection<X509Certificate> getTrustedCertificates();
-
-    /**
-     * Set the date to be used for subsequent validations. NOTE that
-     * this is not a supported API, it is provided to simplify
-     * writing tests only.
-     *
-     * @deprecated
-     */
-    @Deprecated
-    public void setValidationDate(Date validationDate) {
-        this.validationDate = validationDate;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/validator/ValidatorException.java b/ojluni/src/main/java/sun/security/validator/ValidatorException.java
deleted file mode 100644
index db4b056..0000000
--- a/ojluni/src/main/java/sun/security/validator/ValidatorException.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.validator;
-
-import java.security.cert.*;
-
-/**
- * ValidatorException thrown by the Validator. It has optional fields that
- * allow better error diagnostics.
- *
- * @author Andreas Sterbenz
- */
-public class ValidatorException extends CertificateException {
-
-    private static final long serialVersionUID = -2836879718282292155L;
-
-    public final static Object T_NO_TRUST_ANCHOR =
-        "No trusted certificate found";
-
-    public final static Object T_EE_EXTENSIONS =
-        "End entity certificate extension check failed";
-
-    public final static Object T_CA_EXTENSIONS =
-        "CA certificate extension check failed";
-
-    public final static Object T_CERT_EXPIRED =
-        "Certificate expired";
-
-    public final static Object T_SIGNATURE_ERROR =
-        "Certificate signature validation failed";
-
-    public final static Object T_NAME_CHAINING =
-        "Certificate chaining error";
-
-    public final static Object T_ALGORITHM_DISABLED =
-        "Certificate signature algorithm disabled";
-
-    public final static Object T_UNTRUSTED_CERT =
-        "Untrusted certificate";
-
-    private Object type;
-    private X509Certificate cert;
-
-    public ValidatorException(String msg) {
-        super(msg);
-    }
-
-    public ValidatorException(String msg, Throwable cause) {
-        super(msg);
-        initCause(cause);
-    }
-
-    public ValidatorException(Object type) {
-        this(type, null);
-    }
-
-    public ValidatorException(Object type, X509Certificate cert) {
-        super((String)type);
-        this.type = type;
-        this.cert = cert;
-    }
-
-    public ValidatorException(Object type, X509Certificate cert,
-            Throwable cause) {
-        this(type, cert);
-        initCause(cause);
-    }
-
-    public ValidatorException(String msg, Object type, X509Certificate cert) {
-        super(msg);
-        this.type = type;
-        this.cert = cert;
-    }
-
-    public ValidatorException(String msg, Object type, X509Certificate cert,
-            Throwable cause) {
-        this(msg, type, cert);
-        initCause(cause);
-    }
-
-    /**
-     * Get the type of the failure (one of the T_XXX constants), if
-     * available. This may be helpful when designing a user interface.
-     */
-    public Object getErrorType() {
-        return type;
-    }
-
-    /**
-     * Get the certificate causing the exception, if available.
-     */
-    public X509Certificate getErrorCertificate() {
-        return cert;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
index 0258e5a..9a89dc0 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
@@ -196,7 +196,7 @@
         return isAlpha(c) || isNumeric(c);
     }
 
-    static boolean isAlphaNumericString(String s) {
+    public static boolean isAlphaNumericString(String s) {
         int len = s.length();
         for (int i = 0; i < len; i++) {
             if (!isAlphaNumeric(s.charAt(i))) {
diff --git a/ojluni/src/main/native/FileInputStream.c b/ojluni/src/main/native/FileInputStream.c
index 0501c97..a5a54f5 100644
--- a/ojluni/src/main/native/FileInputStream.c
+++ b/ojluni/src/main/native/FileInputStream.c
@@ -63,7 +63,7 @@
 }
 
 JNIEXPORT void JNICALL
-FileInputStream_open(JNIEnv *env, jobject this, jstring path) {
+FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
     fileOpen(env, this, path, fis_fd, O_RDONLY);
 }
 
@@ -133,7 +133,7 @@
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(FileInputStream, open, "(Ljava/lang/String;)V"),
+  NATIVE_METHOD(FileInputStream, open0, "(Ljava/lang/String;)V"),
   NATIVE_METHOD(FileInputStream, skip0, "(J)J"),
   NATIVE_METHOD(FileInputStream, available0, "()I"),
 };
diff --git a/ojluni/src/main/native/FileOutputStream_md.c b/ojluni/src/main/native/FileOutputStream_md.c
index 642cef6..615627a 100644
--- a/ojluni/src/main/native/FileOutputStream_md.c
+++ b/ojluni/src/main/native/FileOutputStream_md.c
@@ -52,14 +52,14 @@
 
 
 JNIEXPORT void JNICALL
-FileOutputStream_open(JNIEnv *env, jobject this,
+FileOutputStream_open0(JNIEnv *env, jobject this,
                                    jstring path, jboolean append) {
     fileOpen(env, this, path, fos_fd,
              O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(FileOutputStream, open, "(Ljava/lang/String;Z)V"),
+  NATIVE_METHOD(FileOutputStream, open0, "(Ljava/lang/String;Z)V"),
 };
 
 void register_java_io_FileOutputStream(JNIEnv* env) {
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/ObjectInputStream.c b/ojluni/src/main/native/ObjectInputStream.c
index 55cebba..95eeec4 100644
--- a/ojluni/src/main/native/ObjectInputStream.c
+++ b/ojluni/src/main/native/ObjectInputStream.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2000, 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
diff --git a/ojluni/src/main/native/ObjectOutputStream.c b/ojluni/src/main/native/ObjectOutputStream.c
index d74e31f..25ee3bf 100644
--- a/ojluni/src/main/native/ObjectOutputStream.c
+++ b/ojluni/src/main/native/ObjectOutputStream.c
@@ -192,4 +192,3 @@
 void register_java_io_ObjectOutputStream(JNIEnv* env) {
     jniRegisterNativeMethods(env, "java/io/ObjectOutputStream", gMethods, NELEM(gMethods));
 }
-
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index 5f67d8d..9d40c16 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -25,19 +25,19 @@
 
 #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);
 extern void register_java_io_FileDescriptor(JNIEnv*);
 extern void register_java_io_FileInputStream(JNIEnv*);
 extern void register_java_io_FileOutputStream(JNIEnv*);
-extern void register_java_io_FileSystem(JNIEnv*);
 extern void register_java_io_ObjectInputStream(JNIEnv*);
 extern void register_java_io_ObjectOutputStream(JNIEnv*);
 extern void register_java_io_ObjectStreamClass(JNIEnv*);
@@ -100,7 +100,6 @@
     register_java_util_zip_Deflater(env);
     register_java_util_zip_CRC32(env);
     register_java_util_zip_Adler32(env);
-    register_java_io_FileSystem(env);
     register_sun_nio_ch_IOUtil(env);
     register_sun_nio_ch_FileChannelImpl(env);
     register_sun_nio_ch_FileDispatcherImpl(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 f0f199a..ff82754 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -36,7 +36,6 @@
     NativeThread.c \
     FileKey.c \
     UnixFileSystem_md.c \
-    FileSystem_md.c \
     ObjectStreamClass.c \
     ObjectOutputStream.c \
     ObjectInputStream.c \
@@ -55,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 1796b31..8a1cb4f 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -22,6 +22,7 @@
     ojluni/src/main/java/java/io/DataInputStream.java \
     ojluni/src/main/java/java/io/DataOutput.java \
     ojluni/src/main/java/java/io/DataOutputStream.java \
+    ojluni/src/main/java/java/io/DefaultFileSystem.java \
     ojluni/src/main/java/java/io/DeleteOnExitHook.java \
     ojluni/src/main/java/java/io/EOFException.java \
     ojluni/src/main/java/java/io/ExpiringCache.java \
@@ -186,9 +187,11 @@
     ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java \
     ojluni/src/main/java/java/lang/ReflectiveOperationException.java \
     ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java \
+    ojluni/src/main/java/java/lang/reflect/MalformedParametersException.java \
     ojluni/src/main/java/java/lang/reflect/Member.java \
     ojluni/src/main/java/java/lang/reflect/Method.java \
     ojluni/src/main/java/java/lang/reflect/Modifier.java \
+    ojluni/src/main/java/java/lang/reflect/Parameter.java \
     ojluni/src/main/java/java/lang/reflect/ParameterizedType.java \
     ojluni/src/main/java/java/lang/reflect/Proxy.java \
     ojluni/src/main/java/java/lang/reflect/ReflectPermission.java \
@@ -1161,6 +1164,8 @@
     ojluni/src/main/java/sun/misc/FloatingDecimal.java \
     ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java \
     ojluni/src/main/java/java/lang/invoke/MethodHandle.java \
+    ojluni/src/main/java/java/lang/invoke/MethodHandles.java \
+    ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java \
     ojluni/src/main/java/java/lang/invoke/MethodHandleInfo.java \
     ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java \
     ojluni/src/main/java/java/lang/invoke/MethodType.java \
@@ -1176,6 +1181,7 @@
     ojluni/src/main/java/java/util/spi/CurrencyNameProvider.java \
     ojluni/src/main/java/java/util/spi/LocaleNameProvider.java \
     ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java \
+    ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java \
     ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java \
     ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java \
     ojluni/src/main/java/jdk/net/NetworkPermission.java \
@@ -1184,6 +1190,7 @@
     ojluni/src/main/java/sun/invoke/empty/Empty.java \
     ojluni/src/main/java/sun/invoke/util/BytecodeDescriptor.java \
     ojluni/src/main/java/sun/invoke/util/Wrapper.java \
+    ojluni/src/main/java/sun/invoke/util/VerifyAccess.java \
     ojluni/src/main/java/sun/misc/ASCIICaseInsensitiveComparator.java \
     ojluni/src/main/java/sun/misc/BASE64Decoder.java \
     ojluni/src/main/java/sun/misc/BASE64Encoder.java \
@@ -1201,7 +1208,6 @@
     ojluni/src/main/java/sun/misc/Hashing.java \
     ojluni/src/main/java/sun/misc/HexDumpEncoder.java \
     ojluni/src/main/java/sun/misc/InvalidJarIndexException.java \
-    ojluni/src/main/java/sun/misc/IoTrace.java \
     ojluni/src/main/java/sun/misc/IOUtils.java \
     ojluni/src/main/java/sun/misc/JarIndex.java \
     ojluni/src/main/java/sun/misc/JavaIOFileDescriptorAccess.java \
@@ -1501,12 +1507,6 @@
     ojluni/src/main/java/sun/security/util/SecurityConstants.java \
     ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java \
     ojluni/src/main/java/sun/security/util/UntrustedCertificates.java \
-    ojluni/src/main/java/sun/security/validator/EndEntityChecker.java \
-    ojluni/src/main/java/sun/security/validator/KeyStores.java \
-    ojluni/src/main/java/sun/security/validator/PKIXValidator.java \
-    ojluni/src/main/java/sun/security/validator/SimpleValidator.java \
-    ojluni/src/main/java/sun/security/validator/ValidatorException.java \
-    ojluni/src/main/java/sun/security/validator/Validator.java \
     ojluni/src/main/java/sun/security/x509/AccessDescription.java \
     ojluni/src/main/java/sun/security/x509/AlgorithmId.java \
     ojluni/src/main/java/sun/security/x509/AttributeNameEnumeration.java \
@@ -1608,22 +1608,24 @@
     ojluni/src/main/java/sun/util/logging/PlatformLogger.java \
     ojluni/src/main/java/sun/util/ResourceBundleEnumeration.java \
     ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java \
-    $(openjdk_javadoc_files)
+    $(openjdk_javadoc_files) \
+    $(openjdk_lambda_stub_files)
 
 # Stubs needed to satisfy javac's dependencies when compiling lambda code. These are
 # not used on Android devices or required by the Jack compiler.
 #
-# The stub files in openjdk_lambda_duplicate_stub_files are present in core-oj as
-# well, and need to be included here to support compiling against older SDKs and the
-# like. This additional bit of ugliness if required to avoid a circular dependency
-# between core-all and these stubs. Eventually, all of these stubs will become
-# "duplicates" and then that list can be renamed to "openjdk_lambda_stub_files".
+# On aosp/master:
+# openjdk_lambda_stub_files : These are included in core-oj as stubs
+# openjdk_lambda_duplicate_stub_files : These contain complete implementations in core-oj.
+#
+# On older platforms : Both sets of stub files are used and core-oj does not contain
+# any of these classes.
 openjdk_lambda_stub_files := \
     ojluni/src/lambda/java/java/lang/invoke/CallSite.java \
     ojluni/src/lambda/java/java/lang/invoke/LambdaMetafactory.java \
-    ojluni/src/lambda/java/java/lang/invoke/MethodHandles.java \
     ojluni/src/lambda/java/java/lang/invoke/SerializedLambda.java
 openjdk_lambda_duplicate_stub_files := \
+    ojluni/src/lambda/java/java/lang/invoke/MethodHandles.java \
     ojluni/src/lambda/java/java/lang/invoke/LambdaConversionException.java \
     ojluni/src/lambda/java/java/lang/invoke/MethodHandle.java \
     ojluni/src/lambda/java/java/lang/invoke/MethodType.java \
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index d2f8b67..1f6756e 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -230,7 +230,10 @@
         provide("MessageDigest", "SHA-384");
         provide("MessageDigest", "SHA-512");
         provide("Policy", "JavaPolicy");
-        provide("SSLContext", "SSLv3");
+        // Android does not support SSLv3
+        if (IS_RI) {
+            provide("SSLContext", "SSLv3");
+        }
         provide("SSLContext", "TLSv1");
         provide("SSLContext", "TLSv1.1");
         provide("SSLContext", "TLSv1.2");
@@ -290,7 +293,10 @@
 
         // Not documented as in RI 6 but mentioned in Standard Names
         provide("AlgorithmParameters", "PBE");
-        provide("SSLContext", "SSL");
+        // Android does not support SSLv3
+        if (IS_RI) {
+            provide("SSLContext", "SSL");
+        }
         provide("SSLContext", "TLS");
 
         // Not documented as in RI 6 but that exist in RI 6
@@ -580,8 +586,6 @@
             provideSslContextEnabledProtocols("TLSv1.2", TLSVersion.SSLv3, TLSVersion.TLSv12);
             provideSslContextEnabledProtocols("Default", TLSVersion.SSLv3, TLSVersion.TLSv1);
         } else {
-            provideSslContextEnabledProtocols("SSL", TLSVersion.SSLv3, TLSVersion.TLSv12);
-            provideSslContextEnabledProtocols("SSLv3", TLSVersion.SSLv3, TLSVersion.TLSv12);
             provideSslContextEnabledProtocols("TLS", TLSVersion.TLSv1, TLSVersion.TLSv12);
             provideSslContextEnabledProtocols("TLSv1", TLSVersion.TLSv1, TLSVersion.TLSv12);
             provideSslContextEnabledProtocols("TLSv1.1", TLSVersion.TLSv1, TLSVersion.TLSv12);
@@ -593,9 +597,6 @@
     public static final String SSL_CONTEXT_PROTOCOLS_DEFAULT = "Default";
     public static final Set<String> SSL_CONTEXT_PROTOCOLS = new HashSet<String>(Arrays.asList(
         SSL_CONTEXT_PROTOCOLS_DEFAULT,
-        "SSL",
-        // "SSLv2",
-        "SSLv3",
         "TLS",
         "TLSv1",
         "TLSv1.1",
@@ -619,8 +620,6 @@
     }
 
     public static final Set<String> SSL_SOCKET_PROTOCOLS = new HashSet<String>(Arrays.asList(
-        // "SSLv2",
-        "SSLv3",
         "TLSv1",
         "TLSv1.1",
         "TLSv1.2"));
@@ -735,11 +734,7 @@
         addBoth(   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
         addBoth(   "TLS_RSA_WITH_AES_128_CBC_SHA");
         addBoth(   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
-        addBoth(   "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
-        addBoth(   "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
-        addBoth(   "SSL_RSA_WITH_RC4_128_SHA");
         addBoth(   "SSL_RSA_WITH_3DES_EDE_CBC_SHA");
-        addBoth(   "SSL_RSA_WITH_RC4_128_MD5");
 
         // TLSv1.2 cipher suites
         addBoth(   "TLS_RSA_WITH_AES_128_CBC_SHA256");
@@ -762,7 +757,6 @@
         addOpenSsl("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
 
         // Pre-Shared Key (PSK) cipher suites
-        addOpenSsl("TLS_PSK_WITH_RC4_128_SHA");
         addOpenSsl("TLS_PSK_WITH_AES_128_CBC_SHA");
         addOpenSsl("TLS_PSK_WITH_AES_256_CBC_SHA");
         addOpenSsl("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA");
@@ -801,6 +795,12 @@
         addRi(     "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
         addNeither("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384");
 
+        // Android does not have RC4 support
+        addRi(     "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
+        addRi(     "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
+        addRi(     "SSL_RSA_WITH_RC4_128_SHA");
+        addRi(     "SSL_RSA_WITH_RC4_128_MD5");
+
         // Dropped
         addNeither("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
         addNeither("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
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);
+        }
+    }
+}