Merge "Test that confirms a socket can be closed during connect()"
diff --git a/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java
index 02d8f97..e84c287 100644
--- a/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java
@@ -18,14 +18,14 @@
 
 import com.google.caliper.SimpleBenchmark;
 
-import java.util.Locale;
-import java.util.TimeZone;
+import android.icu.util.ULocale;
+import android.icu.util.TimeZone;
 
 import static libcore.icu.DateIntervalFormat.*;
 
 public class DateIntervalFormatBenchmark extends SimpleBenchmark {
   public void timeDateIntervalFormat_formatDateRange_DATE(int reps) throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY;
 
@@ -35,7 +35,7 @@
   }
 
   public void timeDateIntervalFormat_formatDateRange_TIME(int reps) throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR;
 
@@ -45,7 +45,7 @@
   }
 
   public void timeDateIntervalFormat_formatDateRange_DATE_TIME(int reps) throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_24HOUR;
 
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
index 4b606e6..59e28e2 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -18,6 +18,8 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Provides access to some VM-specific debug features. Though this class and
@@ -389,4 +391,57 @@
      * @param data the array into which the stats are written.
      */
     public static native void getHeapSpaceStats(long[] data);
+
+    /* Map from the names of the runtime stats supported by getRuntimeStat() to their IDs */
+    private static final HashMap<String, Integer> runtimeStatsMap = new HashMap<>();
+
+    static {
+        runtimeStatsMap.put("art.gc.gc-count", 0);
+        runtimeStatsMap.put("art.gc.gc-time", 1);
+        runtimeStatsMap.put("art.gc.bytes-allocated", 2);
+        runtimeStatsMap.put("art.gc.bytes-freed", 3);
+        runtimeStatsMap.put("art.gc.blocking-gc-count", 4);
+        runtimeStatsMap.put("art.gc.blocking-gc-time", 5);
+        runtimeStatsMap.put("art.gc.gc-count-rate-histogram", 6);
+        runtimeStatsMap.put("art.gc.blocking-gc-count-rate-histogram", 7);
+    }
+
+    /**
+     * Returns the value of a particular runtime statistic or {@code null} if no
+     * such runtime statistic exists.
+     *
+     * @param statName
+     *            the name of the runtime statistic to look up.
+     * @return the value of the runtime statistic.
+     */
+    public static String getRuntimeStat(String statName) {
+        if (statName == null) {
+            throw new NullPointerException("statName == null");
+        }
+        Integer statId = runtimeStatsMap.get(statName);
+        if (statId != null) {
+            return getRuntimeStatInternal(statId);
+        }
+        return null;
+    }
+
+    /**
+     * Returns a map of the names/values of the runtime statistics
+     * that {@link #getRuntimeStat()} supports.
+     *
+     * @return a map of the names/values of the supported runtime statistics.
+     */
+    public static Map<String, String> getRuntimeStats() {
+        HashMap<String, String> map = new HashMap<>();
+        String[] values = getRuntimeStatsInternal();
+        for (String name : runtimeStatsMap.keySet()) {
+            int id = runtimeStatsMap.get(name);
+            String value = values[id];
+            map.put(name, value);
+        }
+        return map;
+    }
+
+    private static native String getRuntimeStatInternal(int statId);
+    private static native String[] getRuntimeStatsInternal();
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FileTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FileTest.java
index 5cc88f4..77812ed 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FileTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FileTest.java
@@ -227,8 +227,8 @@
             assertEquals("wrong result 4", ref1.getPath(), file4.getPath());
         }
 
-        File ref2 = new File("/lib/content-types.properties");
-        File file5 = new File("/", "lib/content-types.properties");
+        File ref2 = new File("/lib/test_112270.properties");
+        File file5 = new File("/", "lib/test_112270.properties");
         assertEquals("wrong result 5", ref2.getPath(), file5.getPath());
     }
 
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/cert/X509CertificateTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/cert/X509CertificateTest.java
index 64bfbb3..26403f5 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/cert/X509CertificateTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/cert/X509CertificateTest.java
@@ -20,7 +20,7 @@
  * @version $Revision$
  */
 
-package tests.api.javax.security.cert;
+package org.apache.harmony.tests.javax.security.cert;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
diff --git a/libart/src/main/java/dalvik/system/VMStack.java b/libart/src/main/java/dalvik/system/VMStack.java
index ee0a0db..b69ab60 100644
--- a/libart/src/main/java/dalvik/system/VMStack.java
+++ b/libart/src/main/java/dalvik/system/VMStack.java
@@ -48,11 +48,10 @@
     native public static Class<?> getStackClass2();
 
     /**
-     * Returns the first ClassLoader on the call stack that isn't either of
-     * the passed-in ClassLoaders.
+     * Returns the first ClassLoader on the call stack that isn't the
+     * bootstrap class loader.
      */
-    public native static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap,
-                                                               ClassLoader system);
+    public native static ClassLoader getClosestUserClassLoader();
 
     /**
      * Retrieves the stack trace from the specified thread.
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 4ea0bb5..1072ce8 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -124,16 +124,16 @@
 
     private static final long serialVersionUID = 3206093459760846163L;
 
-    /** defining class loader, or NULL for the "bootstrap" system loader. */
+    /** defining class loader, or null for the "bootstrap" system loader. */
     private transient ClassLoader classLoader;
 
     /**
      * For array classes, the component class object for instanceof/checkcast (for String[][][],
-     * this will be String[][]). NULL for non-array classes.
+     * this will be String[][]). null for non-array classes.
      */
     private transient Class<?> componentType;
     /**
-     * DexCache of resolved constant pool entries. Will be null for certain VM-generated classes
+     * DexCache of resolved constant pool entries. Will be null for certain runtime-generated classes
      * e.g. arrays and primitive classes.
      */
     private transient DexCache dexCache;
@@ -163,7 +163,7 @@
     /** Lazily computed name of this class; always prefer calling getName(). */
     private transient String name;
 
-    /** The superclass, or NULL if this is java.lang.Object, an interface or primitive type. */
+    /** The superclass, or null if this is java.lang.Object, an interface or primitive type. */
     private transient Class<? super T> superClass;
 
     /** If class verify fails, we must return same error on subsequent tries. */
@@ -253,7 +253,8 @@
     private transient int status;
 
     private Class() {
-        // Prevent this class to be instantiated, instance should be created by JVM only
+        // Prevent this class from being instantiated,
+        // instances should be created by the runtime only.
     }
 
     /**
@@ -291,6 +292,9 @@
      * If the class has not yet been initialized and {@code shouldInitialize} is true,
      * the class will be initialized.
      *
+     * <p>If the provided {@code classLoader} is {@code null}, the bootstrap
+     * class loader will be used to load the class.
+     *
      * @throws ClassNotFoundException
      *             if the requested class cannot be found.
      * @throws LinkageError
@@ -303,7 +307,7 @@
             ClassLoader classLoader) throws ClassNotFoundException {
 
         if (classLoader == null) {
-            classLoader = ClassLoader.getSystemClassLoader();
+            classLoader = BootClassLoader.getInstance();
         }
         // Catch an Exception thrown by the underlying native code. It wraps
         // up everything inside a ClassNotFoundException, even if e.g. an
@@ -414,24 +418,7 @@
             return null;
         }
 
-        ClassLoader loader = getClassLoaderImpl();
-        if (loader == null) {
-            loader = BootClassLoader.getInstance();
-        }
-        return loader;
-    }
-
-    /**
-     * This must be provided by the VM vendor, as it is used by other provided
-     * class implementations in this package. Outside of this class, it is used
-     * by SecurityManager.classLoaderDepth(),
-     * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for
-     * this Class without doing any security checks. The bootstrap ClassLoader
-     * is returned, unlike getClassLoader() which returns null in place of the
-     * bootstrap ClassLoader.
-     */
-    ClassLoader getClassLoaderImpl() {
-        ClassLoader loader = classLoader;
+        final ClassLoader loader = classLoader;
         return loader == null ? BootClassLoader.getInstance() : loader;
     }
 
@@ -540,30 +527,12 @@
     }
 
     /**
-     * Returns the constructor with the given parameters if it is defined by this class; null
-     * otherwise. This may return a non-public member.
+     * Returns the constructor with the given parameters if it is defined by this class;
+     * {@code null} otherwise. This may return a non-public member.
      *
      * @param args the types of the parameters to the constructor.
      */
-    private Constructor<T> getDeclaredConstructorInternal(Class<?>[] args) {
-        if (directMethods != null) {
-            for (ArtMethod m : directMethods) {
-                int modifiers = m.getAccessFlags();
-                if (Modifier.isStatic(modifiers)) {
-                    // skip <clinit> which is a static constructor
-                    continue;
-                }
-                if (!Modifier.isConstructor(modifiers)) {
-                    continue;
-                }
-                if (!ArtMethod.equalConstructorParameters(m, args)) {
-                    continue;
-                }
-                return new Constructor<T>(m);
-            }
-        }
-        return null;
-    }
+    private native Constructor<T> getDeclaredConstructorInternal(Class<?>[] args);
 
     /**
      * Returns an array containing {@code Constructor} objects for all public
@@ -574,9 +543,7 @@
      * @see #getDeclaredConstructors()
      */
     public Constructor<?>[] getConstructors() {
-        ArrayList<Constructor<T>> constructors = new ArrayList();
-        getDeclaredConstructors(true, constructors);
-        return constructors.toArray(new Constructor[constructors.size()]);
+        return getDeclaredConstructorsInternal(true);
     }
 
     /**
@@ -588,27 +555,10 @@
      * @see #getConstructors()
      */
     public Constructor<?>[] getDeclaredConstructors() {
-        ArrayList<Constructor<T>> constructors = new ArrayList();
-        getDeclaredConstructors(false, constructors);
-        return constructors.toArray(new Constructor[constructors.size()]);
+        return getDeclaredConstructorsInternal(false);
     }
 
-    private void getDeclaredConstructors(boolean publicOnly, List<Constructor<T>> constructors) {
-        if (directMethods != null) {
-            for (ArtMethod m : directMethods) {
-                int modifiers = m.getAccessFlags();
-                if (!publicOnly || Modifier.isPublic(modifiers)) {
-                    if (Modifier.isStatic(modifiers)) {
-                        // skip <clinit> which is a static constructor
-                        continue;
-                    }
-                    if (Modifier.isConstructor(modifiers)) {
-                        constructors.add(new Constructor<T>(m));
-                    }
-                }
-            }
-        }
-    }
+    private native Constructor<?>[] getDeclaredConstructorsInternal(boolean publicOnly);
 
     /**
      * Returns a {@code Method} object which represents the method matching the
@@ -695,78 +645,13 @@
     }
 
     /**
-     * Returns the method if it is defined by this class; null otherwise. This may return a
+     * Returns the method if it is defined by this class; {@code null} otherwise. This may return a
      * non-public member.
      *
      * @param name the method name
      * @param args the method's parameter types
      */
-    private Method getDeclaredMethodInternal(String name, Class<?>[] args) {
-        // Covariant return types permit the class to define multiple
-        // methods with the same name and parameter types. Prefer to
-        // return a non-synthetic method in such situations. We may
-        // still return a synthetic method to handle situations like
-        // escalated visibility. We never return miranda methods that
-        // were synthesized by the VM.
-        int skipModifiers = Modifier.MIRANDA | Modifier.SYNTHETIC;
-        ArtMethod artMethodResult = null;
-        if (virtualMethods != null) {
-            for (ArtMethod m : virtualMethods) {
-                ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(m);
-                String methodName = ArtMethod.getMethodName(nonProxyMethod);
-                if (!name.equals(methodName)) {
-                    continue;
-                }
-                if (!ArtMethod.equalMethodParameters(nonProxyMethod, args)) {
-                    continue;
-                }
-                int modifiers = m.getAccessFlags();
-                if ((modifiers & skipModifiers) == 0) {
-                    return new Method(m);
-                }
-                if ((modifiers & Modifier.MIRANDA) == 0) {
-                    // Remember as potential result if it's not a miranda method.
-                    artMethodResult = m;
-                }
-            }
-        }
-        if (artMethodResult == null) {
-            if (directMethods != null) {
-                for (ArtMethod m : directMethods) {
-                    int modifiers = m.getAccessFlags();
-                    if (Modifier.isConstructor(modifiers)) {
-                        continue;
-                    }
-                    ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(m);
-                    String methodName = ArtMethod.getMethodName(nonProxyMethod);
-                    if (!name.equals(methodName)) {
-                        continue;
-                    }
-                    if (!ArtMethod.equalMethodParameters(nonProxyMethod, args)) {
-                        continue;
-                    }
-                    if ((modifiers & skipModifiers) == 0) {
-                        return new Method(m);
-                    }
-                    // Direct methods cannot be miranda methods,
-                    // so this potential result must be synthetic.
-                    artMethodResult = m;
-                }
-            }
-        }
-        if (artMethodResult == null) {
-            return null;
-        }
-        return new Method(artMethodResult);
-    }
-
-    /**
-     * Returns the overridden method if the {@code method} is a proxy method,
-     * otherwise returns the {@code method}.
-     *
-     * @hide
-     */
-    public static native ArtMethod findOverriddenMethodIfProxy(ArtMethod method);
+    private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
 
     /**
      * Returns an array containing {@code Method} objects for all methods
@@ -777,11 +662,7 @@
      * @see #getMethods()
      */
     public Method[] getDeclaredMethods() {
-        int initial_size = virtualMethods == null ? 0 : virtualMethods.length;
-        initial_size += directMethods == null ? 0 : directMethods.length;
-        ArrayList<Method> methods = new ArrayList<Method>(initial_size);
-        getDeclaredMethodsUnchecked(false, methods);
-        Method[] result = methods.toArray(new Method[methods.size()]);
+        Method[] result = getDeclaredMethodsUnchecked(false);
         for (Method m : result) {
             // Throw NoClassDefFoundError if types cannot be resolved.
             m.getReturnType();
@@ -799,30 +680,7 @@
      * @param methods A list to populate with declared methods.
      * @hide
      */
-    public void getDeclaredMethodsUnchecked(boolean publicOnly, List<Method> methods) {
-        if (virtualMethods != null) {
-            for (ArtMethod m : virtualMethods) {
-                int modifiers = m.getAccessFlags();
-                if (!publicOnly || Modifier.isPublic(modifiers)) {
-                    // Add non-miranda virtual methods.
-                    if ((modifiers & Modifier.MIRANDA) == 0) {
-                        methods.add(new Method(m));
-                    }
-                }
-            }
-        }
-        if (directMethods != null) {
-            for (ArtMethod m : directMethods) {
-                int modifiers = m.getAccessFlags();
-                if (!publicOnly || Modifier.isPublic(modifiers)) {
-                    // Add non-constructor direct/static methods.
-                    if (!Modifier.isConstructor(modifiers)) {
-                        methods.add(new Method(m));
-                    }
-                }
-            }
-        }
-    }
+    public native Method[] getDeclaredMethodsUnchecked(boolean publicOnly);
 
     /**
      * Returns an array containing {@code Method} objects for all public methods
@@ -852,11 +710,11 @@
      * superclasses, and all implemented interfaces, including overridden methods.
      */
     private void getPublicMethodsInternal(List<Method> result) {
-        getDeclaredMethodsUnchecked(true, result);
+        Collections.addAll(result, getDeclaredMethodsUnchecked(true));
         if (!isInterface()) {
             // Search superclasses, for interfaces don't search java.lang.Object.
             for (Class<?> c = superClass; c != null; c = c.superClass) {
-                c.getDeclaredMethodsUnchecked(true, result);
+                Collections.addAll(result, c.getDeclaredMethodsUnchecked(true));
             }
         }
         // Search iftable which has a flattened and uniqued list of interfaces.
@@ -864,7 +722,7 @@
         if (iftable != null) {
             for (int i = 0; i < iftable.length; i += 2) {
                 Class<?> ifc = (Class<?>) iftable[i];
-                ifc.getDeclaredMethodsUnchecked(true, result);
+                Collections.addAll(result, ifc.getDeclaredMethodsUnchecked(true));
             }
         }
     }
@@ -920,7 +778,7 @@
     public native Field[] getDeclaredFieldsUnchecked(boolean publicOnly);
 
     /**
-     * Returns the field if it is defined by this class; null otherwise. This
+     * Returns the field if it is defined by this class; {@code null} otherwise. This
      * may return a non-public member.
      */
     private native Field getDeclaredFieldInternal(String name);
@@ -1234,21 +1092,21 @@
     }
 
     /**
-     * Returns the simple name of a member or local class, or null otherwise.
+     * Returns the simple name of a member or local class, or {@code null} otherwise.
      */
     private String getInnerClassName() {
         return AnnotationAccess.getInnerClassName(this);
     }
 
     /**
-     * Returns null.
+     * Returns {@code null}.
      */
     public ProtectionDomain getProtectionDomain() {
         return null;
     }
 
     /**
-     * Returns the URL of the given resource, or null if the resource is not found.
+     * Returns the URL of the given resource, or {@code null} if the resource is not found.
      * The mapping between the resource name and the URL is managed by the class' class loader.
      *
      * @see ClassLoader
@@ -1279,8 +1137,8 @@
     }
 
     /**
-     * Returns a read-only stream for the contents of the given resource, or null if the resource
-     * is not found.
+     * Returns a read-only stream for the contents of the given resource, or {@code null} if the
+     * resource is not found.
      * The mapping between the resource name and the stream is managed by the class' class loader.
      *
      * @see ClassLoader
@@ -1311,8 +1169,8 @@
     }
 
     /**
-     * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files.
-     * All classes from any given dex file will have the same signers, but different dex
+     * Returns {@code null}. (On Android, a {@code ClassLoader} can load classes from multiple dex
+     * files. All classes from any given dex file will have the same signers, but different dex
      * files may have different signers. This does not fit well with the original
      * {@code ClassLoader}-based model of {@code getSigners}.)
      */
@@ -1542,7 +1400,7 @@
           throw new IllegalAccessException(init + " is not accessible from " + caller);
         }
         try {
-          return init.newInstance(null, init.isAccessible());
+          return init.newInstanceTwoFrames();
         } catch (InvocationTargetException e) {
           SneakyThrow.sneakyThrow(e.getCause());
           return null;  // Unreachable.
@@ -1603,7 +1461,7 @@
      * object was created by the class loader of the class.
      */
     public Package getPackage() {
-        // TODO This might be a hack, but the VM doesn't have the necessary info.
+        // TODO This might be a hack, but the runtime doesn't have the necessary info.
         ClassLoader loader = getClassLoader();
         if (loader != null) {
             String packageName = getPackageName$();
@@ -1613,7 +1471,7 @@
     }
 
     /**
-     * Returns the package name of this class. This returns null for classes in
+     * Returns the package name of this class. This returns {@code null} for classes in
      * the default package.
      *
      * @hide
diff --git a/libart/src/main/java/java/lang/String.java b/libart/src/main/java/java/lang/String.java
index 0107b6e..a5bf34c 100644
--- a/libart/src/main/java/java/lang/String.java
+++ b/libart/src/main/java/java/lang/String.java
@@ -22,12 +22,12 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.regex.Pattern;
+import libcore.util.CharsetUtils;
 import libcore.util.EmptyArray;
 
 /**
@@ -337,12 +337,12 @@
             this.offset = 0;
             this.value = new char[byteCount];
             this.count = byteCount;
-            Charsets.isoLatin1BytesToChars(data, offset, byteCount, value);
+            CharsetUtils.isoLatin1BytesToChars(data, offset, byteCount, value);
         } else if (canonicalCharsetName.equals("US-ASCII")) {
             this.offset = 0;
             this.value = new char[byteCount];
             this.count = byteCount;
-            Charsets.asciiBytesToChars(data, offset, byteCount, value);
+            CharsetUtils.asciiBytesToChars(data, offset, byteCount, value);
         } else {
             CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));
             this.offset = 0;
@@ -772,13 +772,13 @@
     public byte[] getBytes(Charset charset) {
         String canonicalCharsetName = charset.name();
         if (canonicalCharsetName.equals("UTF-8")) {
-            return Charsets.toUtf8Bytes(value, offset, count);
+            return CharsetUtils.toUtf8Bytes(value, offset, count);
         } else if (canonicalCharsetName.equals("ISO-8859-1")) {
-            return Charsets.toIsoLatin1Bytes(value, offset, count);
+            return CharsetUtils.toIsoLatin1Bytes(value, offset, count);
         } else if (canonicalCharsetName.equals("US-ASCII")) {
-            return Charsets.toAsciiBytes(value, offset, count);
+            return CharsetUtils.toAsciiBytes(value, offset, count);
         } else if (canonicalCharsetName.equals("UTF-16BE")) {
-            return Charsets.toBigEndianUtf16Bytes(value, offset, count);
+            return CharsetUtils.toBigEndianUtf16Bytes(value, offset, count);
         } else {
             CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
             ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index 7e6491d..0ac15f9 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -39,28 +39,38 @@
 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 AccessibleObject {
+    /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
+    protected int accessFlags;
+
+    /**
+     * The ArtMethod associated with this Method, requried for dispatching due to entrypoints
+     * Hidden to workaround b/16828157.
+     * @hide
+     */
+    protected ArtMethod artMethod;
+
+    /** Method's declaring class */
+    protected Class<?> declaringClass;
+
+    /** Overriden method's declaring class (same as declaringClass unless declaringClass
+     * is a proxy class) */
+    protected Class<?> declaringClassOfOverriddenMethod;
+
+    /** The method index of this method within its defining dex file */
+    protected int dexMethodIndex;
 
     /**
      * Hidden to workaround b/16828157.
      * @hide
      */
-    protected final ArtMethod artMethod;
-
-    /**
-     * Hidden to workaround b/16828157.
-     * @hide
-     */
-    protected AbstractMethod(ArtMethod artMethod) {
-        if (artMethod == null) {
-            throw new NullPointerException("artMethod == null");
-        }
-        this.artMethod = artMethod;
+    protected AbstractMethod() {
     }
 
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
@@ -90,33 +100,33 @@
     }
 
     int getModifiers() {
-        return fixMethodFlags(artMethod.getAccessFlags());
+        return fixMethodFlags(accessFlags);
     }
 
     boolean isVarArgs() {
-        return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0;
+        return (accessFlags & Modifier.VARARGS) != 0;
     }
 
     boolean isBridge() {
-        return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0;
+        return (accessFlags & Modifier.BRIDGE) != 0;
     }
 
     boolean isSynthetic() {
-        return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0;
+        return (accessFlags & Modifier.SYNTHETIC) != 0;
     }
 
     /**
      * @hide
      */
     public final int getAccessFlags() {
-        return artMethod.getAccessFlags();
+        return accessFlags;
     }
 
     /**
      * Returns the class that declares this constructor or method.
      */
     Class<?> getDeclaringClass() {
-        return artMethod.getDeclaringClass();
+        return declaringClass;
     }
 
     /**
@@ -125,7 +135,7 @@
      * @hide
      */
     public final int getDexMethodIndex() {
-        return artMethod.getDexMethodIndex();
+        return dexMethodIndex;
     }
 
     /**
@@ -144,7 +154,17 @@
      * @return the parameter types
      */
     Class<?>[] getParameterTypes() {
-        return artMethod.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;
     }
 
     /**
@@ -155,8 +175,10 @@
         if (!(other instanceof AbstractMethod)) {
             return false;
         }
-        // exactly one instance of each member in this runtime
-        return this.artMethod == ((AbstractMethod) other).artMethod;
+        // Exactly one instance of each member in this runtime, todo, does this work for proxies?
+        AbstractMethod otherMethod = (AbstractMethod) other;
+        return this.declaringClass == otherMethod.declaringClass &&
+            this.dexMethodIndex == otherMethod.dexMethodIndex;
     }
 
     String toGenericString() {
@@ -252,6 +274,37 @@
                                parser.returnType, parser.formalTypeParameters);
     }
 
+    protected 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;
+    }
+
+    protected int compareParameters(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;
+    }
+
     /**
      * Helper for Method and Constructor for toGenericString
      */
diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java
index 3abcb60..84e6b48 100644
--- a/libart/src/main/java/java/lang/reflect/ArtMethod.java
+++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java
@@ -75,103 +75,4 @@
 
     /** Only created by ART directly. */
     private ArtMethod() {}
-
-    public Class getDeclaringClass() {
-        return declaringClass;
-    }
-
-    public int getAccessFlags() {
-        return accessFlags;
-    }
-
-    int getDexMethodIndex() {
-        return dexMethodIndex;
-    }
-
-    public static String getMethodName(ArtMethod artMethod) {
-        Class<?> declClass = artMethod.getDeclaringClass();
-        Dex dex = declClass.getDex();
-        int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex());
-        // Note, in the case of a Proxy the dex cache strings are equal.
-        return declClass.getDexCacheString(dex, nameIndex);
-    }
-
-    /**
-     * Returns true if the given parameters match those of the method in the given order.
-     *
-     * @hide
-     */
-    public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) {
-        Class<?> declClass = artMethod.getDeclaringClass();
-        Dex dex = declClass.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex());
-        if (types.length != params.length) {
-            return false;
-        }
-        for (int i = 0; i < types.length; i++) {
-            if (declClass.getDexCacheType(dex, types[i]) != params[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns true if the given parameters match those of this method in the given order.
-     *
-     * @hide
-     */
-    public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) {
-        return equalConstructorParameters(artMethod, params);
-    }
-
-    Class<?>[] getParameterTypes() {
-        Class<?> declClass = getDeclaringClass();
-        Dex dex = declClass.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] = declClass.getDexCacheType(dex, types[i]);
-        }
-        return parametersArray;
-    }
-
-    Class<?> getReturnType() {
-        Class<?> declClass = getDeclaringClass();
-        Dex dex = declClass.getDex();
-        int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex);
-        // Note, in the case of a Proxy the dex cache types are equal.
-        return declClass.getDexCacheType(dex, returnTypeIndex);
-    }
-
-    /**
-     * Performs a comparison of the parameters to this method with the given parameters.
-     *
-     * @hide
-     */
-    int compareParameters(Class<?>[] params) {
-        Class<?> declClass = getDeclaringClass();
-        Dex dex = declClass.getDex();
-        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
-        int length = Math.min(types.length, params.length);
-        for (int i = 0; i < length; i++) {
-            Class<?> aType = declClass.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;
-    }
-
-    Annotation[][] getParameterAnnotations() {
-        return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex);
-    }
 }
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 66ae143..9701147 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -49,11 +49,7 @@
 
     private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method.
 
-    /**
-     * @hide
-     */
-    public Constructor(ArtMethod artMethod) {
-        super(artMethod);
+    private Constructor() {
     }
 
     public Annotation[] getAnnotations() {
@@ -213,7 +209,8 @@
      * @return an array of arrays of {@code Annotation} instances
      */
     public Annotation[][] getParameterAnnotations() {
-        return artMethod.getParameterAnnotations();
+        return AnnotationAccess.getParameterAnnotations(
+            declaringClassOfOverriddenMethod, dexMethodIndex);
     }
 
     /**
@@ -283,13 +280,14 @@
      *
      * @see AccessibleObject
      */
-    public T newInstance(Object... args) throws InstantiationException,
-            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-      return newInstance(args, isAccessible());
-    }
+    public native T newInstance(Object... args) throws InstantiationException,
+            IllegalAccessException, IllegalArgumentException, InvocationTargetException;
 
-    /** @hide */
-    public native T newInstance(Object[] args, boolean accessible) throws InstantiationException,
+    /**
+     * Special version that looks up two frames for access check. Used by Class.newInstance.
+     * @hide
+     */
+    public native T newInstanceTwoFrames(Object... args) throws InstantiationException,
             IllegalAccessException, IllegalArgumentException, InvocationTargetException;
 
     /**
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index c70e34e..a07ec6f 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -57,8 +57,7 @@
             }
             int comparison = a.getName().compareTo(b.getName());
             if (comparison == 0) {
-                comparison = Class.findOverriddenMethodIfProxy(a.artMethod).compareParameters(
-                        Class.findOverriddenMethodIfProxy(b.artMethod).getParameterTypes());
+                comparison = a.compareParameters(b.getParameterTypes());
                 if (comparison == 0) {
                     // This is necessary for methods that have covariant return types.
                     Class<?> aReturnType = a.getReturnType();
@@ -77,12 +76,7 @@
     /**
      * @hide
      */
-    public Method(ArtMethod artMethod) {
-        super(artMethod);
-    }
-
-    ArtMethod getArtMethod() {
-        return artMethod;
+    private Method() {
     }
 
     public Annotation[] getAnnotations() {
@@ -136,8 +130,9 @@
      * @return the name of this method
      */
     @Override public String getName() {
-        ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(artMethod);
-        return ArtMethod.getMethodName(nonProxyMethod);
+        Dex dex = declaringClassOfOverriddenMethod.getDex();
+        int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex);
+        return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex);
     }
 
     /**
@@ -172,7 +167,7 @@
      * @return the parameter types
      */
     @Override public Class<?>[] getParameterTypes() {
-        return Class.findOverriddenMethodIfProxy(artMethod).getParameterTypes();
+        return super.getParameterTypes();
     }
 
     /**
@@ -182,9 +177,13 @@
      * @return the return type
      */
     public Class<?> getReturnType() {
-        return Class.findOverriddenMethodIfProxy(artMethod).getReturnType();
+        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);
     }
 
+
     /**
      * {@inheritDoc}
      *
@@ -210,10 +209,7 @@
      * @hide needed by Proxy
      */
     boolean equalNameAndParameters(Method m) {
-        ArtMethod nonProxyThis = Class.findOverriddenMethodIfProxy(this.artMethod);
-        ArtMethod nonProxyM = Class.findOverriddenMethodIfProxy(m.artMethod);
-        return ArtMethod.getMethodName(nonProxyThis).equals(ArtMethod.getMethodName(nonProxyM)) &&
-                ArtMethod.equalMethodParameters(nonProxyThis, nonProxyM.getParameterTypes());
+        return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes());
     }
 
     /**
@@ -313,7 +309,8 @@
      * @return an array of arrays of {@code Annotation} instances
      */
     public Annotation[][] getParameterAnnotations() {
-        return Class.findOverriddenMethodIfProxy(artMethod).getParameterAnnotations();
+        return AnnotationAccess.getParameterAnnotations(
+            declaringClassOfOverriddenMethod, dexMethodIndex);
     }
 
     /**
@@ -370,12 +367,7 @@
      * @throws InvocationTargetException
      *             if an exception was thrown by the invoked method
      */
-    public Object invoke(Object receiver, Object... args)
-            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-        return invoke(receiver, args, isAccessible());
-    }
-
-    private native Object invoke(Object receiver, Object[] args, boolean accessible)
+    public native Object invoke(Object receiver, Object... args)
             throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
 
     /**
diff --git a/libart/src/main/java/java/lang/reflect/Proxy.java b/libart/src/main/java/java/lang/reflect/Proxy.java
index e47b27b..18ad49c 100755
--- a/libart/src/main/java/java/lang/reflect/Proxy.java
+++ b/libart/src/main/java/java/lang/reflect/Proxy.java
@@ -166,11 +166,7 @@
         Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
         validateReturnTypes(methods);
         List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
-
-        ArtMethod[] methodsArray = new ArtMethod[methods.size()];
-        for (int i = 0; i < methodsArray.length; i++) {
-            methodsArray[i] = methods.get(i).getArtMethod();
-        }
+        Method[] methodsArray = methods.toArray(new Method[methods.size()]);
         Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
 
         String baseName = commonPackageName != null && !commonPackageName.isEmpty()
@@ -383,7 +379,7 @@
     }
 
     private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
-                                                 ClassLoader loader, ArtMethod[] methods,
+                                                 ClassLoader loader, Method[] methods,
                                                  Class<?>[][] exceptions);
 
     /*
@@ -392,8 +388,8 @@
      */
     private static native void constructorPrototype(InvocationHandler h);
 
-    static Object invoke(Proxy proxy, ArtMethod method, Object[] args) throws Throwable {
+    private static Object invoke(Proxy proxy, Method method, Object[] args) throws Throwable {
         InvocationHandler h = proxy.h;
-        return h.invoke(proxy, new Method(method), args);
+        return h.invoke(proxy, method, args);
     }
 }
diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java
index 3a89b52..c588251 100644
--- a/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/luni/src/main/java/java/io/ObjectInputStream.java
@@ -1977,7 +1977,7 @@
             // original/outside caller
             if (++nestedLevels == 1) {
                 // Remember the caller's class loader
-                callerClassLoader = VMStack.getClosestUserClassLoader(bootstrapLoader, systemLoader);
+                callerClassLoader = VMStack.getClosestUserClassLoader();
             }
 
             result = readNonPrimitiveContent(unshared);
@@ -2014,9 +2014,6 @@
         return result;
     }
 
-    private static final ClassLoader bootstrapLoader = Object.class.getClassLoader();
-    private static final ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
-
     /**
      * Method to be overridden by subclasses to read the next object from the
      * source stream.
diff --git a/luni/src/main/java/java/lang/Package.java b/luni/src/main/java/java/lang/Package.java
index 7e30883..cff01b9 100644
--- a/luni/src/main/java/java/lang/Package.java
+++ b/luni/src/main/java/java/lang/Package.java
@@ -96,7 +96,14 @@
      */
     public Annotation[] getAnnotations() {
         try {
-            Class<?> c = Class.forName(getName() + ".package-info");
+            ClassLoader classLoader = VMStack.getCallingClassLoader();
+            if (classLoader == null) {
+                classLoader = ClassLoader.getSystemClassLoader();
+            }
+            Class<?> c = Class.forName(getName() + ".package-info",
+                                       // TODO: It is unclear if we need to initialize here.
+                                       true,
+                                       classLoader);
             return c.getAnnotations();
         } catch (Exception ex) {
             return NO_ANNOTATIONS;
@@ -175,11 +182,11 @@
      * @see ClassLoader#getPackage(java.lang.String)
      */
     public static Package getPackage(String packageName) {
-        ClassLoader classloader = VMStack.getCallingClassLoader();
-        if (classloader == null) {
-            classloader = ClassLoader.getSystemClassLoader();
+        ClassLoader classLoader = VMStack.getCallingClassLoader();
+        if (classLoader == null) {
+            classLoader = ClassLoader.getSystemClassLoader();
         }
-        return classloader.getPackage(packageName);
+        return classLoader.getPackage(packageName);
     }
 
     /**
@@ -189,11 +196,11 @@
      * @see ClassLoader#getPackages
      */
     public static Package[] getPackages() {
-        ClassLoader classloader = VMStack.getCallingClassLoader();
-        if (classloader == null) {
-            classloader = ClassLoader.getSystemClassLoader();
+        ClassLoader classLoader = VMStack.getCallingClassLoader();
+        if (classLoader == null) {
+            classLoader = ClassLoader.getSystemClassLoader();
         }
-        return classloader.getPackages();
+        return classLoader.getPackages();
     }
 
     /**
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index bed9de6..e79f844 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -1176,7 +1176,12 @@
      * named by the argument. On Android, this would turn {@code "MyLibrary"} into
      * {@code "libMyLibrary.so"}.
      */
-    public static native String mapLibraryName(String nickname);
+    public static String mapLibraryName(String nickname) {
+        if (nickname == null) {
+            throw new NullPointerException("nickname == null");
+        }
+        return "lib" + nickname + ".so";
+    }
 
     /**
      * Used to set System.err, System.in, and System.out.
diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index c8a6a73..dc4161f 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/luni/src/main/java/java/util/Collections.java
@@ -1426,21 +1426,21 @@
         if (!(list instanceof RandomAccess)) {
             ListIterator<? extends Comparable<? super T>> it = list.listIterator();
             while (it.hasNext()) {
-                int result;
-                if ((result = -it.next().compareTo(object)) <= 0) {
-                    if (result == 0) {
-                        return it.previousIndex();
-                    }
+                final int result = it.next().compareTo(object);
+                if (result == 0) {
+                    return it.previousIndex();
+                } else if (result > 0) {
                     return -it.previousIndex() - 1;
                 }
             }
             return -list.size() - 1;
         }
 
-        int low = 0, mid = list.size(), high = mid - 1, result = -1;
+        int low = 0, mid = list.size(), high = mid - 1, result = 1;
         while (low <= high) {
             mid = (low + high) >>> 1;
-            if ((result = -list.get(mid).compareTo(object)) > 0) {
+            result = list.get(mid).compareTo(object);
+            if (result < 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1448,7 +1448,7 @@
                 high = mid - 1;
             }
         }
-        return -mid - (result < 0 ? 1 : 2);
+        return -mid - (result > 0 ? 1 : 2);
     }
 
     /**
@@ -1481,21 +1481,21 @@
         if (!(list instanceof RandomAccess)) {
             ListIterator<? extends T> it = list.listIterator();
             while (it.hasNext()) {
-                int result;
-                if ((result = -comparator.compare(it.next(), object)) <= 0) {
-                    if (result == 0) {
-                        return it.previousIndex();
-                    }
+                final int result = comparator.compare(it.next(), object);
+                if (result == 0) {
+                    return it.previousIndex();
+                } else if (result > 0) {
                     return -it.previousIndex() - 1;
                 }
             }
             return -list.size() - 1;
         }
 
-        int low = 0, mid = list.size(), high = mid - 1, result = -1;
+        int low = 0, mid = list.size(), high = mid - 1, result = 1;
         while (low <= high) {
             mid = (low + high) >>> 1;
-            if ((result = -comparator.compare(list.get(mid), object)) > 0) {
+            result = comparator.compare(list.get(mid), object);
+            if (result < 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1503,7 +1503,7 @@
                 high = mid - 1;
             }
         }
-        return -mid - (result < 0 ? 1 : 2);
+        return -mid - (result > 0 ? 1 : 2);
     }
 
     /**
diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java
index d7adbf2..d7beb91 100644
--- a/luni/src/main/java/java/util/TimeZone.java
+++ b/luni/src/main/java/java/util/TimeZone.java
@@ -109,7 +109,7 @@
                 raw = -raw;
             }
 
-            String cleanId = String.format("GMT%c%02d:%02d", sign, hour, minute);
+            String cleanId = String.format((Locale) null, "GMT%c%02d:%02d", sign, hour, minute);
             return new SimpleTimeZone(raw, cleanId);
         }
     }
diff --git a/luni/src/main/java/java/util/jar/Manifest.java b/luni/src/main/java/java/util/jar/Manifest.java
index 6a3936d..5a6b42d 100644
--- a/luni/src/main/java/java/util/jar/Manifest.java
+++ b/luni/src/main/java/java/util/jar/Manifest.java
@@ -41,8 +41,10 @@
 
     private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' };
 
-    private final Attributes mainAttributes;
-    private final HashMap<String, Attributes> entries;
+    /* non-final for {@code #clone()} */
+    private Attributes mainAttributes;
+    /* non-final for {@code #clone()} */
+    private HashMap<String, Attributes> entries;
 
     static final class Chunk {
         final int start;
@@ -93,9 +95,7 @@
      */
     @SuppressWarnings("unchecked")
     public Manifest(Manifest man) {
-        mainAttributes = (Attributes) man.mainAttributes.clone();
-        entries = (HashMap<String, Attributes>) ((HashMap<String, Attributes>) man
-                .getEntries()).clone();
+        cloneAttributesAndEntriesFrom(man);
     }
 
     Manifest(byte[] manifestBytes, boolean readChunks) throws IOException {
@@ -156,7 +156,21 @@
      */
     @Override
     public Object clone() {
-        return new Manifest(this);
+        Manifest result;
+        try {
+            result = (Manifest) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
+
+        result.cloneAttributesAndEntriesFrom(this);
+        return result;
+    }
+
+    private final void cloneAttributesAndEntriesFrom(Manifest other) {
+        mainAttributes = (Attributes) other.mainAttributes.clone();
+        entries = (HashMap<String, Attributes>) ((HashMap<String, Attributes>) other
+                .getEntries()).clone();
     }
 
     /**
diff --git a/luni/src/main/java/javax/security/cert/X509Certificate.java b/luni/src/main/java/javax/security/cert/X509Certificate.java
index e85a556..5084ae0 100644
--- a/luni/src/main/java/javax/security/cert/X509Certificate.java
+++ b/luni/src/main/java/javax/security/cert/X509Certificate.java
@@ -51,7 +51,7 @@
             String classname = Security.getProperty("cert.provider.x509v1");
             Class cl = Class.forName(classname);
             constructor = cl.getConstructor(new Class[] {InputStream.class});
-        } catch (Throwable e) {
+        } catch (Exception|LinkageError e) {
         }
     }
 
@@ -80,7 +80,7 @@
             try {
                 return (X509Certificate)
                     constructor.newInstance(new Object[] {inStream});
-            } catch (Throwable e) {
+            } catch (ReflectiveOperationException e) {
                 throw new CertificateException(e.getMessage());
             }
         }
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
index 96d2ca7..10e3e6a 100644
--- a/luni/src/main/java/libcore/icu/DateIntervalFormat.java
+++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
@@ -16,9 +16,12 @@
 
 package libcore.icu;
 
+import com.ibm.icu.impl.JavaTimeZone;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.ULocale;
+
 import java.text.FieldPosition;
-import java.util.Calendar;
-import java.util.Locale;
 import java.util.TimeZone;
 import libcore.util.BasicLruCache;
 
@@ -45,9 +48,6 @@
   public static final int FORMAT_NUMERIC_DATE   = 0x20000;
   public static final int FORMAT_ABBREV_ALL     = 0x80000;
 
-  private static final int DAY_IN_MS = 24 * 60 * 60 * 1000;
-  private static final int EPOCH_JULIAN_DAY = 2440588;
-
   private static final FormatterCache CACHED_FORMATTERS = new FormatterCache();
 
   static class FormatterCache extends BasicLruCache<String, com.ibm.icu.text.DateIntervalFormat> {
@@ -64,23 +64,24 @@
     if ((flags & FORMAT_UTC) != 0) {
       olsonId = "UTC";
     }
+    // We create a java.util.TimeZone here to use libcore's data and libcore's olson ID / pseudo-tz
+    // logic.
     TimeZone tz = (olsonId != null) ? TimeZone.getTimeZone(olsonId) : TimeZone.getDefault();
-    return formatDateRange(Locale.getDefault(), tz, startMs, endMs, flags);
+    com.ibm.icu.util.TimeZone icuTimeZone = icuTimeZone(tz);
+    ULocale icuLocale = ULocale.getDefault();
+    return formatDateRange(icuLocale, icuTimeZone, startMs, endMs, flags);
   }
 
   // This is our slightly more sensible internal API. (A truly sane replacement would take a
   // skeleton instead of int flags.)
-  public static String formatDateRange(Locale locale, TimeZone tz, long startMs, long endMs,
-      int flags) {
-    Calendar startCalendar = Calendar.getInstance(tz);
-    startCalendar.setTimeInMillis(startMs);
-
+  public static String formatDateRange(ULocale icuLocale, com.ibm.icu.util.TimeZone icuTimeZone,
+      long startMs, long endMs, int flags) {
+    Calendar startCalendar = createIcuCalendar(icuTimeZone, icuLocale, startMs);
     Calendar endCalendar;
     if (startMs == endMs) {
       endCalendar = startCalendar;
     } else {
-      endCalendar = Calendar.getInstance(tz);
-      endCalendar.setTimeInMillis(endMs);
+      endCalendar = createIcuCalendar(icuTimeZone, icuLocale, endMs);
     }
 
     boolean endsAtMidnight = isMidnight(endCalendar);
@@ -92,27 +93,26 @@
     if (startMs != endMs && endsAtMidnight &&
         ((flags & FORMAT_SHOW_TIME) == 0 || dayDistance(startCalendar, endCalendar) <= 1)) {
       endCalendar.roll(Calendar.DAY_OF_MONTH, false);
-      endMs -= DAY_IN_MS;
     }
 
     String skeleton = toSkeleton(startCalendar, endCalendar, flags);
     synchronized (CACHED_FORMATTERS) {
-      com.ibm.icu.text.DateIntervalFormat formatter = getFormatter(skeleton, locale, tz);
-      com.ibm.icu.util.Calendar scal = icuCalendar(startCalendar);
-      com.ibm.icu.util.Calendar ecal = icuCalendar(endCalendar);
-      return formatter.format(scal, ecal, new StringBuffer(), new FieldPosition(0)).toString();
+      com.ibm.icu.text.DateIntervalFormat formatter =
+          getFormatter(skeleton, icuLocale, icuTimeZone);
+      return formatter.format(startCalendar, endCalendar, new StringBuffer(),
+          new FieldPosition(0)).toString();
     }
   }
 
-  private static com.ibm.icu.text.DateIntervalFormat getFormatter(String skeleton, Locale locale,
-      TimeZone tz) {
-    String key = skeleton + "\t" + locale + "\t" + tz;
+  private static com.ibm.icu.text.DateIntervalFormat getFormatter(String skeleton, ULocale locale,
+      com.ibm.icu.util.TimeZone icuTimeZone) {
+    String key = skeleton + "\t" + locale + "\t" + icuTimeZone;
     com.ibm.icu.text.DateIntervalFormat formatter = CACHED_FORMATTERS.get(key);
     if (formatter != null) {
       return formatter;
     }
     formatter = com.ibm.icu.text.DateIntervalFormat.getInstance(skeleton, locale);
-    formatter.setTimeZone(icuTimeZone(tz));
+    formatter.setTimeZone(icuTimeZone);
     CACHED_FORMATTERS.put(key, formatter);
     return formatter;
   }
@@ -223,39 +223,30 @@
   }
 
   private static boolean isThisYear(Calendar c) {
-    Calendar now = Calendar.getInstance(c.getTimeZone());
+    Calendar now = (Calendar) c.clone();
+    now.setTimeInMillis(System.currentTimeMillis());
     return c.get(Calendar.YEAR) == now.get(Calendar.YEAR);
   }
 
-  // Return the date difference for the two times in a given timezone.
-  public static int dayDistance(TimeZone tz, long startTime, long endTime) {
-    return julianDay(tz, endTime) - julianDay(tz, startTime);
-  }
-
   public static int dayDistance(Calendar c1, Calendar c2) {
-    return julianDay(c2) - julianDay(c1);
+    return c2.get(Calendar.JULIAN_DAY) - c1.get(Calendar.JULIAN_DAY);
   }
 
-  private static int julianDay(TimeZone tz, long time) {
-    long utcMs = time + tz.getOffset(time);
-    return (int) (utcMs / DAY_IN_MS) + EPOCH_JULIAN_DAY;
+  /**
+   * Creates an immutable ICU timezone backed by the specified libcore timezone data. At the time of
+   * writing the libcore implementation is faster but restricted to 1902 - 2038.
+   * Callers must not modify the {@code tz} after calling this method.
+   */
+  static com.ibm.icu.util.TimeZone icuTimeZone(TimeZone tz) {
+    JavaTimeZone javaTimeZone = new JavaTimeZone(tz, null);
+    javaTimeZone.freeze(); // Optimization - allows the timezone to be copied cheaply.
+    return javaTimeZone;
   }
 
-  private static int julianDay(Calendar c) {
-    long utcMs = c.getTimeInMillis() + c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
-    return (int) (utcMs / DAY_IN_MS) + EPOCH_JULIAN_DAY;
+  static Calendar createIcuCalendar(com.ibm.icu.util.TimeZone icuTimeZone, ULocale icuLocale,
+      long timeInMillis) {
+    Calendar calendar = new GregorianCalendar(icuTimeZone, icuLocale);
+    calendar.setTimeInMillis(timeInMillis);
+    return calendar;
   }
-
-  private static com.ibm.icu.util.TimeZone icuTimeZone(TimeZone tz) {
-    final int timezoneType = com.ibm.icu.util.TimeZone.TIMEZONE_JDK;
-    return com.ibm.icu.util.TimeZone.getTimeZone(tz.getID(), timezoneType);
-  }
-
-  private static com.ibm.icu.util.Calendar icuCalendar(Calendar cal) {
-    com.ibm.icu.util.TimeZone timeZone = icuTimeZone(cal.getTimeZone());
-    com.ibm.icu.util.Calendar result = com.ibm.icu.util.Calendar.getInstance(timeZone);
-    result.setTime(cal.getTime());
-    return result;
-  }
-
 }
diff --git a/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
index 750df00..8d62c78 100644
--- a/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
+++ b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
@@ -16,13 +16,11 @@
 
 package libcore.icu;
 
-import java.util.Calendar;
-import java.util.GregorianCalendar;
 import java.util.Locale;
-import java.util.TimeZone;
 import libcore.util.BasicLruCache;
-import libcore.icu.DateIntervalFormat;
+
 import com.ibm.icu.text.DisplayContext;
+import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.ULocale;
 
 /**
@@ -50,6 +48,9 @@
   // constant comes from public API in DateUtils, it cannot be fixed here.
   public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
 
+  private static final int DAY_IN_MS = 24 * 60 * 60 * 1000;
+  private static final int EPOCH_JULIAN_DAY = 2440588;
+
   private static final FormatterCache CACHED_FORMATTERS = new FormatterCache();
 
   static class FormatterCache
@@ -89,7 +90,7 @@
    * always // returns a string like '0 seconds/minutes/... ago' according to
    * minResolution.
    */
-  public static String getRelativeTimeSpanString(Locale locale, TimeZone tz, long time,
+  public static String getRelativeTimeSpanString(Locale locale, java.util.TimeZone tz, long time,
       long now, long minResolution, int flags) {
     if (locale == null) {
       throw new NullPointerException("locale == null");
@@ -97,6 +98,9 @@
     if (tz == null) {
       throw new NullPointerException("tz == null");
     }
+    ULocale icuLocale = ULocale.forLocale(locale);
+    com.ibm.icu.util.TimeZone icuTimeZone = DateIntervalFormat.icuTimeZone(tz);
+
     long duration = Math.abs(now - time);
     boolean past = (now >= time);
 
@@ -142,7 +146,7 @@
       count = (int)(duration / HOUR_IN_MILLIS);
       unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.HOURS;
     } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
-      count = Math.abs(DateIntervalFormat.dayDistance(tz, time, now));
+      count = Math.abs(dayDistance(icuTimeZone, time, now));
       unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.DAYS;
 
       if (count == 2) {
@@ -156,14 +160,14 @@
         String str;
         if (past) {
           synchronized (CACHED_FORMATTERS) {
-            str = getFormatter(locale.toString(), style, capitalizationContext)
+            str = getFormatter(icuLocale, style, capitalizationContext)
                 .format(
                     com.ibm.icu.text.RelativeDateTimeFormatter.Direction.LAST_2,
                     com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY);
           }
         } else {
           synchronized (CACHED_FORMATTERS) {
-            str = getFormatter(locale.toString(), style, capitalizationContext)
+            str = getFormatter(icuLocale, style, capitalizationContext)
                 .format(
                     com.ibm.icu.text.RelativeDateTimeFormatter.Direction.NEXT_2,
                     com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY);
@@ -198,32 +202,28 @@
       // formatDateRange() would determine that based on the current system
       // time and may give wrong results.
       if ((flags & (FORMAT_NO_YEAR | FORMAT_SHOW_YEAR)) == 0) {
-          Calendar timeCalendar = new GregorianCalendar(false);
-          timeCalendar.setTimeZone(tz);
-          timeCalendar.setTimeInMillis(time);
-          Calendar nowCalendar = new GregorianCalendar(false);
-          nowCalendar.setTimeZone(tz);
-          nowCalendar.setTimeInMillis(now);
+        Calendar timeCalendar = DateIntervalFormat.createIcuCalendar(icuTimeZone, icuLocale, time);
+        Calendar nowCalendar = DateIntervalFormat.createIcuCalendar(icuTimeZone, icuLocale, now);
 
-          if (timeCalendar.get(Calendar.YEAR) != nowCalendar.get(Calendar.YEAR)) {
-              flags |= FORMAT_SHOW_YEAR;
-          } else {
-              flags |= FORMAT_NO_YEAR;
-          }
+        if (timeCalendar.get(Calendar.YEAR) != nowCalendar.get(Calendar.YEAR)) {
+          flags |= FORMAT_SHOW_YEAR;
+        } else {
+          flags |= FORMAT_NO_YEAR;
+        }
       }
 
-      return DateIntervalFormat.formatDateRange(locale, tz, time, time, flags);
+      return DateIntervalFormat.formatDateRange(icuLocale, icuTimeZone, time, time, flags);
     }
 
     if (relative) {
       synchronized (CACHED_FORMATTERS) {
-        return getFormatter(locale.toString(), style, capitalizationContext)
+        return getFormatter(icuLocale, style, capitalizationContext)
             .format(count, direction, unit);
       }
     } else {
       capitalizationContext = DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE;
       synchronized (CACHED_FORMATTERS) {
-        return getFormatter(locale.toString(), style, capitalizationContext)
+        return getFormatter(icuLocale, style, capitalizationContext)
             .format(direction, aunit);
       }
     }
@@ -258,7 +258,7 @@
    * now - 2 hours, now, HOUR_IN_MILLIS, DAY_IN_MILLIS, 0), instead of '2
    * hours ago, 11:30 PM' even with minResolution being HOUR_IN_MILLIS.
    */
-  public static String getRelativeDateTimeString(Locale locale, TimeZone tz, long time,
+  public static String getRelativeDateTimeString(Locale locale, java.util.TimeZone tz, long time,
       long now, long minResolution, long transitionResolution, int flags) {
 
     if (locale == null) {
@@ -267,10 +267,12 @@
     if (tz == null) {
       throw new NullPointerException("tz == null");
     }
+    ULocale icuLocale = ULocale.forLocale(locale);
+    com.ibm.icu.util.TimeZone icuTimeZone = DateIntervalFormat.icuTimeZone(tz);
 
     // Get the time clause first.
-    String timeClause = DateIntervalFormat.formatDateRange(locale, tz, time, time,
-                                                           FORMAT_SHOW_TIME);
+    String timeClause = DateIntervalFormat.formatDateRange(icuLocale, icuTimeZone, time, time,
+        FORMAT_SHOW_TIME);
 
     long duration = Math.abs(now - time);
     // It doesn't make much sense to have results like: "1 week ago, 10:50 AM".
@@ -288,12 +290,8 @@
     // are currently using the _NONE option only.
     DisplayContext capitalizationContext = DisplayContext.CAPITALIZATION_NONE;
 
-    Calendar timeCalendar = new GregorianCalendar(false);
-    timeCalendar.setTimeZone(tz);
-    timeCalendar.setTimeInMillis(time);
-    Calendar nowCalendar = new GregorianCalendar(false);
-    nowCalendar.setTimeZone(tz);
-    nowCalendar.setTimeInMillis(now);
+    Calendar timeCalendar = DateIntervalFormat.createIcuCalendar(icuTimeZone, icuLocale, time);
+    Calendar nowCalendar = DateIntervalFormat.createIcuCalendar(icuTimeZone, icuLocale, now);
 
     int days = Math.abs(DateIntervalFormat.dayDistance(timeCalendar, nowCalendar));
 
@@ -318,12 +316,12 @@
         flags = FORMAT_SHOW_DATE | FORMAT_NO_YEAR | FORMAT_ABBREV_MONTH;
       }
 
-      dateClause = DateIntervalFormat.formatDateRange(locale, tz, time, time, flags);
+      dateClause = DateIntervalFormat.formatDateRange(icuLocale, icuTimeZone, time, time, flags);
     }
 
     // Combine the two clauses, such as '5 days ago, 10:50 AM'.
     synchronized (CACHED_FORMATTERS) {
-      return getFormatter(locale.toString(), style, capitalizationContext)
+      return getFormatter(icuLocale, style, capitalizationContext)
               .combineDateAndTime(dateClause, timeClause);
     }
   }
@@ -337,15 +335,26 @@
    * formatter->action().
    */
   private static com.ibm.icu.text.RelativeDateTimeFormatter getFormatter(
-      String localeName, com.ibm.icu.text.RelativeDateTimeFormatter.Style style,
+      ULocale locale, com.ibm.icu.text.RelativeDateTimeFormatter.Style style,
       DisplayContext capitalizationContext) {
-    String key = localeName + "\t" + style + "\t" + capitalizationContext;
+    String key = locale + "\t" + style + "\t" + capitalizationContext;
     com.ibm.icu.text.RelativeDateTimeFormatter formatter = CACHED_FORMATTERS.get(key);
     if (formatter == null) {
       formatter = com.ibm.icu.text.RelativeDateTimeFormatter.getInstance(
-          new ULocale(localeName), null, style, capitalizationContext);
+          locale, null, style, capitalizationContext);
       CACHED_FORMATTERS.put(key, formatter);
     }
     return formatter;
   }
+
+  // Return the date difference for the two times in a given timezone.
+  private static int dayDistance(com.ibm.icu.util.TimeZone icuTimeZone, long startTime,
+      long endTime) {
+    return julianDay(icuTimeZone, endTime) - julianDay(icuTimeZone, startTime);
+  }
+
+  private static int julianDay(com.ibm.icu.util.TimeZone icuTimeZone, long time) {
+    long utcMs = time + icuTimeZone.getOffset(time);
+    return (int) (utcMs / DAY_IN_MS) + EPOCH_JULIAN_DAY;
+  }
 }
diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java
index 2e72078..e36b3d1 100644
--- a/luni/src/main/java/libcore/net/MimeUtils.java
+++ b/luni/src/main/java/libcore/net/MimeUtils.java
@@ -16,13 +16,8 @@
 
 package libcore.net;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 
 /**
  * Utilities for dealing with MIME types.
@@ -382,7 +377,6 @@
         add("video/x-webex", "wrf");
         add("x-conference/x-cooltalk", "ice");
         add("x-epoc/x-sisx-app", "sisx");
-        applyOverrides();
     }
 
     private static void add(String mimeType, String extension) {
@@ -399,61 +393,6 @@
         }
     }
 
-    private static InputStream getContentTypesPropertiesStream() {
-        // User override?
-        String userTable = System.getProperty("content.types.user.table");
-        if (userTable != null) {
-            File f = new File(userTable);
-            if (f.exists()) {
-                try {
-                    return new FileInputStream(f);
-                } catch (IOException ignored) {
-                }
-            }
-        }
-
-        // Standard location?
-        File f = new File(System.getProperty("java.home"), "lib" + File.separator + "content-types.properties");
-        if (f.exists()) {
-            try {
-                return new FileInputStream(f);
-            } catch (IOException ignored) {
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * This isn't what the RI does. The RI doesn't have hard-coded defaults, so supplying your
-     * own "content.types.user.table" means you don't get any of the built-ins, and the built-ins
-     * come from "$JAVA_HOME/lib/content-types.properties".
-     */
-    private static void applyOverrides() {
-        // Get the appropriate InputStream to read overrides from, if any.
-        InputStream stream = getContentTypesPropertiesStream();
-        if (stream == null) {
-            return;
-        }
-
-        try {
-            try {
-                // Read the properties file...
-                Properties overrides = new Properties();
-                overrides.load(stream);
-                // And translate its mapping to ours...
-                for (Map.Entry<Object, Object> entry : overrides.entrySet()) {
-                    String extension = (String) entry.getKey();
-                    String mimeType = (String) entry.getValue();
-                    add(mimeType, extension);
-                }
-            } finally {
-                stream.close();
-            }
-        } catch (IOException ignored) {
-        }
-    }
-
     private MimeUtils() {
     }
 
diff --git a/luni/src/main/java/java/nio/charset/Charsets.java b/luni/src/main/java/libcore/util/CharsetUtils.java
similarity index 96%
rename from luni/src/main/java/java/nio/charset/Charsets.java
rename to luni/src/main/java/libcore/util/CharsetUtils.java
index 3dede7a..2e426c4 100644
--- a/luni/src/main/java/java/nio/charset/Charsets.java
+++ b/luni/src/main/java/libcore/util/CharsetUtils.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package java.nio.charset;
+package libcore.util;
 
 /**
  * Various special-case charset conversions (for performance).
  *
  * @hide internal use only
  */
-public final class Charsets {
+public final class CharsetUtils {
     /**
      * Returns a new byte array containing the bytes corresponding to the given characters,
      * encoded in US-ASCII. Unrepresentable characters are replaced by (byte) '?'.
@@ -75,6 +75,6 @@
      */
     public static native void isoLatin1BytesToChars(byte[] bytes, int offset, int length, char[] chars);
 
-    private Charsets() {
+    private CharsetUtils() {
     }
 }
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 035b1d9..0f2d0ad 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -48,7 +48,6 @@
     REGISTER(register_java_lang_System);
     REGISTER(register_java_math_NativeBN);
     REGISTER(register_java_nio_ByteOrder);
-    REGISTER(register_java_nio_charset_Charsets);
     REGISTER(register_java_text_Bidi);
     REGISTER(register_java_util_jar_StrictJarFile);
     REGISTER(register_java_util_regex_Matcher);
@@ -70,6 +69,7 @@
     REGISTER(register_libcore_io_AsynchronousCloseMonitor);
     REGISTER(register_libcore_io_Memory);
     REGISTER(register_libcore_io_Posix);
+    REGISTER(register_libcore_util_CharsetUtils);
     REGISTER(register_org_apache_harmony_dalvik_NativeTestTarget);
     REGISTER(register_org_apache_harmony_xml_ExpatParser);
     REGISTER(register_sun_misc_Unsafe);
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 3b995e7..306adab 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -124,22 +124,9 @@
 #endif
 }
 
-static jstring System_mapLibraryName(JNIEnv* env, jclass, jstring javaName) {
-    ScopedUtfChars name(env, javaName);
-    if (name.c_str() == NULL) {
-        return NULL;
-    }
-    char* mappedName = NULL;
-    asprintf(&mappedName, "lib%s.so", name.c_str());
-    jstring result = env->NewStringUTF(mappedName);
-    free(mappedName);
-    return result;
-}
-
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(System, currentTimeMillis, "!()J"),
     NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"),
-    NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(System, nanoTime, "!()J"),
     NATIVE_METHOD(System, setFieldImpl, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"),
     NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"),
diff --git a/luni/src/main/native/java_nio_charset_Charsets.cpp b/luni/src/main/native/libcore_util_CharsetUtils.cpp
similarity index 98%
rename from luni/src/main/native/java_nio_charset_Charsets.cpp
rename to luni/src/main/native/libcore_util_CharsetUtils.cpp
index a49ba22..57c8172 100644
--- a/luni/src/main/native/java_nio_charset_Charsets.cpp
+++ b/luni/src/main/native/libcore_util_CharsetUtils.cpp
@@ -245,6 +245,6 @@
     NATIVE_METHOD(Charsets, toIsoLatin1Bytes, "([CII)[B"),
     NATIVE_METHOD(Charsets, toUtf8Bytes, "([CII)[B"),
 };
-void register_java_nio_charset_Charsets(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "java/nio/charset/Charsets", gMethods, NELEM(gMethods));
+void register_libcore_util_CharsetUtils(JNIEnv* env) {
+    jniRegisterNativeMethods(env, "libcore/util/CharsetUtils", gMethods, NELEM(gMethods));
 }
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index 2bc44ed..a90c683 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -28,7 +28,6 @@
     java_lang_System.cpp \
     java_math_NativeBN.cpp \
     java_nio_ByteOrder.cpp \
-    java_nio_charset_Charsets.cpp \
     java_text_Bidi.cpp \
     java_util_jar_StrictJarFile.cpp \
     java_util_regex_Matcher.cpp \
@@ -50,6 +49,7 @@
     libcore_io_AsynchronousCloseMonitor.cpp \
     libcore_io_Memory.cpp \
     libcore_io_Posix.cpp \
+    libcore_util_CharsetUtils.cpp \
     org_apache_harmony_xml_ExpatParser.cpp \
     readlink.cpp \
     sun_misc_Unsafe.cpp \
diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
index d49579c..d14710c 100644
--- a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
+++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
@@ -16,9 +16,10 @@
 
 package libcore.icu;
 
-import java.util.Calendar;
-import java.util.Locale;
-import java.util.TimeZone;
+import android.icu.util.Calendar;
+import android.icu.util.TimeZone;
+import android.icu.util.ULocale;
+
 import static libcore.icu.DateIntervalFormat.*;
 
 public class DateIntervalFormatTest extends junit.framework.TestCase {
@@ -32,7 +33,7 @@
   public void test_formatDateInterval() throws Exception {
     TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 
-    Calendar c = Calendar.getInstance(tz, Locale.US);
+    Calendar c = Calendar.getInstance(tz, ULocale.US);
     c.set(Calendar.MONTH, Calendar.JANUARY);
     c.set(Calendar.DAY_OF_MONTH, 19);
     c.set(Calendar.HOUR_OF_DAY, 3);
@@ -51,10 +52,10 @@
     long noonDuration = (8 * 60 + 30) * 60 * 1000 - 15 * 1000;
     long midnightDuration = (3 * 60 + 30) * 60 * 1000 + 15 * 1000;
 
-    Locale de_DE = new Locale("de", "DE");
-    Locale en_US = new Locale("en", "US");
-    Locale es_ES = new Locale("es", "ES");
-    Locale es_US = new Locale("es", "US");
+    ULocale de_DE = new ULocale("de", "DE");
+    ULocale en_US = new ULocale("en", "US");
+    ULocale es_ES = new ULocale("es", "ES");
+    ULocale es_US = new ULocale("es", "US");
 
     assertEquals("Monday", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_WEEKDAY));
     assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, FORMAT_SHOW_DATE));
@@ -168,7 +169,7 @@
   // http://b/8862241 - we should be able to format dates past 2038.
   // See also http://code.google.com/p/android/issues/detail?id=13050.
   public void test8862241() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
     Calendar c = Calendar.getInstance(tz, l);
     c.clear();
@@ -182,7 +183,7 @@
 
   // http://b/10089890 - we should take the given time zone into account.
   public void test10089890() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     TimeZone pacific = TimeZone.getTimeZone("America/Los_Angeles");
     int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL | FORMAT_SHOW_TIME | FORMAT_24HOUR;
@@ -204,7 +205,7 @@
     int abbr12 = time12 | FORMAT_ABBREV_ALL;
     int abbr24 = time24 | FORMAT_ABBREV_ALL;
 
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     // Full length on-the-hour times.
@@ -231,7 +232,7 @@
   // http://b/10560853 - when the time is not displayed, an end time 0 ms into the next day is
   // considered to belong to the previous day.
   public void test10560853_when_time_not_displayed() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     long midnight = 0;
@@ -255,7 +256,7 @@
   // http://b/10560853 - when the start and end times are otherwise on the same day,
   // an end time 0 ms into the next day is considered to belong to the previous day.
   public void test10560853_for_single_day_events() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE;
@@ -267,7 +268,7 @@
   // The fix for http://b/10560853 didn't work except for the day around the epoch, which was
   // all the unit test checked!
   public void test_single_day_events_later_than_epoch() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE;
@@ -285,7 +286,7 @@
   // The fix for http://b/10560853 didn't work except for UTC, which was
   // all the unit test checked!
   public void test_single_day_events_not_in_UTC() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone pacific = TimeZone.getTimeZone("America/Los_Angeles");
 
     int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE;
@@ -306,7 +307,7 @@
   // http://b/10209343 - even if the caller didn't explicitly ask us to include the year,
   // we should do so for years other than the current year.
   public void test10209343_when_not_this_year() {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_24HOUR;
@@ -329,7 +330,7 @@
   // http://b/10209343 - for the current year, we should honor the FORMAT_SHOW_YEAR flags.
   public void test10209343_when_this_year() {
     // Construct a date in the current year (whenever the test happens to be run).
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     Calendar c = Calendar.getInstance(utc, l);
     c.set(Calendar.MONTH, Calendar.FEBRUARY);
@@ -364,7 +365,7 @@
 
   // http://b/8467515 - yet another y2k38 bug report.
   public void test8467515() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
     int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH | FORMAT_ABBREV_WEEKDAY;
     long t;
@@ -384,7 +385,7 @@
   // http://b/12004664
   public void test12004664() throws Exception {
     TimeZone utc = TimeZone.getTimeZone("UTC");
-    Calendar c = Calendar.getInstance(utc, Locale.US);
+    Calendar c = Calendar.getInstance(utc, ULocale.US);
     c.clear();
     c.set(Calendar.YEAR, 1980);
     c.set(Calendar.MONTH, Calendar.FEBRUARY);
@@ -393,26 +394,26 @@
     long thisYear = c.getTimeInMillis();
 
     int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR;
-    assertEquals("Sunday, February 10, 1980", formatDateRange(new Locale("en", "US"), utc, thisYear, thisYear, flags));
+    assertEquals("Sunday, February 10, 1980", formatDateRange(new ULocale("en", "US"), utc, thisYear, thisYear, flags));
 
-    // If we supported non-Gregorian calendars, this is what that we'd expect for these locales.
+    // If we supported non-Gregorian calendars, this is what that we'd expect for these ULocales.
     // This is really the correct behavior, but since java.util.Calendar currently only supports
     // the Gregorian calendar, we want to deliberately force icu4c to agree, otherwise we'd have
     // a mix of calendars throughout an app's UI depending on whether Java or native code formatted
     // the date.
-    // assertEquals("یکشنبه ۲۱ بهمن ۱۳۵۸ ه‍.ش.", formatDateRange(new Locale("fa"), utc, thisYear, thisYear, flags));
-    // assertEquals("AP ۱۳۵۸ سلواغه ۲۱, یکشنبه", formatDateRange(new Locale("ps"), utc, thisYear, thisYear, flags));
-    // assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 2523", formatDateRange(new Locale("th"), utc, thisYear, thisYear, flags));
+    // assertEquals("یکشنبه ۲۱ بهمن ۱۳۵۸ ه‍.ش.", formatDateRange(new ULocale("fa"), utc, thisYear, thisYear, flags));
+    // assertEquals("AP ۱۳۵۸ سلواغه ۲۱, یکشنبه", formatDateRange(new ULocale("ps"), utc, thisYear, thisYear, flags));
+    // assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 2523", formatDateRange(new ULocale("th"), utc, thisYear, thisYear, flags));
 
     // For now, here are the localized Gregorian strings instead...
-    assertEquals("یکشنبه ۱۰ فوریهٔ ۱۹۸۰", formatDateRange(new Locale("fa"), utc, thisYear, thisYear, flags));
-    assertEquals("یکشنبه د ۱۹۸۰ د فبروري ۱۰", formatDateRange(new Locale("ps"), utc, thisYear, thisYear, flags));
-    assertEquals("วันอาทิตย์ที่ 10 กุมภาพันธ์ ค.ศ. 1980", formatDateRange(new Locale("th"), utc, thisYear, thisYear, flags));
+    assertEquals("یکشنبه ۱۰ فوریهٔ ۱۹۸۰", formatDateRange(new ULocale("fa"), utc, thisYear, thisYear, flags));
+    assertEquals("یکشنبه د ۱۹۸۰ د فبروري ۱۰", formatDateRange(new ULocale("ps"), utc, thisYear, thisYear, flags));
+    assertEquals("วันอาทิตย์ที่ 10 กุมภาพันธ์ ค.ศ. 1980", formatDateRange(new ULocale("th"), utc, thisYear, thisYear, flags));
   }
 
   // http://b/13234532
   public void test13234532() throws Exception {
-    Locale l = Locale.US;
+    ULocale l = ULocale.US;
     TimeZone utc = TimeZone.getTimeZone("UTC");
 
     int flags = FORMAT_SHOW_TIME | FORMAT_ABBREV_ALL | FORMAT_12HOUR;
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
index 42de50a..1611120 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
@@ -256,15 +256,7 @@
 
     private void getSigAlgName(CertificateFactory f) throws Exception {
         X509CRL crlRsa = getCRL(f, CRL_RSA);
-
-        String actual = crlRsa.getSigAlgName().toUpperCase(Locale.US);
-
-        // Bouncycastle is broken
-        if ("BC".equals(f.getProvider().getName())) {
-            assertEquals("1.2.840.113549.1.1.5", actual);
-        } else {
-            assertEquals("SHA1WITHRSA", actual);
-        }
+        assertEquals("SHA1WITHRSA",  getCRL(f, CRL_RSA).getSigAlgName().toUpperCase(Locale.ROOT));
     }
 
     private void getSigAlgOID(CertificateFactory f) throws Exception {
diff --git a/luni/src/test/java/libcore/java/util/CollectionsTest.java b/luni/src/test/java/libcore/java/util/CollectionsTest.java
index cd89397..bc73817 100644
--- a/luni/src/test/java/libcore/java/util/CollectionsTest.java
+++ b/luni/src/test/java/libcore/java/util/CollectionsTest.java
@@ -19,6 +19,7 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.ConcurrentModificationException;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -113,4 +114,75 @@
         } catch (ConcurrentModificationException expected) {
         }
     }
+
+    /**
+     * A value type whose {@code compareTo} method returns one of {@code 0},
+     * {@code Integer.MIN_VALUE} and {@code Integer.MAX_VALUE}.
+     */
+    static final class IntegerWithExtremeComparator
+            implements Comparable<IntegerWithExtremeComparator> {
+        private final int value;
+
+        public IntegerWithExtremeComparator(int value) {
+            this.value = value;
+        }
+
+        @Override
+        public int compareTo(IntegerWithExtremeComparator another) {
+            if (another.value == this.value) {
+                return 0;
+            } else if (another.value > this.value) {
+                return Integer.MIN_VALUE;
+            } else {
+                return Integer.MAX_VALUE;
+            }
+        }
+    }
+
+    // http://b/19749094
+    public void testBinarySearch_comparatorThatReturnsMinAndMaxValue() {
+        ArrayList<Integer> list = new ArrayList<Integer>(16);
+        list.add(4);
+        list.add(9);
+        list.add(11);
+        list.add(14);
+        list.add(16);
+
+        int index = Collections.binarySearch(list, 9, new Comparator<Integer>() {
+            @Override
+            public int compare(Integer lhs, Integer rhs) {
+                final int compare = lhs.compareTo(rhs);
+                if (compare == 0) {
+                    return 0;
+                } else if (compare < 0) {
+                    return Integer.MIN_VALUE;
+                } else {
+                    return Integer.MAX_VALUE;
+                }
+            }
+        });
+        assertEquals(1, index);
+
+        ArrayList<IntegerWithExtremeComparator> list2 =
+                new ArrayList<IntegerWithExtremeComparator>();
+        list2.add(new IntegerWithExtremeComparator(4));
+        list2.add(new IntegerWithExtremeComparator(9));
+        list2.add(new IntegerWithExtremeComparator(11));
+        list2.add(new IntegerWithExtremeComparator(14));
+        list2.add(new IntegerWithExtremeComparator(16));
+
+        assertEquals(1, Collections.binarySearch(list2, new IntegerWithExtremeComparator(9)));
+    }
+
+    public void testBinarySearch_emptyCollection() {
+        assertEquals(-1, Collections.binarySearch(new ArrayList<Integer>(), 9));
+
+        assertEquals(-1, Collections.binarySearch(new ArrayList<Integer>(), 9,
+                new Comparator<Integer>() {
+                    @Override
+                    public int compare(Integer lhs, Integer rhs) {
+                        return lhs.compareTo(rhs);
+                    }
+                }));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 4f2e38c..68e9109 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -310,4 +310,18 @@
         assertFalse(tz.inDaylightTime(new Date(2206292400000L)));
         assertEquals(-18000000, tz.getOffset(2206292400000L));
     }
+
+    public void testTimeZoneIDLocalization() {
+        Locale defaultLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("en"));
+            TimeZone en_timezone = TimeZone.getTimeZone("GMT+09:00");
+            Locale.setDefault(new Locale("ar"));
+            TimeZone ar_timezone = TimeZone.getTimeZone("GMT+09:00");
+
+            assertEquals(en_timezone.getID(), ar_timezone.getID());
+        } finally {
+            Locale.setDefault(defaultLocale);
+        }
+    }
 }
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
index 9b7dc18..e90452d 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
@@ -100,6 +100,12 @@
         macList.add(Mac.getInstance(defaultAlgorithm, defaultProvider));
         macList.add(Mac.getInstance(defaultAlgorithm, defaultProviderName));
         for (Provider p : Security.getProviders("Mac." + defaultAlgorithm)) {
+            // Do not test AndroidKeyStore's Mac. It cannot be initialized without providing an
+            // AndroidKeyStore-backed SecretKey instance. It's OKish not to test here because it's
+            // tested by cts/tests/test/keystore.
+            if ("AndroidKeyStore".equals(p.getName())) {
+                continue;
+            }
             macList.add(Mac.getInstance(defaultAlgorithm, p));
         }
         return macList.toArray(new Mac[macList.size()]);
@@ -845,6 +851,13 @@
         byte[] output = null;
         byte[] output2 = null;
         for (int i = 0; i < providers.length; i++) {
+            // Do not test AndroidKeyStore's Mac. It cannot be initialized without providing an
+            // AndroidKeyStore-backed SecretKey instance. It's OKish not to test here because it's
+            // tested by cts/tests/test/keystore.
+            if ("AndroidKeyStore".equals(providers[i].getName())) {
+                continue;
+            }
+
             System.out.println("provider = " + providers[i].getName());
             Mac mac = Mac.getInstance("HmacMD5", providers[i]);
             mac.init(key);
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index a55b47a..9aab942 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -394,6 +394,12 @@
             provide("Signature", "NONEwithRSA");
             provide("Cipher", "RSA/ECB/NOPADDING");
             provide("Cipher", "RSA/ECB/PKCS1PADDING");
+            provide("SecretKeyFactory", "AES");
+            provide("SecretKeyFactory", "HmacSHA1");
+            provide("SecretKeyFactory", "HmacSHA224");
+            provide("SecretKeyFactory", "HmacSHA256");
+            provide("SecretKeyFactory", "HmacSHA384");
+            provide("SecretKeyFactory", "HmacSHA512");
 
             // different names: ARCFOUR vs ARC4
             unprovide("Cipher", "ARCFOUR");